* [PATCH net-next v2 1/8] net: 3com: 3c59x: Use dev_get_drvdata
From: Chuhong Yuan @ 2019-07-24 6:05 UTC (permalink / raw)
Cc: Steffen Klassert, David S . Miller, netdev, linux-kernel,
Chuhong Yuan
Instead of using to_pci_dev + pci_get_drvdata,
use dev_get_drvdata to make code simpler.
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
---
Changes in v2:
- Change pci_set_drvdata to dev_set_drvdata
to keep consistency.
drivers/net/ethernet/3com/3c59x.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 147051404194..a0960c05833d 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -847,8 +847,7 @@ static void poll_vortex(struct net_device *dev)
static int vortex_suspend(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
+ struct net_device *ndev = dev_get_drvdata(dev);
if (!ndev || !netif_running(ndev))
return 0;
@@ -861,8 +860,7 @@ static int vortex_suspend(struct device *dev)
static int vortex_resume(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
+ struct net_device *ndev = dev_get_drvdata(dev);
int err;
if (!ndev || !netif_running(ndev))
@@ -1222,7 +1220,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
/* if we are a PCI driver, we store info in pdev->driver_data
* instead of a module list */
if (pdev)
- pci_set_drvdata(pdev, dev);
+ dev_set_drvdata(&pdev->dev, dev);
if (edev)
eisa_set_drvdata(edev, dev);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next v2 0/8] Use dev_get_drvdata where possible
From: Chuhong Yuan @ 2019-07-24 6:05 UTC (permalink / raw)
Cc: Steffen Klassert, David S . Miller, Jay Cliburn, Chris Snook,
Rasesh Mody, Michael Chan, Siva Reddy Kallam, Prashant Sreedharan,
GR-Linux-NIC-Dev, Jeff Kirsher, Guo-Fu Tseng, intel-wired-lan,
netdev, linux-kernel, Chuhong Yuan
These patches use dev_get_drvdata instead of
using to_pci_dev + pci_get_drvdata to make
code simpler where possible.
Changelog:
v1 -> v2:
- Change pci_set_drvdata to dev_set_drvdata
to keep consistency.
Chuhong Yuan (8):
net: 3com: 3c59x: Use dev_get_drvdata
net: atheros: Use dev_get_drvdata
net: broadcom: Use dev_get_drvdata
e1000e: Use dev_get_drvdata where possible
fm10k: Use dev_get_drvdata
i40e: Use dev_get_drvdata
igb: Use dev_get_drvdata where possible
net: jme: Use dev_get_drvdata
drivers/net/ethernet/3com/3c59x.c | 8 +++-----
drivers/net/ethernet/atheros/alx/main.c | 8 +++-----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 10 ++++------
drivers/net/ethernet/atheros/atlx/atl1.c | 8 +++-----
drivers/net/ethernet/broadcom/bnx2.c | 8 +++-----
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 +++-----
drivers/net/ethernet/broadcom/tg3.c | 8 +++-----
drivers/net/ethernet/intel/e1000e/netdev.c | 9 ++++-----
drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 6 +++---
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++------
drivers/net/ethernet/intel/igb/igb_main.c | 5 ++---
drivers/net/ethernet/jme.c | 8 +++-----
12 files changed, 38 insertions(+), 58 deletions(-)
--
2.20.1
^ permalink raw reply
* Re: [PATCH v2] drivers: net: xgene: Remove acpi_has_method() calls
From: Kelsey Skunberg @ 2019-07-24 5:56 UTC (permalink / raw)
To: David Miller
Cc: iyappan, keyur, quan, netdev, linux-kernel, bjorn, skhan,
linux-kernel-mentees
In-Reply-To: <20190723.140739.379654507424022463.davem@davemloft.net>
On Tue, Jul 23, 2019 at 02:07:39PM -0700, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Tue, 23 Jul 2019 14:06:46 -0700 (PDT)
>
> > From: Kelsey Skunberg <skunberg.kelsey@gmail.com>
> > Date: Tue, 23 Jul 2019 12:58:11 -0600
> >
> >> acpi_evaluate_object will already return an error if the needed method
> >> does not exist. Remove unnecessary acpi_has_method() calls and check the
> >> returned acpi_status for failure instead.
> >>
> >> Signed-off-by: Kelsey Skunberg <skunberg.kelsey@gmail.com>
> >> ---
> >> Changes in v2:
> >> - Fixed white space warnings and errors
> >
> > Applied to net-next.
>
> Wow did you even build test this? Reverted...
>
This patch has definitely been a mess, so thank you for your time and
sticking with me here. I thought my build tests included these files,
though discovered they did not. Since submitting v2, I was able to reproduce the
same errors you listed and corrected the problem in v3.
I also realized my .git/post-commit file needed to be fixed, so the white
space problem in v1 should also not be a problem in the future.
Please let me know if you notice anything else I can improve on. I will
learn from my mistakes and really appreciate advice. Thank you again, David.
Best Regards,
Kelsey
^ permalink raw reply
* Re: kernel v5.3.0-rc1
From: Heiner Kallweit @ 2019-07-24 5:48 UTC (permalink / raw)
To: Bob Gleitsmann, netdev
In-Reply-To: <ed5c39e4-e364-ccca-0a9e-8d0b4d648bfd@bellsouth.net>
On 24.07.2019 03:38, Bob Gleitsmann wrote:
> Hello,
>
>
> I had problems with network functionality in kernel v5.3.0-rc1. I was
> not able to ping local devices with ip address or internet points by
> name. I have been testing git kernels for a while and this is the first
> time this has happened, i.e., it didn't happen with v5.2.0. One
> interesting thing is that simply rebooting with a good kernel doesn't
> fix the problem. The machine has to be powered off and restarted.
>
> It was clear that network names were not being resolved.
>
> I can provide more details and try different things to help track down
> the problem. I'm using x86-64 system, gentoo linux, r8169 PHY.
>
Thanks for reporting. For one known issue there's a fix pending for 5.3-rc2:
1a03bb532934 ("r8169: fix RTL8168g PHY init")
You could apply it on top of 5.3-rc1 or test linux-next.
If this doesn't help then at least a full dmesg log is needed.
>
> Best Wishes,
>
>
> Bob Gleitsmann
>
>
Heiner
^ permalink raw reply
* Re: [PATCH] mt76_init_sband_2g: null check the allocation
From: Kalle Valo @ 2019-07-24 5:39 UTC (permalink / raw)
To: Navid Emamdoost
Cc: emamd001, kjlu, smccaman, secalert, Jakub Kicinski,
David S. Miller, Matthias Brugger, linux-wireless, netdev,
linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <20190723221954.9233-1-navid.emamdoost@gmail.com>
Navid Emamdoost <navid.emamdoost@gmail.com> writes:
> devm_kzalloc may fail and return NULL. So the null check is needed.
>
> Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
> ---
> drivers/net/wireless/mediatek/mt7601u/init.c | 3 +++
> 1 file changed, 3 insertions(+)
The prefix in the title should be "mt7601u:".
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#commit_title_is_wrong
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 03/12] block: bio_release_pages: use flags arg instead of bool
From: Christoph Hellwig @ 2019-07-24 5:30 UTC (permalink / raw)
To: john.hubbard
Cc: Andrew Morton, Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization, John Hubbard,
Christoph Hellwig, Jérôme Glisse, Minwoo Im
In-Reply-To: <20190724042518.14363-4-jhubbard@nvidia.com>
On Tue, Jul 23, 2019 at 09:25:09PM -0700, john.hubbard@gmail.com wrote:
> From: John Hubbard <jhubbard@nvidia.com>
>
> In commit d241a95f3514 ("block: optionally mark pages dirty in
> bio_release_pages"), new "bool mark_dirty" argument was added to
> bio_release_pages.
>
> In upcoming work, another bool argument (to indicate that the pages came
> from get_user_pages) is going to be added. That's one bool too many,
> because it's not desirable have calls of the form:
All pages releases by bio_release_pages should come from
get_get_user_pages, so I don't really see the point here.
^ permalink raw reply
* Re: [PATCH V2 1/1] can: sja1000: f81601: add Fintek F81601 support
From: Ji-Ze Hong (Peter Hong) @ 2019-07-24 5:19 UTC (permalink / raw)
To: Saeed Mahameed, peter_hong@fintek.com.tw, wg@grandegger.com,
mkl@pengutronix.de
Cc: hpeter+linux_kernel@gmail.com, f.suligoi@asem.it,
linux-can@vger.kernel.org, davem@davemloft.net,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org
In-Reply-To: <bb38703fa94f19578ac67f763bb1a0ad34196757.camel@mellanox.com>
Hi,
Saeed Mahameed 於 2019/7/24 上午 05:38 寫道:
> On Mon, 2019-07-22 at 14:22 +0800, Ji-Ze Hong (Peter Hong) wrote:
>> This patch add support for Fintek PCIE to 2 CAN controller support
>>
>> Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com
>>>
>> ---
>> Changelog:
>> v2:
>> 1: Fix comment on the spinlock with write access.
>> 2: Use ARRAY_SIZE instead of F81601_PCI_MAX_CHAN.
>> 3: Check the strap pin outside the loop.
>> 4: Fix the cleanup issue in f81601_pci_add_card().
>> 5: Remove unused "channels" in struct f81601_pci_card.
>>
>> drivers/net/can/sja1000/Kconfig | 8 ++
>> drivers/net/can/sja1000/Makefile | 1 +
>> drivers/net/can/sja1000/f81601.c | 215
>> +++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 224 insertions(+)
>> create mode 100644 drivers/net/can/sja1000/f81601.c
>>
>> diff --git a/drivers/net/can/sja1000/Kconfig
>> b/drivers/net/can/sja1000/Kconfig
>> index f6dc89927ece..8588323c5138 100644
>> --- a/drivers/net/can/sja1000/Kconfig
>> +++ b/drivers/net/can/sja1000/Kconfig
>> @@ -101,4 +101,12 @@ config CAN_TSCAN1
>> IRQ numbers are read from jumpers JP4 and JP5,
>> SJA1000 IO base addresses are chosen heuristically (first
>> that works).
>>
>> +config CAN_F81601
>> + tristate "Fintek F81601 PCIE to 2 CAN Controller"
>> + depends on PCI
>> + help
>> + This driver adds support for Fintek F81601 PCIE to 2 CAN
>> Controller.
>> + It had internal 24MHz clock source, but it can be changed by
>> + manufacturer. We can use modinfo to get usage for parameters.
>> + Visit http://www.fintek.com.tw to get more information.
>> endif
>> diff --git a/drivers/net/can/sja1000/Makefile
>> b/drivers/net/can/sja1000/Makefile
>> index 9253aaf9e739..6f6268543bd9 100644
>> --- a/drivers/net/can/sja1000/Makefile
>> +++ b/drivers/net/can/sja1000/Makefile
>> @@ -13,3 +13,4 @@ obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o
>> obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
>> obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
>> obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
>> +obj-$(CONFIG_CAN_F81601) += f81601.o
>> diff --git a/drivers/net/can/sja1000/f81601.c
>> b/drivers/net/can/sja1000/f81601.c
>> new file mode 100644
>> index 000000000000..3c378de8764d
>> --- /dev/null
>> +++ b/drivers/net/can/sja1000/f81601.c
>> @@ -0,0 +1,215 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Fintek F81601 PCIE to 2 CAN controller driver
>> + *
>> + * Copyright (C) 2019 Peter Hong <peter_hong@fintek.com.tw>
>> + * Copyright (C) 2019 Linux Foundation
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/netdevice.h>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/pci.h>
>> +#include <linux/can/dev.h>
>> +#include <linux/io.h>
>> +#include <linux/version.h>
>> +
>> +#include "sja1000.h"
>> +
>> +#define F81601_PCI_MAX_CHAN 2
>> +
>> +#define F81601_DECODE_REG 0x209
>> +#define F81601_IO_MODE BIT(7)
>> +#define F81601_MEM_MODE BIT(6)
>> +#define F81601_CFG_MODE BIT(5)
>> +#define F81601_CAN2_INTERNAL_CLK BIT(3)
>> +#define F81601_CAN1_INTERNAL_CLK BIT(2)
>> +#define F81601_CAN2_EN BIT(1)
>> +#define F81601_CAN1_EN BIT(0)
>> +
>> +#define F81601_TRAP_REG 0x20a
>> +#define F81601_CAN2_HAS_EN BIT(4)
>> +
>> +struct f81601_pci_card {
>> + void __iomem *addr;
>> + spinlock_t lock; /* use this spin lock only for write access
>> */
>> + struct pci_dev *dev;
>> + struct net_device *net_dev[F81601_PCI_MAX_CHAN];
>> +};
>> +
>> +static const struct pci_device_id f81601_pci_tbl[] = {
>> + { PCI_DEVICE(0x1c29, 0x1703) },
>> + {},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(pci, f81601_pci_tbl);
>> +
>> +static bool internal_clk = 1;
>> +module_param(internal_clk, bool, 0444);
>> +MODULE_PARM_DESC(internal_clk, "Use internal clock, default 1
>> (24MHz)");
>> +
>> +static unsigned int external_clk;
>> +module_param(external_clk, uint, 0444);
>> +MODULE_PARM_DESC(external_clk, "External Clock, must spec when
>> internal_clk = 0");
>> +
>> +static u8 f81601_pci_read_reg(const struct sja1000_priv *priv, int
>> port)
>> +{
>> + return readb(priv->reg_base + port);
>> +}
>> +
>> +static void f81601_pci_write_reg(const struct sja1000_priv *priv,
>> int port,
>> + u8 val)
>> +{
>> + struct f81601_pci_card *card = priv->priv;
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&card->lock, flags);
>> + writeb(val, priv->reg_base + port);
>> + readb(priv->reg_base);
>> + spin_unlock_irqrestore(&card->lock, flags);
>> +}
>> +
>> +static void f81601_pci_del_card(struct pci_dev *pdev)
>> +{
>> + struct f81601_pci_card *card = pci_get_drvdata(pdev);
>> + struct net_device *dev;
>> + int i = 0;
>> +
>> + for (i = 0; i < ARRAY_SIZE(card->net_dev); i++) {
>> + dev = card->net_dev[i];
>> + if (!dev)
>> + continue;
>> +
>> + dev_info(&pdev->dev, "%s: Removing %s\n", __func__,
>> dev->name);
>> +
>> + unregister_sja1000dev(dev);
>> + free_sja1000dev(dev);
>> + }
>> +
>> + pcim_iounmap(pdev, card->addr);
>> +}
>> +
>> +/* Probe F81601 based device for the SJA1000 chips and register each
>> + * available CAN channel to SJA1000 Socket-CAN subsystem.
>> + */
>> +static int f81601_pci_add_card(struct pci_dev *pdev,
>> + const struct pci_device_id *ent)
>> +{
>> + struct sja1000_priv *priv;
>> + struct net_device *dev;
>> + struct f81601_pci_card *card;
>
> nit, reverse xmas tree.
>
>> + int err, i, count;
>> + u8 tmp;
>> +
>> + if (pcim_enable_device(pdev) < 0) {
>> + dev_err(&pdev->dev, "Failed to enable PCI device\n");
>> + return -ENODEV;
>> + }
>> +
>> + dev_info(&pdev->dev, "Detected card at slot #%i\n",
>> + PCI_SLOT(pdev->devfn));
>> +
>> + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
>> + if (!card)
>> + return -ENOMEM;
>> +
>> + card->dev = pdev;
>> + spin_lock_init(&card->lock);
>> +
>> + pci_set_drvdata(pdev, card);
>> +
>> + tmp = F81601_IO_MODE | F81601_MEM_MODE | F81601_CFG_MODE |
>> + F81601_CAN2_EN | F81601_CAN1_EN;
>> +
>> + if (internal_clk) {
>> + tmp |= F81601_CAN2_INTERNAL_CLK |
>> F81601_CAN1_INTERNAL_CLK;
>> +
>> + dev_info(&pdev->dev,
>> + "F81601 running with internal clock:
>> 24Mhz\n");
>> + } else {
>> + dev_info(&pdev->dev,
>> + "F81601 running with external clock: %dMhz\n",
>> + external_clk / 1000000);
>> + }
>> +
>> + pci_write_config_byte(pdev, F81601_DECODE_REG, tmp);
>> +
>> + card->addr = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
>> +
>> + if (!card->addr) {
>> + err = -ENOMEM;
>> + dev_err(&pdev->dev, "%s: Failed to remap BAR\n",
>> __func__);
>> + goto failure_cleanup;
>> + }
>> +
>> + /* read CAN2_HW_EN strap pin to detect how many CANBUS do we
>> have */
>> + count = ARRAY_SIZE(card->net_dev);
>> + pci_read_config_byte(pdev, F81601_TRAP_REG, &tmp);
>> + if (!(tmp & F81601_CAN2_HAS_EN))
>> + count = 1;
>> +
>> + /* Detect available channels */
>> + for (i = 0; i < count; i++) {
>> + dev = alloc_sja1000dev(0);
>> + if (!dev) {
>> + err = -ENOMEM;
>> + goto failure_cleanup;
>> + }
>> +
>
> don't you need to rollback and cleanup/unregister previously allocated
> devs ?
>
I'll do cleanup when errors jump to failure_cleanup label and do
f81601_pci_del_card().
>> + priv = netdev_priv(dev);
>> + priv->priv = card;
>> + priv->irq_flags = IRQF_SHARED;
>> + priv->reg_base = card->addr + 0x80 * i;
>> + priv->read_reg = f81601_pci_read_reg;
>> + priv->write_reg = f81601_pci_write_reg;
>> +
>> + if (internal_clk)
>> + priv->can.clock.freq = 24000000 / 2;
>> + else
>> + priv->can.clock.freq = external_clk / 2;
>> +
>> + priv->ocr = OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL;
>> + priv->cdr = CDR_CBP;
>> +
>> + SET_NETDEV_DEV(dev, &pdev->dev);
>> + dev->dev_id = i;
>> + dev->irq = pdev->irq;
>> +
>> + /* Register SJA1000 device */
>> + err = register_sja1000dev(dev);
>> + if (err) {
>> + dev_err(&pdev->dev,
>> + "%s: Registering device failed: %x\n",
>> __func__,
>> + err);
>> + free_sja1000dev(dev);
>> + goto failure_cleanup;
>> + }
>> +
>> + card->net_dev[i] = dev;
>> + dev_info(&pdev->dev, "Channel #%d, %s at 0x%p, irq
>> %d\n", i,
>> + dev->name, priv->reg_base, dev->irq);
>> + }
>> +
>> + return 0;
>> +
>> +failure_cleanup:
>> + dev_err(&pdev->dev, "%s: failed: %d. Cleaning Up.\n", __func__,
>> err);
>> + f81601_pci_del_card(pdev);
--
With Best Regards,
Peter Hong
^ permalink raw reply
* Re: [PATCH] qca8k: enable port flow control
From: xiaofeis @ 2019-07-24 5:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: davem, vkoul, netdev, linux-arm-msm, bjorn.andersson,
vivien.didelot, f.fainelli, niklas.cassel, xiazha
In-Reply-To: <20190719131306.GA24930@lunn.ch>
Hi Andrew
Thanks for your comments. I have sent a new patch based on net-next
tree.
Thanks
Xiaofeis
On 2019-07-19 21:13, Andrew Lunn wrote:
> On Fri, Jul 19, 2019 at 10:53:11AM +0800, xiaofeis wrote:
>> Set phy device advertising to enable MAC flow control.
>>
>> Change-Id: Ibf0f554b072fc73136ec9f7ffb90c20b25a4faae
>> Signed-off-by: Xiaofei Shen <xiaofeis@codeaurora.org>
>
> Hi Xiaofei
>
> What tree is this patch against? I don't think it is net-next. It
> actually looks to be an old tree. Please rebase to David Millers
> net-next. Patches to that tree are closed at the moment, due to the
> merge window. You can post an RFC, or wait until it opens again.
>
> Thanks
> Andrew
^ permalink raw reply
* [PATCH v2] net: dsa: qca8k: enable port flow control
From: xiaofeis @ 2019-07-24 5:02 UTC (permalink / raw)
To: davem
Cc: vkoul, netdev, andrew, linux-arm-msm, bjorn.andersson,
vivien.didelot, f.fainelli, niklas.cassel, xiazha, xiaofeis
Set phy device advertising to enable MAC flow control.
Signed-off-by: Xiaofei Shen <xiaofeis@codeaurora.org>
---
drivers/net/dsa/qca8k.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 232e8cc..c5ac426 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016 John Crispin <john@phrozen.org>
*/
@@ -935,6 +935,8 @@
qca8k_port_set_status(priv, port, 1);
priv->port_sts[port].enabled = 1;
+ phy->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/2] qed: Add API for flashing the nvm attributes.
From: Sudarsana Reddy Kalluru @ 2019-07-24 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, mkalderon, aelior
In-Reply-To: <20190724045141.27703-1-skalluru@marvell.com>
The patch adds driver interface for reading the NVM config request and
update the attributes on nvm config flash partition.
Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Signed-off-by: Ariel Elior <aelior@marvell.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 65 ++++++++++++++++++++++++++++++
include/linux/qed/qed_if.h | 1 +
2 files changed, 66 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 829dd60..54f00d2 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -67,6 +67,8 @@
#define QED_ROCE_QPS (8192)
#define QED_ROCE_DPIS (8)
#define QED_RDMA_SRQS QED_ROCE_QPS
+#define QED_NVM_CFG_SET_FLAGS 0xE
+#define QED_NVM_CFG_SET_PF_FLAGS 0x1E
static char version[] =
"QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n";
@@ -2227,6 +2229,66 @@ static int qed_nvm_flash_image_validate(struct qed_dev *cdev,
return 0;
}
+/* Binary file format -
+ * /----------------------------------------------------------------------\
+ * 0B | 0x5 [command index] |
+ * 4B | Entity ID | Reserved | Number of config attributes |
+ * 8B | Config ID | Length | Value |
+ * | |
+ * \----------------------------------------------------------------------/
+ * There can be several Cfg_id-Length-Value sets as specified by 'Number of...'.
+ * Entity ID - A non zero entity value for which the config need to be updated.
+ */
+static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ u8 entity_id, len, buf[32];
+ struct qed_ptt *ptt;
+ u16 cfg_id, count;
+ int rc = 0, i;
+ u32 flags;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ /* NVM CFG ID attribute header */
+ *data += 4;
+ entity_id = **data;
+ *data += 2;
+ count = *((u16 *)*data);
+ *data += 2;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "Read config ids: entity id %02x num _attrs = %0d\n",
+ entity_id, count);
+ /* NVM CFG ID attributes */
+ for (i = 0; i < count; i++) {
+ cfg_id = *((u16 *)*data);
+ *data += 2;
+ len = **data;
+ (*data)++;
+ memcpy(buf, *data, len);
+ *data += len;
+
+ flags = entity_id ? QED_NVM_CFG_SET_PF_FLAGS :
+ QED_NVM_CFG_SET_FLAGS;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "cfg_id = %d len = %d\n", cfg_id, len);
+ rc = qed_mcp_nvm_set_cfg(hwfn, ptt, cfg_id, entity_id, flags,
+ buf, len);
+ if (rc) {
+ DP_ERR(cdev, "Error %d configuring %d\n", rc, cfg_id);
+ break;
+ }
+ }
+
+ qed_ptt_release(hwfn, ptt);
+
+ return rc;
+}
+
static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
{
const struct firmware *image;
@@ -2268,6 +2330,9 @@ static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
rc = qed_nvm_flash_image_access(cdev, &data,
&check_resp);
break;
+ case QED_NVM_FLASH_CMD_NVM_CFG_ID:
+ rc = qed_nvm_flash_cfg_write(cdev, &data);
+ break;
default:
DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
rc = -EINVAL;
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index eef02e6..23805ea 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -804,6 +804,7 @@ enum qed_nvm_flash_cmd {
QED_NVM_FLASH_CMD_FILE_DATA = 0x2,
QED_NVM_FLASH_CMD_FILE_START = 0x3,
QED_NVM_FLASH_CMD_NVM_CHANGE = 0x4,
+ QED_NVM_FLASH_CMD_NVM_CFG_ID = 0x5,
QED_NVM_FLASH_CMD_NVM_MAX,
};
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 1/2] qed: Add APIs for NVM config attributes.
From: Sudarsana Reddy Kalluru @ 2019-07-24 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, mkalderon, aelior
In-Reply-To: <20190724045141.27703-1-skalluru@marvell.com>
The patch adds APIs for reading/configuring the NVM config attributes
using Management FW interfaces.
Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Signed-off-by: Ariel Elior <aelior@marvell.com>
---
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 17 ++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 64 +++++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 14 +++++++
3 files changed, 95 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index e054f6c..557a12e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12580,6 +12580,8 @@ struct public_drv_mb {
#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000
#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
#define DRV_MSG_CODE_S_TAG_UPDATE_ACK 0x3b000000
+#define DRV_MSG_CODE_GET_NVM_CFG_OPTION 0x003e0000
+#define DRV_MSG_CODE_SET_NVM_CFG_OPTION 0x003f0000
#define DRV_MSG_CODE_INITIATE_PF_FLR 0x02010000
#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
#define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000
@@ -12748,6 +12750,21 @@ struct public_drv_mb {
#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE 0x00000002
#define DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK 0x00010000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_SHIFT 0
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_MASK 0x0000FFFF
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_SHIFT 16
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_MASK 0x00010000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_SHIFT 17
+#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_MASK 0x00020000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_SHIFT 18
+#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_MASK 0x00040000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_SHIFT 19
+#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_MASK 0x00080000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_SHIFT 20
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_MASK 0x00100000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_SHIFT 24
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_MASK 0x0f000000
+
u32 fw_mb_header;
#define FW_MSG_CODE_MASK 0xffff0000
#define FW_MSG_CODE_UNSUPPORTED 0x00000000
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 758702c..573911a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -3750,3 +3750,67 @@ int qed_mcp_get_ppfid_bitmap(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
return 0;
}
+
+int qed_mcp_nvm_get_cfg(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ u16 option_id, u8 entity_id, u16 flags, u8 *p_buf,
+ u32 *p_len)
+{
+ u32 mb_param = 0, resp, param;
+ int rc;
+
+ QED_MFW_SET_FIELD(mb_param, DRV_MB_PARAM_NVM_CFG_OPTION_ID, option_id);
+ if (flags & QED_NVM_CFG_OPTION_INIT)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_INIT, 1);
+ if (flags & QED_NVM_CFG_OPTION_FREE)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_FREE, 1);
+ if (flags & QED_NVM_CFG_OPTION_ENTITY_SEL) {
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL, 1);
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID,
+ entity_id);
+ }
+
+ rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_GET_NVM_CFG_OPTION,
+ mb_param, &resp, ¶m, p_len, (u32 *)p_buf);
+
+ return rc;
+}
+
+int qed_mcp_nvm_set_cfg(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ u16 option_id, u8 entity_id, u16 flags, u8 *p_buf,
+ u32 len)
+{
+ u32 mb_param = 0, resp, param;
+ int rc;
+
+ QED_MFW_SET_FIELD(mb_param, DRV_MB_PARAM_NVM_CFG_OPTION_ID, option_id);
+ if (flags & QED_NVM_CFG_OPTION_ALL)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_ALL, 1);
+ if (flags & QED_NVM_CFG_OPTION_INIT)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_INIT, 1);
+ if (flags & QED_NVM_CFG_OPTION_COMMIT)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT, 1);
+ if (flags & QED_NVM_CFG_OPTION_FREE)
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_FREE, 1);
+ if (flags & QED_NVM_CFG_OPTION_ENTITY_SEL) {
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL, 1);
+ QED_MFW_SET_FIELD(mb_param,
+ DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID,
+ entity_id);
+ }
+
+ rc = qed_mcp_nvm_wr_cmd(p_hwfn, p_ptt,
+ DRV_MSG_CODE_SET_NVM_CFG_OPTION,
+ mb_param, &resp, ¶m, len, (u32 *)p_buf);
+
+ return rc;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index e4f8fe4..550b4dd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -251,6 +251,12 @@ struct qed_mfw_tlv_generic {
struct qed_mfw_tlv_iscsi iscsi;
};
+#define QED_NVM_CFG_OPTION_ALL BIT(0)
+#define QED_NVM_CFG_OPTION_INIT BIT(1)
+#define QED_NVM_CFG_OPTION_COMMIT BIT(2)
+#define QED_NVM_CFG_OPTION_FREE BIT(3)
+#define QED_NVM_CFG_OPTION_ENTITY_SEL BIT(4)
+
/**
* @brief - returns the link params of the hw function
*
@@ -1202,4 +1208,12 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
*/
int qed_mcp_get_ppfid_bitmap(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+int qed_mcp_nvm_get_cfg(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ u16 option_id, u8 entity_id, u16 flags, u8 *p_buf,
+ u32 *p_len);
+
+int qed_mcp_nvm_set_cfg(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ u16 option_id, u8 entity_id, u16 flags, u8 *p_buf,
+ u32 len);
+
#endif
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 0/2] qed: Support for NVM config attributes.
From: Sudarsana Reddy Kalluru @ 2019-07-24 4:51 UTC (permalink / raw)
To: davem; +Cc: netdev, mkalderon, aelior
The patch series add support for managing the NVM config attributes.
Patch (1) adds interfaces for read/write config attributes from MFW.
Patch (2) adds driver interface for updating the config attributes.
Sudarsana Reddy Kalluru (2):
qed: Add APIs for NVM config attributes.
qed: Add API for flashing the nvm attributes.
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 17 ++++++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 65 ++++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 64 +++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 14 +++++++
include/linux/qed/qed_if.h | 1 +
5 files changed, 161 insertions(+)
--
1.8.3.1
^ permalink raw reply
* [PATCH v3 0/3] mm/gup: add make_dirty arg to put_user_pages_dirty_lock()
From: john.hubbard @ 2019-07-24 4:45 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Björn Töpel, Boaz Harrosh,
Christoph Hellwig, Daniel Vetter, Dan Williams, Dave Chinner,
David Airlie, David S . Miller, Ilya Dryomov, Jan Kara,
Jason Gunthorpe, Jens Axboe, Jérôme Glisse,
Johannes Thumshirn, Magnus Karlsson, Matthew Wilcox,
Miklos Szeredi, Ming Lei, Sage Weil, Santosh Shilimkar, Yan Zheng,
netdev, dri-devel, linux-mm, linux-rdma, bpf, LKML, John Hubbard
From: John Hubbard <jhubbard@nvidia.com>
Hi,
I apologize for the extra emails (v2 was sent pretty recently), but I
didn't want to leave a known-broken version sitting out there, creating
problems.
Changes since v2:
* Critical bug fix: remove a stray "break;" from the new routine.
Changes since v1:
* Instead of providing __put_user_pages(), add an argument to
put_user_pages_dirty_lock(), and delete put_user_pages_dirty().
This is based on the following points:
1. Lots of call sites become simpler if a bool is passed
into put_user_page*(), instead of making the call site
choose which put_user_page*() variant to call.
2. Christoph Hellwig's observation that set_page_dirty_lock()
is usually correct, and set_page_dirty() is usually a
bug, or at least questionable, within a put_user_page*()
calling chain.
* Added the Infiniband driver back to the patch series, because it is
a caller of put_user_pages_dirty_lock().
Unchanged parts from the v1 cover letter (except for the diffstat):
Notes about the remaining patches to come:
There are about 50+ patches in my tree [2], and I'll be sending out the
remaining ones in a few more groups:
* The block/bio related changes (Jerome mostly wrote those, but I've
had to move stuff around extensively, and add a little code)
* mm/ changes
* other subsystem patches
* an RFC that shows the current state of the tracking patch set. That
can only be applied after all call sites are converted, but it's
good to get an early look at it.
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
John Hubbard (3):
mm/gup: add make_dirty arg to put_user_pages_dirty_lock()
drivers/gpu/drm/via: convert put_page() to put_user_page*()
net/xdp: convert put_page() to put_user_page*()
drivers/gpu/drm/via/via_dmablit.c | 10 +-
drivers/infiniband/core/umem.c | 5 +-
drivers/infiniband/hw/hfi1/user_pages.c | 5 +-
drivers/infiniband/hw/qib/qib_user_pages.c | 5 +-
drivers/infiniband/hw/usnic/usnic_uiom.c | 5 +-
drivers/infiniband/sw/siw/siw_mem.c | 8 +-
include/linux/mm.h | 5 +-
mm/gup.c | 115 +++++++++------------
net/xdp/xdp_umem.c | 9 +-
9 files changed, 61 insertions(+), 106 deletions(-)
--
2.22.0
^ permalink raw reply
* [PATCH v3 2/3] drivers/gpu/drm/via: convert put_page() to put_user_page*()
From: john.hubbard @ 2019-07-24 4:45 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Björn Töpel, Boaz Harrosh,
Christoph Hellwig, Daniel Vetter, Dan Williams, Dave Chinner,
David Airlie, David S . Miller, Ilya Dryomov, Jan Kara,
Jason Gunthorpe, Jens Axboe, Jérôme Glisse,
Johannes Thumshirn, Magnus Karlsson, Matthew Wilcox,
Miklos Szeredi, Ming Lei, Sage Weil, Santosh Shilimkar, Yan Zheng,
netdev, dri-devel, linux-mm, linux-rdma, bpf, LKML, John Hubbard
In-Reply-To: <20190724044537.10458-1-jhubbard@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
Also reverse the order of a comparison, in order to placate
checkpatch.pl.
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/gpu/drm/via/via_dmablit.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
index 062067438f1d..b5b5bf0ba65e 100644
--- a/drivers/gpu/drm/via/via_dmablit.c
+++ b/drivers/gpu/drm/via/via_dmablit.c
@@ -171,7 +171,6 @@ via_map_blit_for_device(struct pci_dev *pdev,
static void
via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
{
- struct page *page;
int i;
switch (vsg->state) {
@@ -186,13 +185,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
kfree(vsg->desc_pages);
/* fall through */
case dr_via_pages_locked:
- for (i = 0; i < vsg->num_pages; ++i) {
- if (NULL != (page = vsg->pages[i])) {
- if (!PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction))
- SetPageDirty(page);
- put_page(page);
- }
- }
+ put_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
+ (vsg->direction == DMA_FROM_DEVICE));
/* fall through */
case dr_via_pages_alloc:
vfree(vsg->pages);
--
2.22.0
^ permalink raw reply related
* [PATCH v3 3/3] net/xdp: convert put_page() to put_user_page*()
From: john.hubbard @ 2019-07-24 4:45 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Björn Töpel, Boaz Harrosh,
Christoph Hellwig, Daniel Vetter, Dan Williams, Dave Chinner,
David Airlie, David S . Miller, Ilya Dryomov, Jan Kara,
Jason Gunthorpe, Jens Axboe, Jérôme Glisse,
Johannes Thumshirn, Magnus Karlsson, Matthew Wilcox,
Miklos Szeredi, Ming Lei, Sage Weil, Santosh Shilimkar, Yan Zheng,
netdev, dri-devel, linux-mm, linux-rdma, bpf, LKML, John Hubbard
In-Reply-To: <20190724044537.10458-1-jhubbard@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
Cc: Björn Töpel <bjorn.topel@intel.com>
Cc: Magnus Karlsson <magnus.karlsson@intel.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
net/xdp/xdp_umem.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 83de74ca729a..17c4b3d3dc34 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c
@@ -166,14 +166,7 @@ void xdp_umem_clear_dev(struct xdp_umem *umem)
static void xdp_umem_unpin_pages(struct xdp_umem *umem)
{
- unsigned int i;
-
- for (i = 0; i < umem->npgs; i++) {
- struct page *page = umem->pgs[i];
-
- set_page_dirty_lock(page);
- put_page(page);
- }
+ put_user_pages_dirty_lock(umem->pgs, umem->npgs, true);
kfree(umem->pgs);
umem->pgs = NULL;
--
2.22.0
^ permalink raw reply related
* [PATCH v3 1/3] mm/gup: add make_dirty arg to put_user_pages_dirty_lock()
From: john.hubbard @ 2019-07-24 4:45 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Björn Töpel, Boaz Harrosh,
Christoph Hellwig, Daniel Vetter, Dan Williams, Dave Chinner,
David Airlie, David S . Miller, Ilya Dryomov, Jan Kara,
Jason Gunthorpe, Jens Axboe, Jérôme Glisse,
Johannes Thumshirn, Magnus Karlsson, Matthew Wilcox,
Miklos Szeredi, Ming Lei, Sage Weil, Santosh Shilimkar, Yan Zheng,
netdev, dri-devel, linux-mm, linux-rdma, bpf, LKML, John Hubbard,
Ira Weiny
In-Reply-To: <20190724044537.10458-1-jhubbard@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
Provide more capable variation of put_user_pages_dirty_lock(),
and delete put_user_pages_dirty(). This is based on the
following:
1. Lots of call sites become simpler if a bool is passed
into put_user_page*(), instead of making the call site
choose which put_user_page*() variant to call.
2. Christoph Hellwig's observation that set_page_dirty_lock()
is usually correct, and set_page_dirty() is usually a
bug, or at least questionable, within a put_user_page*()
calling chain.
This leads to the following API choices:
* put_user_pages_dirty_lock(page, npages, make_dirty)
* There is no put_user_pages_dirty(). You have to
hand code that, in the rare case that it's
required.
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/infiniband/core/umem.c | 5 +-
drivers/infiniband/hw/hfi1/user_pages.c | 5 +-
drivers/infiniband/hw/qib/qib_user_pages.c | 5 +-
drivers/infiniband/hw/usnic/usnic_uiom.c | 5 +-
drivers/infiniband/sw/siw/siw_mem.c | 8 +-
include/linux/mm.h | 5 +-
mm/gup.c | 115 +++++++++------------
7 files changed, 58 insertions(+), 90 deletions(-)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 08da840ed7ee..965cf9dea71a 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -54,10 +54,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->sg_nents, 0) {
page = sg_page_iter_page(&sg_iter);
- if (umem->writable && dirty)
- put_user_pages_dirty_lock(&page, 1);
- else
- put_user_page(page);
+ put_user_pages_dirty_lock(&page, 1, umem->writable && dirty);
}
sg_free_table(&umem->sg_head);
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
index b89a9b9aef7a..469acb961fbd 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -118,10 +118,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
void hfi1_release_user_pages(struct mm_struct *mm, struct page **p,
size_t npages, bool dirty)
{
- if (dirty)
- put_user_pages_dirty_lock(p, npages);
- else
- put_user_pages(p, npages);
+ put_user_pages_dirty_lock(p, npages, dirty);
if (mm) { /* during close after signal, mm can be NULL */
atomic64_sub(npages, &mm->pinned_vm);
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index bfbfbb7e0ff4..6bf764e41891 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -40,10 +40,7 @@
static void __qib_release_user_pages(struct page **p, size_t num_pages,
int dirty)
{
- if (dirty)
- put_user_pages_dirty_lock(p, num_pages);
- else
- put_user_pages(p, num_pages);
+ put_user_pages_dirty_lock(p, num_pages, dirty);
}
/**
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index 0b0237d41613..62e6ffa9ad78 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -75,10 +75,7 @@ static void usnic_uiom_put_pages(struct list_head *chunk_list, int dirty)
for_each_sg(chunk->page_list, sg, chunk->nents, i) {
page = sg_page(sg);
pa = sg_phys(sg);
- if (dirty)
- put_user_pages_dirty_lock(&page, 1);
- else
- put_user_page(page);
+ put_user_pages_dirty_lock(&page, 1, dirty);
usnic_dbg("pa: %pa\n", &pa);
}
kfree(chunk);
diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
index 67171c82b0c4..358d440efa11 100644
--- a/drivers/infiniband/sw/siw/siw_mem.c
+++ b/drivers/infiniband/sw/siw/siw_mem.c
@@ -65,13 +65,7 @@ static void siw_free_plist(struct siw_page_chunk *chunk, int num_pages,
{
struct page **p = chunk->plist;
- while (num_pages--) {
- if (!PageDirty(*p) && dirty)
- put_user_pages_dirty_lock(p, 1);
- else
- put_user_page(*p);
- p++;
- }
+ put_user_pages_dirty_lock(chunk->plist, num_pages, dirty);
}
void siw_umem_release(struct siw_umem *umem, bool dirty)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0334ca97c584..9759b6a24420 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1057,8 +1057,9 @@ static inline void put_user_page(struct page *page)
put_page(page);
}
-void put_user_pages_dirty(struct page **pages, unsigned long npages);
-void put_user_pages_dirty_lock(struct page **pages, unsigned long npages);
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages,
+ bool make_dirty);
+
void put_user_pages(struct page **pages, unsigned long npages);
#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
diff --git a/mm/gup.c b/mm/gup.c
index 98f13ab37bac..7fefd7ab02c4 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -29,85 +29,70 @@ struct follow_page_context {
unsigned int page_mask;
};
-typedef int (*set_dirty_func_t)(struct page *page);
-
-static void __put_user_pages_dirty(struct page **pages,
- unsigned long npages,
- set_dirty_func_t sdf)
-{
- unsigned long index;
-
- for (index = 0; index < npages; index++) {
- struct page *page = compound_head(pages[index]);
-
- /*
- * Checking PageDirty at this point may race with
- * clear_page_dirty_for_io(), but that's OK. Two key cases:
- *
- * 1) This code sees the page as already dirty, so it skips
- * the call to sdf(). That could happen because
- * clear_page_dirty_for_io() called page_mkclean(),
- * followed by set_page_dirty(). However, now the page is
- * going to get written back, which meets the original
- * intention of setting it dirty, so all is well:
- * clear_page_dirty_for_io() goes on to call
- * TestClearPageDirty(), and write the page back.
- *
- * 2) This code sees the page as clean, so it calls sdf().
- * The page stays dirty, despite being written back, so it
- * gets written back again in the next writeback cycle.
- * This is harmless.
- */
- if (!PageDirty(page))
- sdf(page);
-
- put_user_page(page);
- }
-}
-
/**
- * put_user_pages_dirty() - release and dirty an array of gup-pinned pages
- * @pages: array of pages to be marked dirty and released.
+ * put_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages
+ * @pages: array of pages to be maybe marked dirty, and definitely released.
* @npages: number of pages in the @pages array.
+ * @make_dirty: whether to mark the pages dirty
*
* "gup-pinned page" refers to a page that has had one of the get_user_pages()
* variants called on that page.
*
* For each page in the @pages array, make that page (or its head page, if a
- * compound page) dirty, if it was previously listed as clean. Then, release
- * the page using put_user_page().
+ * compound page) dirty, if @make_dirty is true, and if the page was previously
+ * listed as clean. In any case, releases all pages using put_user_page(),
+ * possibly via put_user_pages(), for the non-dirty case.
*
* Please see the put_user_page() documentation for details.
*
- * set_page_dirty(), which does not lock the page, is used here.
- * Therefore, it is the caller's responsibility to ensure that this is
- * safe. If not, then put_user_pages_dirty_lock() should be called instead.
+ * set_page_dirty_lock() is used internally. If instead, set_page_dirty() is
+ * required, then the caller should a) verify that this is really correct,
+ * because _lock() is usually required, and b) hand code it:
+ * set_page_dirty_lock(), put_user_page().
*
*/
-void put_user_pages_dirty(struct page **pages, unsigned long npages)
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages,
+ bool make_dirty)
{
- __put_user_pages_dirty(pages, npages, set_page_dirty);
-}
-EXPORT_SYMBOL(put_user_pages_dirty);
+ unsigned long index;
-/**
- * put_user_pages_dirty_lock() - release and dirty an array of gup-pinned pages
- * @pages: array of pages to be marked dirty and released.
- * @npages: number of pages in the @pages array.
- *
- * For each page in the @pages array, make that page (or its head page, if a
- * compound page) dirty, if it was previously listed as clean. Then, release
- * the page using put_user_page().
- *
- * Please see the put_user_page() documentation for details.
- *
- * This is just like put_user_pages_dirty(), except that it invokes
- * set_page_dirty_lock(), instead of set_page_dirty().
- *
- */
-void put_user_pages_dirty_lock(struct page **pages, unsigned long npages)
-{
- __put_user_pages_dirty(pages, npages, set_page_dirty_lock);
+ /*
+ * TODO: this can be optimized for huge pages: if a series of pages is
+ * physically contiguous and part of the same compound page, then a
+ * single operation to the head page should suffice.
+ */
+
+ if (!make_dirty) {
+ put_user_pages(pages, npages);
+ return;
+ }
+
+ for (index = 0; index < npages; index++) {
+ struct page *page = compound_head(pages[index]);
+ /*
+ * Checking PageDirty at this point may race with
+ * clear_page_dirty_for_io(), but that's OK. Two key
+ * cases:
+ *
+ * 1) This code sees the page as already dirty, so it
+ * skips the call to set_page_dirty(). That could happen
+ * because clear_page_dirty_for_io() called
+ * page_mkclean(), followed by set_page_dirty().
+ * However, now the page is going to get written back,
+ * which meets the original intention of setting it
+ * dirty, so all is well: clear_page_dirty_for_io() goes
+ * on to call TestClearPageDirty(), and write the page
+ * back.
+ *
+ * 2) This code sees the page as clean, so it calls
+ * set_page_dirty(). The page stays dirty, despite being
+ * written back, so it gets written back again in the
+ * next writeback cycle. This is harmless.
+ */
+ if (!PageDirty(page))
+ set_page_dirty_lock(page);
+ put_user_page(page);
+ }
}
EXPORT_SYMBOL(put_user_pages_dirty_lock);
--
2.22.0
^ permalink raw reply related
* [PATCH] net: fix semicolon.cocci warnings
From: kbuild test robot @ 2019-07-24 4:37 UTC (permalink / raw)
To: Matthew Wilcox (Oracle)
Cc: kbuild-all, netdev, Martin K. Petersen, Thomas Gleixner,
Allison Randal, Kate Stewart, Bart Van Assche, linux-scsi,
target-devel, linux-kernel
In-Reply-To: <201907241208.upolDRPG%lkp@intel.com>
From: kbuild test robot <lkp@intel.com>
drivers/target/iscsi/cxgbit/cxgbit_target.c:1451:47-48: Unneeded semicolon
Remove unneeded semicolon.
Generated by: scripts/coccinelle/misc/semicolon.cocci
Fixes: d7840976e391 ("net: Use skb accessors in network drivers")
CC: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: kbuild test robot <lkp@intel.com>
---
tree: https://kernel.googlesource.com/pub/scm/linux/kernel/git/davem/net-next.git master
head: 3e3bb69589e482e0783f28d4cd1d8e56fda0bcbb
commit: d7840976e3915669382c62ddd1700960f348328e [7/33] net: Use skb accessors in network drivers
cxgbit_target.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/target/iscsi/cxgbit/cxgbit_target.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c
@@ -1448,7 +1448,7 @@ cxgbit_lro_skb_merge(struct cxgbit_sock
hpdu_cb->frags++;
hpdu_cb->hfrag_idx = hfrag_idx;
- len = skb_frag_size(&hssi->frags[hfrag_idx]);;
+ len = skb_frag_size(&hssi->frags[hfrag_idx]);
hskb->len += len;
hskb->data_len += len;
hskb->truesize += len;
^ permalink raw reply
* [net-next:master 7/33] drivers/target/iscsi/cxgbit/cxgbit_target.c:1451:47-48: Unneeded semicolon
From: kbuild test robot @ 2019-07-24 4:37 UTC (permalink / raw)
To: Matthew Wilcox (Oracle); +Cc: kbuild-all, netdev
tree: https://kernel.googlesource.com/pub/scm/linux/kernel/git/davem/net-next.git master
head: 3e3bb69589e482e0783f28d4cd1d8e56fda0bcbb
commit: d7840976e3915669382c62ddd1700960f348328e [7/33] net: Use skb accessors in network drivers
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
coccinelle warnings: (new ones prefixed by >>)
>> drivers/target/iscsi/cxgbit/cxgbit_target.c:1451:47-48: Unneeded semicolon
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* Re: [PATCH 07/12] vhost-scsi: convert put_page() to put_user_page*()
From: John Hubbard @ 2019-07-24 4:34 UTC (permalink / raw)
To: john.hubbard, Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization,
Jérôme Glisse, Jan Kara, Dan Williams,
Johannes Thumshirn, Ming Lei, Dave Chinner, Boaz Harrosh,
Paolo Bonzini, Stefan Hajnoczi
In-Reply-To: <20190724042518.14363-8-jhubbard@nvidia.com>
On 7/23/19 9:25 PM, john.hubbard@gmail.com wrote:
> From: Jérôme Glisse <jglisse@redhat.com>
>
> For pages that were retained via get_user_pages*(), release those pages
> via the new put_user_page*() routines, instead of via put_page().
>
> This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
> ("mm: introduce put_user_page*(), placeholder versions").
>
> Changes from Jérôme's original patch:
>
> * Changed a WARN_ON to a BUG_ON.
>
Clearly, the above commit log has it backwards (this is quite my night
for typos). Please read that as "changed a BUG_ON to a WARN_ON".
I'll correct the commit description in next iteration of this patchset.
...
> + /*
> + * Here in all cases we should have an IOVEC which use GUP. If that is
> + * not the case then we will wrongly call put_user_page() and the page
> + * refcount will go wrong (this is in vhost_scsi_release_cmd())
> + */
> + WARN_ON(!iov_iter_get_pages_use_gup(iter));
> +
...
thanks,
--
John Hubbard
NVIDIA
^ permalink raw reply
* [PATCH 01/12] mm/gup: add make_dirty arg to put_user_pages_dirty_lock()
From: john.hubbard @ 2019-07-24 4:25 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization, John Hubbard,
Jan Kara, Ira Weiny
In-Reply-To: <20190724042518.14363-1-jhubbard@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
Provide more capable variation of put_user_pages_dirty_lock(),
and delete put_user_pages_dirty(). This is based on the
following:
1. Lots of call sites become simpler if a bool is passed
into put_user_page*(), instead of making the call site
choose which put_user_page*() variant to call.
2. Christoph Hellwig's observation that set_page_dirty_lock()
is usually correct, and set_page_dirty() is usually a
bug, or at least questionable, within a put_user_page*()
calling chain.
This leads to the following API choices:
* put_user_pages_dirty_lock(page, npages, make_dirty)
* There is no put_user_pages_dirty(). You have to
hand code that, in the rare case that it's
required.
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/infiniband/core/umem.c | 5 +-
drivers/infiniband/hw/hfi1/user_pages.c | 5 +-
drivers/infiniband/hw/qib/qib_user_pages.c | 5 +-
drivers/infiniband/hw/usnic/usnic_uiom.c | 5 +-
drivers/infiniband/sw/siw/siw_mem.c | 8 +-
include/linux/mm.h | 5 +-
mm/gup.c | 115 +++++++++------------
7 files changed, 58 insertions(+), 90 deletions(-)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 08da840ed7ee..965cf9dea71a 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -54,10 +54,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->sg_nents, 0) {
page = sg_page_iter_page(&sg_iter);
- if (umem->writable && dirty)
- put_user_pages_dirty_lock(&page, 1);
- else
- put_user_page(page);
+ put_user_pages_dirty_lock(&page, 1, umem->writable && dirty);
}
sg_free_table(&umem->sg_head);
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
index b89a9b9aef7a..469acb961fbd 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -118,10 +118,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
void hfi1_release_user_pages(struct mm_struct *mm, struct page **p,
size_t npages, bool dirty)
{
- if (dirty)
- put_user_pages_dirty_lock(p, npages);
- else
- put_user_pages(p, npages);
+ put_user_pages_dirty_lock(p, npages, dirty);
if (mm) { /* during close after signal, mm can be NULL */
atomic64_sub(npages, &mm->pinned_vm);
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index bfbfbb7e0ff4..6bf764e41891 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -40,10 +40,7 @@
static void __qib_release_user_pages(struct page **p, size_t num_pages,
int dirty)
{
- if (dirty)
- put_user_pages_dirty_lock(p, num_pages);
- else
- put_user_pages(p, num_pages);
+ put_user_pages_dirty_lock(p, num_pages, dirty);
}
/**
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index 0b0237d41613..62e6ffa9ad78 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -75,10 +75,7 @@ static void usnic_uiom_put_pages(struct list_head *chunk_list, int dirty)
for_each_sg(chunk->page_list, sg, chunk->nents, i) {
page = sg_page(sg);
pa = sg_phys(sg);
- if (dirty)
- put_user_pages_dirty_lock(&page, 1);
- else
- put_user_page(page);
+ put_user_pages_dirty_lock(&page, 1, dirty);
usnic_dbg("pa: %pa\n", &pa);
}
kfree(chunk);
diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
index 67171c82b0c4..358d440efa11 100644
--- a/drivers/infiniband/sw/siw/siw_mem.c
+++ b/drivers/infiniband/sw/siw/siw_mem.c
@@ -65,13 +65,7 @@ static void siw_free_plist(struct siw_page_chunk *chunk, int num_pages,
{
struct page **p = chunk->plist;
- while (num_pages--) {
- if (!PageDirty(*p) && dirty)
- put_user_pages_dirty_lock(p, 1);
- else
- put_user_page(*p);
- p++;
- }
+ put_user_pages_dirty_lock(chunk->plist, num_pages, dirty);
}
void siw_umem_release(struct siw_umem *umem, bool dirty)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0334ca97c584..9759b6a24420 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1057,8 +1057,9 @@ static inline void put_user_page(struct page *page)
put_page(page);
}
-void put_user_pages_dirty(struct page **pages, unsigned long npages);
-void put_user_pages_dirty_lock(struct page **pages, unsigned long npages);
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages,
+ bool make_dirty);
+
void put_user_pages(struct page **pages, unsigned long npages);
#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
diff --git a/mm/gup.c b/mm/gup.c
index 98f13ab37bac..7fefd7ab02c4 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -29,85 +29,70 @@ struct follow_page_context {
unsigned int page_mask;
};
-typedef int (*set_dirty_func_t)(struct page *page);
-
-static void __put_user_pages_dirty(struct page **pages,
- unsigned long npages,
- set_dirty_func_t sdf)
-{
- unsigned long index;
-
- for (index = 0; index < npages; index++) {
- struct page *page = compound_head(pages[index]);
-
- /*
- * Checking PageDirty at this point may race with
- * clear_page_dirty_for_io(), but that's OK. Two key cases:
- *
- * 1) This code sees the page as already dirty, so it skips
- * the call to sdf(). That could happen because
- * clear_page_dirty_for_io() called page_mkclean(),
- * followed by set_page_dirty(). However, now the page is
- * going to get written back, which meets the original
- * intention of setting it dirty, so all is well:
- * clear_page_dirty_for_io() goes on to call
- * TestClearPageDirty(), and write the page back.
- *
- * 2) This code sees the page as clean, so it calls sdf().
- * The page stays dirty, despite being written back, so it
- * gets written back again in the next writeback cycle.
- * This is harmless.
- */
- if (!PageDirty(page))
- sdf(page);
-
- put_user_page(page);
- }
-}
-
/**
- * put_user_pages_dirty() - release and dirty an array of gup-pinned pages
- * @pages: array of pages to be marked dirty and released.
+ * put_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages
+ * @pages: array of pages to be maybe marked dirty, and definitely released.
* @npages: number of pages in the @pages array.
+ * @make_dirty: whether to mark the pages dirty
*
* "gup-pinned page" refers to a page that has had one of the get_user_pages()
* variants called on that page.
*
* For each page in the @pages array, make that page (or its head page, if a
- * compound page) dirty, if it was previously listed as clean. Then, release
- * the page using put_user_page().
+ * compound page) dirty, if @make_dirty is true, and if the page was previously
+ * listed as clean. In any case, releases all pages using put_user_page(),
+ * possibly via put_user_pages(), for the non-dirty case.
*
* Please see the put_user_page() documentation for details.
*
- * set_page_dirty(), which does not lock the page, is used here.
- * Therefore, it is the caller's responsibility to ensure that this is
- * safe. If not, then put_user_pages_dirty_lock() should be called instead.
+ * set_page_dirty_lock() is used internally. If instead, set_page_dirty() is
+ * required, then the caller should a) verify that this is really correct,
+ * because _lock() is usually required, and b) hand code it:
+ * set_page_dirty_lock(), put_user_page().
*
*/
-void put_user_pages_dirty(struct page **pages, unsigned long npages)
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages,
+ bool make_dirty)
{
- __put_user_pages_dirty(pages, npages, set_page_dirty);
-}
-EXPORT_SYMBOL(put_user_pages_dirty);
+ unsigned long index;
-/**
- * put_user_pages_dirty_lock() - release and dirty an array of gup-pinned pages
- * @pages: array of pages to be marked dirty and released.
- * @npages: number of pages in the @pages array.
- *
- * For each page in the @pages array, make that page (or its head page, if a
- * compound page) dirty, if it was previously listed as clean. Then, release
- * the page using put_user_page().
- *
- * Please see the put_user_page() documentation for details.
- *
- * This is just like put_user_pages_dirty(), except that it invokes
- * set_page_dirty_lock(), instead of set_page_dirty().
- *
- */
-void put_user_pages_dirty_lock(struct page **pages, unsigned long npages)
-{
- __put_user_pages_dirty(pages, npages, set_page_dirty_lock);
+ /*
+ * TODO: this can be optimized for huge pages: if a series of pages is
+ * physically contiguous and part of the same compound page, then a
+ * single operation to the head page should suffice.
+ */
+
+ if (!make_dirty) {
+ put_user_pages(pages, npages);
+ return;
+ }
+
+ for (index = 0; index < npages; index++) {
+ struct page *page = compound_head(pages[index]);
+ /*
+ * Checking PageDirty at this point may race with
+ * clear_page_dirty_for_io(), but that's OK. Two key
+ * cases:
+ *
+ * 1) This code sees the page as already dirty, so it
+ * skips the call to set_page_dirty(). That could happen
+ * because clear_page_dirty_for_io() called
+ * page_mkclean(), followed by set_page_dirty().
+ * However, now the page is going to get written back,
+ * which meets the original intention of setting it
+ * dirty, so all is well: clear_page_dirty_for_io() goes
+ * on to call TestClearPageDirty(), and write the page
+ * back.
+ *
+ * 2) This code sees the page as clean, so it calls
+ * set_page_dirty(). The page stays dirty, despite being
+ * written back, so it gets written back again in the
+ * next writeback cycle. This is harmless.
+ */
+ if (!PageDirty(page))
+ set_page_dirty_lock(page);
+ put_user_page(page);
+ }
}
EXPORT_SYMBOL(put_user_pages_dirty_lock);
--
2.22.0
^ permalink raw reply related
* [PATCH 00/12] block/bio, fs: convert put_page() to put_user_page*()
From: john.hubbard @ 2019-07-24 4:25 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization, John Hubbard
From: John Hubbard <jhubbard@nvidia.com>
Hi,
This is mostly Jerome's work, converting the block/bio and related areas
to call put_user_page*() instead of put_page(). Because I've changed
Jerome's patches, in some cases significantly, I'd like to get his
feedback before we actually leave him listed as the author (he might
want to disown some or all of these).
I added a new patch, in order to make this work with Christoph Hellwig's
recent overhaul to bio_release_pages(): "block: bio_release_pages: use
flags arg instead of bool".
I've started the series with a patch that I've posted in another
series ("mm/gup: add make_dirty arg to put_user_pages_dirty_lock()"[1]),
because I'm not sure which of these will go in first, and this allows each
to stand alone.
Testing: not much beyond build and boot testing has been done yet. And
I'm not set up to even exercise all of it (especially the IB parts) at
run time.
Anyway, changes here are:
* Store, in the iov_iter, a "came from gup (get_user_pages)" parameter.
Then, use the new iov_iter_get_pages_use_gup() to retrieve it when
it is time to release the pages. That allows choosing between put_page()
and put_user_page*().
* Pass in one more piece of information to bio_release_pages: a "from_gup"
parameter. Similar use as above.
* Change the block layer, and several file systems, to use
put_user_page*().
[1] https://lore.kernel.org/r/20190724012606.25844-2-jhubbard@nvidia.com
And please note the correction email that I posted as a follow-up,
if you're looking closely at that patch. :) The fixed version is
included here.
John Hubbard (3):
mm/gup: add make_dirty arg to put_user_pages_dirty_lock()
block: bio_release_pages: use flags arg instead of bool
fs/ceph: fix a build warning: returning a value from void function
Jérôme Glisse (9):
iov_iter: add helper to test if an iter would use GUP v2
block: bio_release_pages: convert put_page() to put_user_page*()
block_dev: convert put_page() to put_user_page*()
fs/nfs: convert put_page() to put_user_page*()
vhost-scsi: convert put_page() to put_user_page*()
fs/cifs: convert put_page() to put_user_page*()
fs/fuse: convert put_page() to put_user_page*()
fs/ceph: convert put_page() to put_user_page*()
9p/net: convert put_page() to put_user_page*()
block/bio.c | 81 ++++++++++++---
drivers/infiniband/core/umem.c | 5 +-
drivers/infiniband/hw/hfi1/user_pages.c | 5 +-
drivers/infiniband/hw/qib/qib_user_pages.c | 5 +-
drivers/infiniband/hw/usnic/usnic_uiom.c | 5 +-
drivers/infiniband/sw/siw/siw_mem.c | 8 +-
drivers/vhost/scsi.c | 13 ++-
fs/block_dev.c | 22 +++-
fs/ceph/debugfs.c | 2 +-
fs/ceph/file.c | 62 ++++++++---
fs/cifs/cifsglob.h | 3 +
fs/cifs/file.c | 22 +++-
fs/cifs/misc.c | 19 +++-
fs/direct-io.c | 2 +-
fs/fuse/dev.c | 22 +++-
fs/fuse/file.c | 53 +++++++---
fs/nfs/direct.c | 10 +-
include/linux/bio.h | 22 +++-
include/linux/mm.h | 5 +-
include/linux/uio.h | 11 ++
mm/gup.c | 115 +++++++++------------
net/9p/trans_common.c | 14 ++-
net/9p/trans_common.h | 3 +-
net/9p/trans_virtio.c | 18 +++-
24 files changed, 357 insertions(+), 170 deletions(-)
--
2.22.0
^ permalink raw reply
* [PATCH 02/12] iov_iter: add helper to test if an iter would use GUP v2
From: john.hubbard @ 2019-07-24 4:25 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization,
Jérôme Glisse, John Hubbard, Jan Kara, Dan Williams,
Johannes Thumshirn, Ming Lei, Dave Chinner
In-Reply-To: <20190724042518.14363-1-jhubbard@nvidia.com>
From: Jérôme Glisse <jglisse@redhat.com>
Add a helper to test if call to iov_iter_get_pages*() with a given
iter would result in calls to GUP (get_user_pages*()). We want to
use different tracking of page references if they are coming from
GUP (get_user_pages*()) and thus we need to know when GUP is used
for a given iter.
Changes since Jérôme's original patch:
* iov_iter_get_pages_use_gup(): do not return true for the ITER_PIPE
case, because iov_iter_get_pages() calls pipe_get_pages(), which in
turn uses get_page(), not get_user_pages().
* Remove some obsolete code, as part of rebasing onto Linux 5.3.
* Fix up the kerneldoc comment to "Return:" rather than "Returns:",
and a few other grammatical tweaks.
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-block@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Matthew Wilcox <willy@infradead.org>
---
include/linux/uio.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/linux/uio.h b/include/linux/uio.h
index ab5f523bc0df..2a179af8e5a7 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -86,6 +86,17 @@ static inline unsigned char iov_iter_rw(const struct iov_iter *i)
return i->type & (READ | WRITE);
}
+/**
+ * iov_iter_get_pages_use_gup - report if iov_iter_get_pages(i) uses GUP
+ * @i: iterator
+ * Return: true if a call to iov_iter_get_pages*() with the iter provided in
+ * the argument would result in the use of get_user_pages*()
+ */
+static inline bool iov_iter_get_pages_use_gup(const struct iov_iter *i)
+{
+ return iov_iter_type(i) == ITER_IOVEC;
+}
+
/*
* Total number of bytes covered by an iovec.
*
--
2.22.0
^ permalink raw reply related
* [PATCH 04/12] block: bio_release_pages: convert put_page() to put_user_page*()
From: john.hubbard @ 2019-07-24 4:25 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization,
Jérôme Glisse, John Hubbard, Christoph Hellwig,
Minwoo Im
In-Reply-To: <20190724042518.14363-1-jhubbard@nvidia.com>
From: Jérôme Glisse <jglisse@redhat.com>
For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
Changes from Jérôme's original patch:
* reworked to be compatible with recent bio_release_pages() changes,
* refactored slightly to remove some code duplication,
* use an approach that changes fewer bio_check_pages_dirty()
callers.
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Minwoo Im <minwoo.im.dev@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
---
block/bio.c | 60 ++++++++++++++++++++++++++++++++++++---------
include/linux/bio.h | 1 +
2 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index 7675e2de509d..74f9eba2583b 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -844,7 +844,11 @@ void bio_release_pages(struct bio *bio, enum bio_rp_flags_t flags)
bio_for_each_segment_all(bvec, bio, iter_all) {
if ((flags & BIO_RP_MARK_DIRTY) && !PageCompound(bvec->bv_page))
set_page_dirty_lock(bvec->bv_page);
- put_page(bvec->bv_page);
+
+ if (flags & BIO_RP_FROM_GUP)
+ put_user_page(bvec->bv_page);
+ else
+ put_page(bvec->bv_page);
}
}
@@ -1667,28 +1671,50 @@ static void bio_dirty_fn(struct work_struct *work);
static DECLARE_WORK(bio_dirty_work, bio_dirty_fn);
static DEFINE_SPINLOCK(bio_dirty_lock);
static struct bio *bio_dirty_list;
+static struct bio *bio_gup_dirty_list;
-/*
- * This runs in process context
- */
-static void bio_dirty_fn(struct work_struct *work)
+static void __bio_dirty_fn(struct work_struct *work,
+ struct bio **dirty_list,
+ enum bio_rp_flags_t flags)
{
struct bio *bio, *next;
spin_lock_irq(&bio_dirty_lock);
- next = bio_dirty_list;
- bio_dirty_list = NULL;
+ next = *dirty_list;
+ *dirty_list = NULL;
spin_unlock_irq(&bio_dirty_lock);
while ((bio = next) != NULL) {
next = bio->bi_private;
- bio_release_pages(bio, BIO_RP_MARK_DIRTY);
+ bio_release_pages(bio, BIO_RP_MARK_DIRTY | flags);
bio_put(bio);
}
}
-void bio_check_pages_dirty(struct bio *bio)
+/*
+ * This runs in process context
+ */
+static void bio_dirty_fn(struct work_struct *work)
+{
+ __bio_dirty_fn(work, &bio_dirty_list, BIO_RP_NORMAL);
+ __bio_dirty_fn(work, &bio_gup_dirty_list, BIO_RP_FROM_GUP);
+}
+
+/**
+ * __bio_check_pages_dirty() - queue up pages on a workqueue to dirty them
+ * @bio: the bio struct containing the pages we should dirty
+ * @from_gup: did the pages in the bio came from GUP (get_user_pages*())
+ *
+ * This will go over all pages in the bio, and for each non dirty page, the
+ * bio is added to a list of bio's that need to get their pages dirtied.
+ *
+ * We also need to know if the pages in the bio are coming from GUP or not,
+ * as GUPed pages need to be released via put_user_page(), instead of
+ * put_page(). Please see Documentation/vm/get_user_pages.rst for details
+ * on that.
+ */
+void __bio_check_pages_dirty(struct bio *bio, bool from_gup)
{
struct bio_vec *bvec;
unsigned long flags;
@@ -1699,17 +1725,27 @@ void bio_check_pages_dirty(struct bio *bio)
goto defer;
}
- bio_release_pages(bio, BIO_RP_NORMAL);
+ bio_release_pages(bio, from_gup ? BIO_RP_FROM_GUP : BIO_RP_NORMAL);
bio_put(bio);
return;
defer:
spin_lock_irqsave(&bio_dirty_lock, flags);
- bio->bi_private = bio_dirty_list;
- bio_dirty_list = bio;
+ if (from_gup) {
+ bio->bi_private = bio_gup_dirty_list;
+ bio_gup_dirty_list = bio;
+ } else {
+ bio->bi_private = bio_dirty_list;
+ bio_dirty_list = bio;
+ }
spin_unlock_irqrestore(&bio_dirty_lock, flags);
schedule_work(&bio_dirty_work);
}
+void bio_check_pages_dirty(struct bio *bio)
+{
+ __bio_check_pages_dirty(bio, false);
+}
+
void update_io_ticks(struct hd_struct *part, unsigned long now)
{
unsigned long stamp;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 2715e55679c1..d68a40c2c9d4 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -444,6 +444,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter);
enum bio_rp_flags_t {
BIO_RP_NORMAL = 0,
BIO_RP_MARK_DIRTY = 1,
+ BIO_RP_FROM_GUP = 2,
};
static inline enum bio_rp_flags_t bio_rp_dirty_flag(bool mark_dirty)
--
2.22.0
^ permalink raw reply related
* Re: [PATCH mlx5-next] net/mlx5: Fix modify_cq_in alignment
From: Leon Romanovsky @ 2019-07-24 4:26 UTC (permalink / raw)
To: Saeed Mahameed
Cc: davem@davemloft.net, Jason Gunthorpe, Yishai Hadas,
netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
dledford@redhat.com, Edward Srouji
In-Reply-To: <702add119e2059101ce67b7e153b5ad0ef0df288.camel@mellanox.com>
On Tue, Jul 23, 2019 at 08:34:07PM +0000, Saeed Mahameed wrote:
> On Tue, 2019-07-23 at 13:02 -0700, David Miller wrote:
> > From: Leon Romanovsky <leon@kernel.org>
> > Date: Tue, 23 Jul 2019 22:04:14 +0300
> >
> > > The intention was to have this patch in shared mlx5 branch, which
> > > is
> > > picked by RDMA too. This "Cc: stable@..." together with merge
> > > through
> > > RDMA will ensure that such patch will be part of stable
> > > automatically.
> >
> > Why wouldn't it come via Saeed's usual mlx5 bug fix pull requests to
> > me?
>
> That should have been the plan in first place, i will handle this,
> thanks Dave and sorry for any inconvenience.
>
> I will apply this patch to my (mlx5) net queue, will submit to net
> shortly.
OK, whatever works for you best.
Thanks
^ permalink raw reply
* [PATCH 06/12] fs/nfs: convert put_page() to put_user_page*()
From: john.hubbard @ 2019-07-24 4:25 UTC (permalink / raw)
To: Andrew Morton
Cc: Alexander Viro, Anna Schumaker, David S . Miller,
Dominique Martinet, Eric Van Hensbergen, Jason Gunthorpe,
Jason Wang, Jens Axboe, Latchesar Ionkov, Michael S . Tsirkin,
Miklos Szeredi, Trond Myklebust, Christoph Hellwig,
Matthew Wilcox, linux-mm, LKML, ceph-devel, kvm, linux-block,
linux-cifs, linux-fsdevel, linux-nfs, linux-rdma, netdev,
samba-technical, v9fs-developer, virtualization,
Jérôme Glisse, John Hubbard, Jan Kara, Dan Williams,
Johannes Thumshirn, Ming Lei, Dave Chinner, Boaz Harrosh
In-Reply-To: <20190724042518.14363-1-jhubbard@nvidia.com>
From: Jérôme Glisse <jglisse@redhat.com>
For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-block@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-nfs@vger.kernel.org
Cc: Jan Kara <jack@suse.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Boaz Harrosh <boaz@plexistor.com>
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <anna.schumaker@netapp.com>
---
fs/nfs/direct.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0cb442406168..35f30fe2900f 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -512,7 +512,10 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
pos += req_len;
dreq->bytes_left -= req_len;
}
- nfs_direct_release_pages(pagevec, npages);
+ if (iov_iter_get_pages_use_gup(iter))
+ put_user_pages(pagevec, npages);
+ else
+ nfs_direct_release_pages(pagevec, npages);
kvfree(pagevec);
if (result < 0)
break;
@@ -935,7 +938,10 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
pos += req_len;
dreq->bytes_left -= req_len;
}
- nfs_direct_release_pages(pagevec, npages);
+ if (iov_iter_get_pages_use_gup(iter))
+ put_user_pages(pagevec, npages);
+ else
+ nfs_direct_release_pages(pagevec, npages);
kvfree(pagevec);
if (result < 0)
break;
--
2.22.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox