From: Rasmus Villemoes <linux@rasmusvillemoes.dk> [ Upstream commit 800cd6fb76f0ec7711deb72a86c924db1ae42648 ] There are a number of problems with cpm_muram_alloc() and its callers. Most callers assign the return value to some variable and then use IS_ERR_VALUE to check for allocation failure. However, when that variable is not sizeof(long), this leads to warnings - and it is indeed broken to do e.g. u32 foo = cpm_muram_alloc(); if (IS_ERR_VALUE(foo)) on a 64-bit platform, since the condition foo >= (unsigned long)-ENOMEM is tautologically false. There are also callers that ignore the possibility of error, and then there are those that check for error by comparing the return value to 0... One could fix that by changing all callers to store the return value temporarily in an "unsigned long" and test that. However, use of IS_ERR_VALUE() is error-prone and should be restricted to things which are inherently long-sized (stuff in pt_regs etc.). Instead, let's aim for changing to the standard kernel style int foo = cpm_muram_alloc(); if (foo < 0) deal_with_it() some->where = foo; Changing the return type from unsigned long to s32 (aka signed int) doesn't change the value that gets stored into any of the callers' variables except if the caller was storing the result in a u64 _and_ the allocation failed, so in itself this patch should be a no-op. Another problem with cpm_muram_alloc() is that it can certainly validly return 0 - and except if some cpm_muram_alloc_fixed() call interferes, the very first cpm_muram_alloc() call will return just that. But that shows that both ucc_slow_free() and ucc_fast_free() are buggy, since they assume that a value of 0 means "that field was never allocated". We'll later change cpm_muram_free() to accept (and ignore) a negative offset, so callers can use a sentinel of -1 instead of 0 and just unconditionally call cpm_muram_free(). Reviewed-by: Timur Tabi <timur@kernel.org> Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Li Yang <leoyang.li@nxp.com> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/soc/fsl/qe/qe_common.c | 29 ++++++++++++++++------------- include/soc/fsl/qe/qe.h | 16 ++++++++-------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index 104e68d9b84f2..4f60724b06b7c 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -35,7 +35,7 @@ static phys_addr_t muram_pbase; struct muram_block { struct list_head head; - unsigned long start; + s32 start; int size; }; @@ -113,13 +113,14 @@ int cpm_muram_init(void) * @algo: algorithm for alloc. * @data: data for genalloc's algorithm. * - * This function returns an offset into the muram area. + * This function returns a non-negative offset into the muram area, or + * a negative errno on failure. */ -static unsigned long cpm_muram_alloc_common(unsigned long size, - genpool_algo_t algo, void *data) +static s32 cpm_muram_alloc_common(unsigned long size, + genpool_algo_t algo, void *data) { struct muram_block *entry; - unsigned long start; + s32 start; if (!muram_pool && cpm_muram_init()) goto out2; @@ -140,7 +141,7 @@ static unsigned long cpm_muram_alloc_common(unsigned long size, out1: gen_pool_free(muram_pool, start, size); out2: - return (unsigned long)-ENOMEM; + return -ENOMEM; } /* @@ -148,13 +149,14 @@ static unsigned long cpm_muram_alloc_common(unsigned long size, * @size: number of bytes to allocate * @align: requested alignment, in bytes * - * This function returns an offset into the muram area. + * This function returns a non-negative offset into the muram area, or + * a negative errno on failure. * Use cpm_dpram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ -unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) +s32 cpm_muram_alloc(unsigned long size, unsigned long align) { - unsigned long start; + s32 start; unsigned long flags; struct genpool_data_align muram_pool_data; @@ -171,7 +173,7 @@ EXPORT_SYMBOL(cpm_muram_alloc); * cpm_muram_free - free a chunk of multi-user ram * @offset: The beginning of the chunk as returned by cpm_muram_alloc(). */ -int cpm_muram_free(unsigned long offset) +int cpm_muram_free(s32 offset) { unsigned long flags; int size; @@ -197,13 +199,14 @@ EXPORT_SYMBOL(cpm_muram_free); * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram * @offset: offset of allocation start address * @size: number of bytes to allocate - * This function returns an offset into the muram area + * This function returns @offset if the area was available, a negative + * errno otherwise. * Use cpm_dpram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ -unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) +s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) { - unsigned long start; + s32 start; unsigned long flags; struct genpool_data_fixed muram_pool_data_fixed; diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index b3d1aff5e8ad5..deb6238416947 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -102,26 +102,26 @@ static inline void qe_reset(void) {} int cpm_muram_init(void); #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) -unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); -int cpm_muram_free(unsigned long offset); -unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); +s32 cpm_muram_alloc(unsigned long size, unsigned long align); +int cpm_muram_free(s32 offset); +s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); dma_addr_t cpm_muram_dma(void __iomem *addr); #else -static inline unsigned long cpm_muram_alloc(unsigned long size, - unsigned long align) +static inline s32 cpm_muram_alloc(unsigned long size, + unsigned long align) { return -ENOSYS; } -static inline int cpm_muram_free(unsigned long offset) +static inline int cpm_muram_free(s32 offset) { return -ENOSYS; } -static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset, - unsigned long size) +static inline s32 cpm_muram_alloc_fixed(unsigned long offset, + unsigned long size) { return -ENOSYS; } -- 2.20.1
From: Oliver O'Halloran <oohall@gmail.com> [ Upstream commit 3b5b9997b331e77ce967eba2c4bc80dc3134a7fe ] On pseries there is a bug with adding hotplugged devices to an IOMMU group. For a number of dumb reasons fixing that bug first requires re-working how VFs are configured on PowerNV. For background, on PowerNV we use the pcibios_sriov_enable() hook to do two things: 1. Create a pci_dn structure for each of the VFs, and 2. Configure the PHB's internal BARs so the MMIO range for each VF maps to a unique PE. Roughly speaking a PE is the hardware counterpart to a Linux IOMMU group since all the devices in a PE share the same IOMMU table. A PE also defines the set of devices that should be isolated in response to a PCI error (i.e. bad DMA, UR/CA, AER events, etc). When isolated all MMIO and DMA traffic to and from devicein the PE is blocked by the root complex until the PE is recovered by the OS. The requirement to block MMIO causes a giant headache because the P8 PHB generally uses a fixed mapping between MMIO addresses and PEs. As a result we need to delay configuring the IOMMU groups for device until after MMIO resources are assigned. For physical devices (i.e. non-VFs) the PE assignment is done in pcibios_setup_bridge() which is called immediately after the MMIO resources for downstream devices (and the bridge's windows) are assigned. For VFs the setup is more complicated because: a) pcibios_setup_bridge() is not called again when VFs are activated, and b) The pci_dev for VFs are created by generic code which runs after pcibios_sriov_enable() is called. The work around for this is a two step process: 1. A fixup in pcibios_add_device() is used to initialised the cached pe_number in pci_dn, then 2. A bus notifier then adds the device to the IOMMU group for the PE specified in pci_dn->pe_number. A side effect fixing the pseries bug mentioned in the first paragraph is moving the fixup out of pcibios_add_device() and into pcibios_bus_add_device(), which is called much later. This results in step 2. failing because pci_dn->pe_number won't be initialised when the bus notifier is run. We can fix this by removing the need for the fixup. The PE for a VF is known before the VF is even scanned so we can initialise pci_dn->pe_number pcibios_sriov_enable() instead. Unfortunately, moving the initialisation causes two problems: 1. We trip the WARN_ON() in the current fixup code, and 2. The EEH core clears pdn->pe_number when recovering a VF and relies on the fixup to correctly re-set it. The only justification for either of these is a comment in eeh_rmv_device() suggesting that pdn->pe_number *must* be set to IODA_INVALID_PE in order for the VF to be scanned. However, this comment appears to have no basis in reality. Both bugs can be fixed by just deleting the code. Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20191028085424.12006-1-oohall@gmail.com Signed-off-by: Sasha Levin <sashal@kernel.org> --- arch/powerpc/kernel/eeh_driver.c | 6 ------ arch/powerpc/platforms/powernv/pci-ioda.c | 19 +++++++++++++++---- arch/powerpc/platforms/powernv/pci.c | 4 ---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 470284f9e4f66..5a48c93aaa1b3 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -520,12 +520,6 @@ static void *eeh_rmv_device(void *data, void *userdata) pci_iov_remove_virtfn(edev->physfn, pdn->vf_index, 0); edev->pdev = NULL; - - /* - * We have to set the VF PE number to invalid one, which is - * required to plug the VF successfully. - */ - pdn->pe_number = IODA_INVALID_PE; #endif if (rmv_data) list_add(&edev->rmv_list, &rmv_data->edev_list); diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index d3d5796f7df60..36ef504eeab32 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1523,6 +1523,10 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) /* Reserve PE for each VF */ for (vf_index = 0; vf_index < num_vfs; vf_index++) { + int vf_devfn = pci_iov_virtfn_devfn(pdev, vf_index); + int vf_bus = pci_iov_virtfn_bus(pdev, vf_index); + struct pci_dn *vf_pdn; + if (pdn->m64_single_mode) pe_num = pdn->pe_num_map[vf_index]; else @@ -1535,13 +1539,11 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) pe->pbus = NULL; pe->parent_dev = pdev; pe->mve_number = -1; - pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) | - pci_iov_virtfn_devfn(pdev, vf_index); + pe->rid = (vf_bus << 8) | vf_devfn; pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%x\n", hose->global_number, pdev->bus->number, - PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)), - PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)), pe_num); + PCI_SLOT(vf_devfn), PCI_FUNC(vf_devfn), pe_num); if (pnv_ioda_configure_pe(phb, pe)) { /* XXX What do we do here ? */ @@ -1555,6 +1557,15 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) list_add_tail(&pe->list, &phb->ioda.pe_list); mutex_unlock(&phb->ioda.pe_list_mutex); + /* associate this pe to it's pdn */ + list_for_each_entry(vf_pdn, &pdn->parent->child_list, list) { + if (vf_pdn->busno == vf_bus && + vf_pdn->devfn == vf_devfn) { + vf_pdn->pe_number = pe_num; + break; + } + } + pnv_pci_ioda2_setup_dma_pe(phb, pe); } } diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 961c131a5b7e8..844ca1886063b 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -978,16 +978,12 @@ void pnv_pci_dma_dev_setup(struct pci_dev *pdev) struct pnv_phb *phb = hose->private_data; #ifdef CONFIG_PCI_IOV struct pnv_ioda_pe *pe; - struct pci_dn *pdn; /* Fix the VF pdn PE number */ if (pdev->is_virtfn) { - pdn = pci_get_pdn(pdev); - WARN_ON(pdn->pe_number != IODA_INVALID_PE); list_for_each_entry(pe, &phb->ioda.pe_list, list) { if (pe->rid == ((pdev->bus->number << 8) | (pdev->devfn & 0xff))) { - pdn->pe_number = pe->pe_number; pe->pdev = pdev; break; } -- 2.20.1
From: Tyrel Datwyler <tyreld@linux.vnet.ibm.com> [ Upstream commit aff8c8242bc638ba57247ae1ec5f272ac3ed3b92 ] Commit e5afdf9dd515 ("powerpc/vfio_spapr_tce: Add reference counting to iommu_table") missed an iommu_table allocation in the pseries vio code. The iommu_table is allocated with kzalloc and as a result the associated kref gets a value of zero. This has the side effect that during a DLPAR remove of the associated virtual IOA the iommu_tce_table_put() triggers a use-after-free underflow warning. Call Trace: [c0000002879e39f0] [c00000000071ecb4] refcount_warn_saturate+0x184/0x190 (unreliable) [c0000002879e3a50] [c0000000000500ac] iommu_tce_table_put+0x9c/0xb0 [c0000002879e3a70] [c0000000000f54e4] vio_dev_release+0x34/0x70 [c0000002879e3aa0] [c00000000087cfa4] device_release+0x54/0xf0 [c0000002879e3b10] [c000000000d64c84] kobject_cleanup+0xa4/0x240 [c0000002879e3b90] [c00000000087d358] put_device+0x28/0x40 [c0000002879e3bb0] [c0000000007a328c] dlpar_remove_slot+0x15c/0x250 [c0000002879e3c50] [c0000000007a348c] remove_slot_store+0xac/0xf0 [c0000002879e3cd0] [c000000000d64220] kobj_attr_store+0x30/0x60 [c0000002879e3cf0] [c0000000004ff13c] sysfs_kf_write+0x6c/0xa0 [c0000002879e3d10] [c0000000004fde4c] kernfs_fop_write+0x18c/0x260 [c0000002879e3d60] [c000000000410f3c] __vfs_write+0x3c/0x70 [c0000002879e3d80] [c000000000415408] vfs_write+0xc8/0x250 [c0000002879e3dd0] [c0000000004157dc] ksys_write+0x7c/0x120 [c0000002879e3e20] [c00000000000b278] system_call+0x5c/0x68 Further, since the refcount was always zero the iommu_tce_table_put() fails to call the iommu_table release function resulting in a leak. Fix this issue be initilizing the iommu_table kref immediately after allocation. Fixes: e5afdf9dd515 ("powerpc/vfio_spapr_tce: Add reference counting to iommu_table") Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/1579558202-26052-1-git-send-email-tyreld@linux.ibm.com Signed-off-by: Sasha Levin <sashal@kernel.org> --- arch/powerpc/platforms/pseries/vio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index d86938260a867..fc778865a4124 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -1195,6 +1195,8 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) if (tbl == NULL) return NULL; + kref_init(&tbl->it_kref); + of_parse_dma_window(dev->dev.of_node, dma_window, &tbl->it_index, &offset, &size); -- 2.20.1
From: Rasmus Villemoes <linux@rasmusvillemoes.dk> [ Upstream commit 148587a59f6b85831695e0497d9dd1af5f0495af ] Qiang Zhao points out that these offsets get written to 16-bit registers, and there are some QE platforms with more than 64K muram. So it is possible that qe_muram_alloc() gives us an allocation that can't actually be used by the hardware, so detect and reject that. Reported-by: Qiang Zhao <qiang.zhao@nxp.com> Reviewed-by: Timur Tabi <timur@kernel.org> Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Li Yang <leoyang.li@nxp.com> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/net/wan/fsl_ucc_hdlc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 571a1ff8f81f2..6a26cef621935 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -240,6 +240,11 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) ret = -ENOMEM; goto free_riptr; } + if (riptr != (u16)riptr || tiptr != (u16)tiptr) { + dev_err(priv->dev, "MURAM allocation out of addressable range\n"); + ret = -ENOMEM; + goto free_tiptr; + } /* Set RIPTR, TIPTR */ iowrite16be(riptr, &priv->ucc_pram->riptr); -- 2.20.1
From: Chen Zhou <chenzhou10@huawei.com> [ Upstream commit 270fe2ceda66b6964d4c6f261d7f562a02c1c786 ] Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wan/fsl_ucc_hdlc.c: In function ucc_hdlc_irq_handler: drivers/net/wan/fsl_ucc_hdlc.c:643:23: warning: variable ut_info set but not used [-Wunused-but-set-variable] drivers/net/wan/fsl_ucc_hdlc.c: In function uhdlc_suspend: drivers/net/wan/fsl_ucc_hdlc.c:880:23: warning: variable ut_info set but not used [-Wunused-but-set-variable] drivers/net/wan/fsl_ucc_hdlc.c: In function uhdlc_resume: drivers/net/wan/fsl_ucc_hdlc.c:925:6: warning: variable ret set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Chen Zhou <chenzhou10@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/net/wan/fsl_ucc_hdlc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 6a26cef621935..c1e613e2c72c8 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -592,11 +592,9 @@ static irqreturn_t ucc_hdlc_irq_handler(int irq, void *dev_id) struct ucc_hdlc_private *priv = (struct ucc_hdlc_private *)dev_id; struct net_device *dev = priv->ndev; struct ucc_fast_private *uccf; - struct ucc_tdm_info *ut_info; u32 ucce; u32 uccm; - ut_info = priv->ut_info; uccf = priv->uccf; ucce = ioread32be(uccf->p_ucce); @@ -826,7 +824,6 @@ static void resume_clk_config(struct ucc_hdlc_private *priv) static int uhdlc_suspend(struct device *dev) { struct ucc_hdlc_private *priv = dev_get_drvdata(dev); - struct ucc_tdm_info *ut_info; struct ucc_fast __iomem *uf_regs; if (!priv) @@ -838,7 +835,6 @@ static int uhdlc_suspend(struct device *dev) netif_device_detach(priv->ndev); napi_disable(&priv->napi); - ut_info = priv->ut_info; uf_regs = priv->uf_regs; /* backup gumr guemr*/ @@ -871,7 +867,7 @@ static int uhdlc_resume(struct device *dev) struct ucc_fast __iomem *uf_regs; struct ucc_fast_private *uccf; struct ucc_fast_info *uf_info; - int ret, i; + int i; u32 cecr_subblock; u16 bd_status; @@ -916,16 +912,16 @@ static int uhdlc_resume(struct device *dev) /* Write to QE CECR, UCCx channel to Stop Transmission */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); - ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock, - (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0); + qe_issue_cmd(QE_STOP_TX, cecr_subblock, + (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0); /* Set UPSMR normal mode */ iowrite32be(0, &uf_regs->upsmr); /* init parameter base */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); - ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock, - QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset); + qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock, + QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset); priv->ucc_pram = (struct ucc_hdlc_param __iomem *) qe_muram_addr(priv->ucc_pram_offset); -- 2.20.1
From: YueHaibing <yuehaibing@huawei.com> [ Upstream commit 6e62bd36e9ad85a22d92b1adce6a0336ea549733 ] drivers/soc/fsl/qe/gpio.c: In function qe_pin_request: drivers/soc/fsl/qe/gpio.c:163:26: warning: variable mm_gc set but not used [-Wunused-but-set-variable] commit 1e714e54b5ca ("powerpc: qe_lib-gpio: use gpiochip data pointer") left behind this unused variable. Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Chen Zhou <chenzhou10@huawei.com> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Li Yang <leoyang.li@nxp.com> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/soc/fsl/qe/gpio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 5cbc5ce5ac159..38643e84f355a 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -137,7 +137,6 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) { struct qe_pin *qe_pin; struct gpio_chip *gc; - struct of_mm_gpio_chip *mm_gc; struct qe_gpio_chip *qe_gc; int err; unsigned long flags; @@ -163,7 +162,6 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) goto err0; } - mm_gc = to_of_mm_gpio_chip(gc); qe_gc = gpiochip_get_data(gc); spin_lock_irqsave(&qe_gc->lock, flags); -- 2.20.1
From: Wang Hai <wanghai38@huawei.com> [ Upstream commit 98949a1946d70771789def0c9dbc239497f9f138 ] Fix the following gcc warning: drivers/ide/pmac.c: In function pmac_ide_setup_device: drivers/ide/pmac.c:1027:14: warning: variable hwif set but not used [-Wunused-but-set-variable] Fixes: d58b0c39e32f ("powerpc/macio: Rework hotplug media bay support") Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Wang Hai <wanghai38@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/ide/pmac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 203ed4adc04ae..7db083ec5ee06 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -1024,7 +1024,6 @@ static int pmac_ide_setup_device(pmac_ide_hwif_t *pmif, struct ide_hw *hw) struct device_node *np = pmif->node; const int *bidp; struct ide_host *host; - ide_hwif_t *hwif; struct ide_hw *hws[] = { hw }; struct ide_port_info d = pmac_port_info; int rc; @@ -1080,7 +1079,7 @@ static int pmac_ide_setup_device(pmac_ide_hwif_t *pmif, struct ide_hw *hw) rc = -ENOMEM; goto bail; } - hwif = pmif->hwif = host->ports[0]; + pmif->hwif = host->ports[0]; if (on_media_bay(pmif)) { /* Fixup bus ID for media bay */ -- 2.20.1
From: Oliver O'Halloran <oohall@gmail.com> [ Upstream commit 1fb4124ca9d456656a324f1ee29b7bf942f59ac8 ] When disabling virtual functions on an SR-IOV adapter we currently do not correctly remove the EEH state for the now-dead virtual functions. When removing the pci_dn that was created for the VF when SR-IOV was enabled we free the corresponding eeh_dev without removing it from the child device list of the eeh_pe that contained it. This can result in crashes due to the use-after-free. Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Reviewed-by: Sam Bobroff <sbobroff@linux.ibm.com> Tested-by: Sam Bobroff <sbobroff@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20190821062655.19735-1-oohall@gmail.com Signed-off-by: Sasha Levin <sashal@kernel.org> --- arch/powerpc/kernel/pci_dn.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 0e395afbf0f49..0e45a446a8c78 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -261,9 +261,22 @@ void remove_dev_pci_data(struct pci_dev *pdev) continue; #ifdef CONFIG_EEH - /* Release EEH device for the VF */ + /* + * Release EEH state for this VF. The PCI core + * has already torn down the pci_dev for this VF, but + * we're responsible to removing the eeh_dev since it + * has the same lifetime as the pci_dn that spawned it. + */ edev = pdn_to_eeh_dev(pdn); if (edev) { + /* + * We allocate pci_dn's for the totalvfs count, + * but only only the vfs that were activated + * have a configured PE. + */ + if (edev->pe) + eeh_rmv_from_parent_pe(edev); + pdn->edev = NULL; kfree(edev); } -- 2.20.1