* [net-next:master 13/125] drivers/net//ethernet/ni/nixge.c:254:9: warning: cast to pointer from integer of different size
From: kbuild test robot @ 2018-09-17 2:30 UTC (permalink / raw)
To: Moritz Fischer; +Cc: kbuild-all, netdev
[-- Attachment #1: Type: text/plain, Size: 9499 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: c3ec8bcceb07ab81e4ff017b4ebbacc137a5a15e
commit: 7e8d5755be0e6c92d3b86a85e54c6a550b1910c5 [13/125] net: nixge: Add support for 64-bit platforms
config: i386-randconfig-i1-09170930 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
git checkout 7e8d5755be0e6c92d3b86a85e54c6a550b1910c5
# save the attached .config to linux build tree
make ARCH=i386
All warnings (new ones prefixed by >>):
drivers/net//ethernet/ni/nixge.c: In function 'nixge_hw_dma_bd_release':
>> drivers/net//ethernet/ni/nixge.c:254:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
skb = (struct sk_buff *)
^
In file included from include/linux/skbuff.h:17:0,
from include/linux/if_ether.h:23,
from include/linux/etherdevice.h:25,
from drivers/net//ethernet/ni/nixge.c:7:
drivers/net//ethernet/ni/nixge.c: In function 'nixge_hw_dma_bd_init':
>> drivers/net//ethernet/ni/nixge.c:130:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
(bd)->field##_lo = lower_32_bits(((u64)addr)); \
^
include/linux/kernel.h:234:33: note: in definition of macro 'lower_32_bits'
#define lower_32_bits(n) ((u32)(n))
^
drivers/net//ethernet/ni/nixge.c:145:2: note: in expansion of macro 'nixge_hw_dma_bd_set_addr'
nixge_hw_dma_bd_set_addr((bd), sw_id_offset, (addr))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:326:3: note: in expansion of macro 'nixge_hw_dma_bd_set_offset'
nixge_hw_dma_bd_set_offset(&priv->rx_bd_v[i], skb);
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:131:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
(bd)->field##_hi = upper_32_bits(((u64)addr)); \
^
include/linux/kernel.h:228:35: note: in definition of macro 'upper_32_bits'
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
^
drivers/net//ethernet/ni/nixge.c:145:2: note: in expansion of macro 'nixge_hw_dma_bd_set_addr'
nixge_hw_dma_bd_set_addr((bd), sw_id_offset, (addr))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:326:3: note: in expansion of macro 'nixge_hw_dma_bd_set_offset'
nixge_hw_dma_bd_set_offset(&priv->rx_bd_v[i], skb);
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c: In function 'nixge_recv':
drivers/net//ethernet/ni/nixge.c:604:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
skb = (struct sk_buff *)nixge_hw_dma_bd_get_addr(cur_p,
^
In file included from include/linux/skbuff.h:17:0,
from include/linux/if_ether.h:23,
from include/linux/etherdevice.h:25,
from drivers/net//ethernet/ni/nixge.c:7:
>> drivers/net//ethernet/ni/nixge.c:130:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
(bd)->field##_lo = lower_32_bits(((u64)addr)); \
^
include/linux/kernel.h:234:33: note: in definition of macro 'lower_32_bits'
#define lower_32_bits(n) ((u32)(n))
^
drivers/net//ethernet/ni/nixge.c:145:2: note: in expansion of macro 'nixge_hw_dma_bd_set_addr'
nixge_hw_dma_bd_set_addr((bd), sw_id_offset, (addr))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:646:3: note: in expansion of macro 'nixge_hw_dma_bd_set_offset'
nixge_hw_dma_bd_set_offset(cur_p, new_skb);
^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:131:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
(bd)->field##_hi = upper_32_bits(((u64)addr)); \
^
include/linux/kernel.h:228:35: note: in definition of macro 'upper_32_bits'
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
^
drivers/net//ethernet/ni/nixge.c:145:2: note: in expansion of macro 'nixge_hw_dma_bd_set_addr'
nixge_hw_dma_bd_set_addr((bd), sw_id_offset, (addr))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/net//ethernet/ni/nixge.c:646:3: note: in expansion of macro 'nixge_hw_dma_bd_set_offset'
nixge_hw_dma_bd_set_offset(cur_p, new_skb);
^~~~~~~~~~~~~~~~~~~~~~~~~~
vim +254 drivers/net//ethernet/ni/nixge.c
126
127 #ifdef CONFIG_PHYS_ADDR_T_64BIT
128 #define nixge_hw_dma_bd_set_addr(bd, field, addr) \
129 do { \
> 130 (bd)->field##_lo = lower_32_bits(((u64)addr)); \
131 (bd)->field##_hi = upper_32_bits(((u64)addr)); \
132 } while (0)
133 #else
134 #define nixge_hw_dma_bd_set_addr(bd, field, addr) \
135 ((bd)->field##_lo = lower_32_bits((addr)))
136 #endif
137
138 #define nixge_hw_dma_bd_set_phys(bd, addr) \
139 nixge_hw_dma_bd_set_addr((bd), phys, (addr))
140
141 #define nixge_hw_dma_bd_set_next(bd, addr) \
142 nixge_hw_dma_bd_set_addr((bd), next, (addr))
143
144 #define nixge_hw_dma_bd_set_offset(bd, addr) \
145 nixge_hw_dma_bd_set_addr((bd), sw_id_offset, (addr))
146
147 #ifdef CONFIG_PHYS_ADDR_T_64BIT
148 #define nixge_hw_dma_bd_get_addr(bd, field) \
149 (dma_addr_t)((((u64)(bd)->field##_hi) << 32) | ((bd)->field##_lo))
150 #else
151 #define nixge_hw_dma_bd_get_addr(bd, field) \
152 (dma_addr_t)((bd)->field##_lo)
153 #endif
154
155 struct nixge_tx_skb {
156 struct sk_buff *skb;
157 dma_addr_t mapping;
158 size_t size;
159 bool mapped_as_page;
160 };
161
162 struct nixge_priv {
163 struct net_device *ndev;
164 struct napi_struct napi;
165 struct device *dev;
166
167 /* Connection to PHY device */
168 struct device_node *phy_node;
169 phy_interface_t phy_mode;
170
171 int link;
172 unsigned int speed;
173 unsigned int duplex;
174
175 /* MDIO bus data */
176 struct mii_bus *mii_bus; /* MII bus reference */
177
178 /* IO registers, dma functions and IRQs */
179 void __iomem *ctrl_regs;
180 void __iomem *dma_regs;
181
182 struct tasklet_struct dma_err_tasklet;
183
184 int tx_irq;
185 int rx_irq;
186
187 /* Buffer descriptors */
188 struct nixge_hw_dma_bd *tx_bd_v;
189 struct nixge_tx_skb *tx_skb;
190 dma_addr_t tx_bd_p;
191
192 struct nixge_hw_dma_bd *rx_bd_v;
193 dma_addr_t rx_bd_p;
194 u32 tx_bd_ci;
195 u32 tx_bd_tail;
196 u32 rx_bd_ci;
197
198 u32 coalesce_count_rx;
199 u32 coalesce_count_tx;
200 };
201
202 static void nixge_dma_write_reg(struct nixge_priv *priv, off_t offset, u32 val)
203 {
204 writel(val, priv->dma_regs + offset);
205 }
206
207 static void nixge_dma_write_desc_reg(struct nixge_priv *priv, off_t offset,
208 dma_addr_t addr)
209 {
210 writel(lower_32_bits(addr), priv->dma_regs + offset);
211 #ifdef CONFIG_PHYS_ADDR_T_64BIT
212 writel(upper_32_bits(addr), priv->dma_regs + offset + 4);
213 #endif
214 }
215
216 static u32 nixge_dma_read_reg(const struct nixge_priv *priv, off_t offset)
217 {
218 return readl(priv->dma_regs + offset);
219 }
220
221 static void nixge_ctrl_write_reg(struct nixge_priv *priv, off_t offset, u32 val)
222 {
223 writel(val, priv->ctrl_regs + offset);
224 }
225
226 static u32 nixge_ctrl_read_reg(struct nixge_priv *priv, off_t offset)
227 {
228 return readl(priv->ctrl_regs + offset);
229 }
230
231 #define nixge_ctrl_poll_timeout(priv, addr, val, cond, sleep_us, timeout_us) \
232 readl_poll_timeout((priv)->ctrl_regs + (addr), (val), (cond), \
233 (sleep_us), (timeout_us))
234
235 #define nixge_dma_poll_timeout(priv, addr, val, cond, sleep_us, timeout_us) \
236 readl_poll_timeout((priv)->dma_regs + (addr), (val), (cond), \
237 (sleep_us), (timeout_us))
238
239 static void nixge_hw_dma_bd_release(struct net_device *ndev)
240 {
241 struct nixge_priv *priv = netdev_priv(ndev);
242 dma_addr_t phys_addr;
243 struct sk_buff *skb;
244 int i;
245
246 for (i = 0; i < RX_BD_NUM; i++) {
247 phys_addr = nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
248 phys);
249
250 dma_unmap_single(ndev->dev.parent, phys_addr,
251 NIXGE_MAX_JUMBO_FRAME_SIZE,
252 DMA_FROM_DEVICE);
253
> 254 skb = (struct sk_buff *)
255 nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
256 sw_id_offset);
257 dev_kfree_skb(skb);
258 }
259
260 if (priv->rx_bd_v)
261 dma_free_coherent(ndev->dev.parent,
262 sizeof(*priv->rx_bd_v) * RX_BD_NUM,
263 priv->rx_bd_v,
264 priv->rx_bd_p);
265
266 if (priv->tx_skb)
267 devm_kfree(ndev->dev.parent, priv->tx_skb);
268
269 if (priv->tx_bd_v)
270 dma_free_coherent(ndev->dev.parent,
271 sizeof(*priv->tx_bd_v) * TX_BD_NUM,
272 priv->tx_bd_v,
273 priv->tx_bd_p);
274 }
275
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32576 bytes --]
^ permalink raw reply
* [PATCHv2 net-next 1/1] net: rds: use memset to optimize the recv
From: Zhu Yanjun @ 2018-09-17 2:49 UTC (permalink / raw)
To: santosh.shilimkar, davem, netdev, linux-rdma, rds-devel
The function rds_inc_init is in recv process. To use memset can optimize
the function rds_inc_init.
The test result:
Before:
1) + 24.950 us | rds_inc_init [rds]();
After:
1) + 10.990 us | rds_inc_init [rds]();
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: Zhu Yanjun <yanjun.zhu@oracle.com>
---
V1->V2: a new patch for net-next
---
net/rds/recv.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 12719653188a..727639dac8a7 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -43,8 +43,6 @@
void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
struct in6_addr *saddr)
{
- int i;
-
refcount_set(&inc->i_refcount, 1);
INIT_LIST_HEAD(&inc->i_item);
inc->i_conn = conn;
@@ -52,8 +50,7 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
inc->i_rdma_cookie = 0;
inc->i_rx_tstamp = ktime_set(0, 0);
- for (i = 0; i < RDS_RX_MAX_TRACES; i++)
- inc->i_rx_lat_trace[i] = 0;
+ memset(inc->i_rx_lat_trace, 0, sizeof(inc->i_rx_lat_trace));
}
EXPORT_SYMBOL_GPL(rds_inc_init);
--
2.17.1
^ permalink raw reply related
* Re: pull-request: bpf 2018-09-16
From: David Miller @ 2018-09-17 0:47 UTC (permalink / raw)
To: daniel; +Cc: ast, netdev
In-Reply-To: <20180916003645.22407-1-daniel@iogearbox.net>
From: Daniel Borkmann <daniel@iogearbox.net>
Date: Sun, 16 Sep 2018 02:36:45 +0200
> The following pull-request contains BPF updates for your *net* tree.
>
> The main changes are:
>
> 1) Fix end boundary calculation in BTF for the type section, from Martin.
>
> 2) Fix and revert subtraction of pointers that was accidentally allowed
> for unprivileged programs, from Alexei.
>
> 3) Fix bpf_msg_pull_data() helper by using __GFP_COMP in order to avoid
> a warning in linearizing sg pages into a single one for large allocs,
> from Tushar.
>
> Please consider pulling these changes from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
Pulled, thanks Daniel.
^ permalink raw reply
* Re: [PATCH 1/2] dt-binding: mediatek: Add binding document for MediaTek GMAC
From: Sergei Shtylyov @ 2018-09-17 8:33 UTC (permalink / raw)
To: Biao Huang, davem, robh+dt
Cc: honghui.zhang, yt.shen, liguo.zhang, mark.rutland, sean.wang,
nelson.chang, matthias.bgg, netdev, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <1537165763-13112-2-git-send-email-biao.huang@mediatek.com>
On 9/17/2018 9:29 AM, Biao Huang wrote:
> The commit adds the device tree binding documentation for the MediaTek
> GMAC found on Mediatek MT2712.
>
> Signed-off-by: Biao Huang <biao.huang@mediatek.com>
> ---
> .../devicetree/bindings/net/mediatek-gmac.txt | 45 ++++++++++++++++++++
> 1 file changed, 45 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/mediatek-gmac.txt
>
> diff --git a/Documentation/devicetree/bindings/net/mediatek-gmac.txt b/Documentation/devicetree/bindings/net/mediatek-gmac.txt
> new file mode 100644
> index 0000000..14876ed
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/mediatek-gmac.txt
> @@ -0,0 +1,45 @@
> +MediaTek Gigabit Ethernet controller
> +=========================================
> +
> +The gigabit ethernet controller can be found on MediaTek SoCs.
> +
> +* Ethernet controller node
> +
> +Required properties:
> +- compatible: Should be
> + "mediatek,mt2712-eth": for MT2712 SoC
> +- reg: Address and length of the register set for the device
> +- interrupts: Should contain the MAC interrupts
> +- interrupt-names: the name of interrupt in the interrupts property. These are
> + "macirq": For MT2712 SoC
> +- clocks: the clock used by the controller
> +- clock-names: the names of the clock listed in the clocks property. These are
> + "axi", "apb", "mac_ext", "ptp", "ptp_parent", "ptp_top": For MT2712 SoC
> +- mac-address: See ethernet.txt in the same directory
> +- power-domains: phandle to the power domain that the ethernet is part of
This (required) prop is absent in your example.
> +- phy-mode: See ethernet.txt file in the same directory.
> +- reset-gpio: gpio number for phy reset.
> +
> +Example:
> +
> +eth: eth@1101c000 {
eth: ethernet@1101c000 {
> + compatible = "mediatek,mt2712-eth";
> + reg = <0 0x1101c000 0 0x1200>;
> + interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
> + interrupt-names = "macirq";
> + phy-mode ="rgmii";
> + mac-address = [00 55 7b b5 7d f7];
> + clock-names = "axi",
> + "apb",
> + "mac_ext",
> + "ptp",
> + "ptp_parent",
> + "ptp_top";
> + clocks = <&pericfg CLK_PERI_GMAC>,
> + <&pericfg CLK_PERI_GMAC_PCLK>,
> + <&topckgen CLK_TOP_ETHER_125M_SEL>,
> + <&topckgen CLK_TOP_ETHER_50M_SEL>,
> + <&topckgen CLK_TOP_APLL1_D3>,
> + <&topckgen CLK_TOP_APLL1>;
> + reset-gpio = <&pio 87 GPIO_ACTIVE_HIGH>;
> + };
MBR, Sergei
^ permalink raw reply
* Re: [PATCH net-next] net/smc: cast sizeof to int for comparison
From: Andreas Schwab @ 2018-09-17 8:42 UTC (permalink / raw)
To: YueHaibing; +Cc: davem, ubraun, linux-kernel, netdev, linux-s390
In-Reply-To: <b598de63-f026-c3ff-3380-8b1814f90b82@huawei.com>
On Sep 17 2018, YueHaibing <yuehaibing@huawei.com> wrote:
> On 2018/9/15 19:35, Andreas Schwab wrote:
>> On Sep 15 2018, YueHaibing <yuehaibing@huawei.com> wrote:
>>
>>> Comparing an int to a size, which is unsigned, causes the int to become
>>> unsigned, giving the wrong result. kernel_sendmsg can return a negative
>>> error code.
>>>
>>> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
>>> ---
>>> net/smc/smc_clc.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
>>> index 83aba9a..fd0f5ce 100644
>>> --- a/net/smc/smc_clc.c
>>> +++ b/net/smc/smc_clc.c
>>> @@ -446,7 +446,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
>>> vec[i++].iov_len = sizeof(trl);
>>> /* due to the few bytes needed for clc-handshake this cannot block */
>>> len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
>>> - if (len < sizeof(pclc)) {
>>> + if (len < (int)sizeof(pclc)) {
>>> if (len >= 0) {
>>> reason_code = -ENETUNREACH;
>>> smc->sk.sk_err = -reason_code;
>>
>> It would perhaps be better to handle len < 0 first.
>
> That need refactor the err hangding, is worth doing it?
Just a few lines moving around, IFAICS.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply
* Re: [PATCH iproute2] libnetlink: fix leak and using unused memory on error
From: David Ahern @ 2018-09-17 3:54 UTC (permalink / raw)
To: Mahesh Bandewar (महेश बंडेवार),
Stephen Hemminger
Cc: Mahesh Bandewar, linux-netdev
In-Reply-To: <CAF2d9jjPGHnzkCgT00Us2ArsYJSjXMyOBrQaUVR-Fs3Rzbaftg@mail.gmail.com>
On 9/14/18 10:48 AM, Mahesh Bandewar (महेश बंडेवार) wrote:
> On Thu, Sep 13, 2018 at 12:33 PM, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
>> If an error happens in multi-segment message (tc only)
>> then report the error and stop processing further responses.
>> This also fixes refering to the buffer after free.
>>
>> The sequence check is not necessary here because the
>> response message has already been validated to be in
>> the window of the sequence number of the iov.
>>
>> Reported-by: Mahesh Bandewar <mahesh@bandewar.net>
>> Fixes: 7b2ee50c0cd5 ("hv_netvsc: common detach logic")
$ git show 7b2ee50c0cd5
fatal: ambiguous argument '7b2ee50c0cd5': unknown revision or path not
in the working tree.
but we knew that since iproute2 does not have hv_netsvc code. Copy and
paste error?
^ permalink raw reply
* Re: [PATCH v2 05/17] compat_ioctl: move more drivers to generic_compat_ioctl_ptrarg
From: Jonathan Cameron @ 2018-09-17 9:33 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-remoteproc-u79uwXL29TY76Z2rM5mHXA,
linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
platform-driver-x86-u79uwXL29TY76Z2rM5mHXA,
sparclinux-u79uwXL29TY76Z2rM5mHXA,
devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-scsi-u79uwXL29TY76Z2rM5mHXA,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
linux-rdma-u79uwXL29TY76Z2rM5mHXA,
qat-linux-ral2JQCrhuEAvxtiuMwx3w,
amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
ceph-devel-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, David S. Miller,
linux-btrfs-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn
In-Reply-To: <20180912151134.436719-1-arnd-r2nGTMty4D4@public.gmane.org>
On Wed, 12 Sep 2018 17:08:52 +0200
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> The .ioctl and .compat_ioctl file operations have the same prototype so
> they can both point to the same function, which works great almost all
> the time when all the commands are compatible.
>
> One exception is the s390 architecture, where a compat pointer is only
> 31 bit wide, and converting it into a 64-bit pointer requires calling
> compat_ptr(). Most drivers here will ever run in s390, but since we now
> have a generic helper for it, it's easy enough to use it consistently.
>
> I double-checked all these drivers to ensure that all ioctl arguments
> are used as pointers or are ignored, but are not interpreted as integer
> values.
>
> Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> ---
For IIO part.
Acked-by: Jonathan Cameron <Jonathan.Cameron-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Thanks,
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index a062cfddc5af..22844b94b0e9 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -1630,7 +1630,7 @@ static const struct file_operations iio_buffer_fileops = {
> .owner = THIS_MODULE,
> .llseek = noop_llseek,
> .unlocked_ioctl = iio_ioctl,
> - .compat_ioctl = iio_ioctl,
> + .compat_ioctl = generic_compat_ioctl_ptrarg,
> };
>
^ permalink raw reply
* Re: [PATCH net-next] net/smc: cast sizeof to int for comparison
From: YueHaibing @ 2018-09-17 9:38 UTC (permalink / raw)
To: Ursula Braun; +Cc: davem, linux-kernel, netdev, linux-s390
In-Reply-To: <554a145a-d59d-9033-1702-4987a9c4bc94@linux.ibm.com>
On 2018/9/17 16:49, Ursula Braun wrote:
>
>
> On 09/15/2018 12:00 PM, YueHaibing wrote:
>> Comparing an int to a size, which is unsigned, causes the int to become
>> unsigned, giving the wrong result. kernel_sendmsg can return a negative
>> error code.
>>
>
> Thanks for reporting this issue!
>
>> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
>> ---
>> net/smc/smc_clc.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
>> index 83aba9a..fd0f5ce 100644
>> --- a/net/smc/smc_clc.c
>> +++ b/net/smc/smc_clc.c
>> @@ -446,7 +446,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
>> vec[i++].iov_len = sizeof(trl);
>> /* due to the few bytes needed for clc-handshake this cannot block */
>> len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
>> - if (len < sizeof(pclc)) {
>> + if (len < (int)sizeof(pclc)) {
>> if (len >= 0) {
>> reason_code = -ENETUNREACH;
>> smc->sk.sk_err = -reason_code;
>>
>
> Your fix helps, but I would like to follow the hint of Andreas Schwab, and split
> the return value check like this:
>
> ---
> net/smc/smc_clc.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> --- a/net/smc/smc_clc.c
> +++ b/net/smc/smc_clc.c
> @@ -446,14 +446,12 @@ int smc_clc_send_proposal(struct smc_soc
> vec[i++].iov_len = sizeof(trl);
> /* due to the few bytes needed for clc-handshake this cannot block */
> len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
> - if (len < sizeof(pclc)) {
> - if (len >= 0) {
> - reason_code = -ENETUNREACH;
> - smc->sk.sk_err = -reason_code;
> - } else {
> - smc->sk.sk_err = smc->clcsock->sk->sk_err;
> - reason_code = -smc->sk.sk_err;
> - }
> + if (len < 0) {
> + smc->sk.sk_err = smc->clcsock->sk->sk_err;
> + reason_code = -smc->sk.sk_err;
> + } else if (len < (int)sizeof(pclc)) {
> + reason_code = -ENETUNREACH;
> + smc->sk.sk_err = -reason_code;
> }
>
> return reason_code;
>
> Agreed?
Yes, Need a new patch from me?
>
> Regards, Ursula
>
>
>
^ permalink raw reply
* Re: [PATCH 1/2] netlink: add NLA_REJECT policy type
From: Johannes Berg @ 2018-09-17 9:38 UTC (permalink / raw)
To: Marcelo Ricardo Leitner, Michal Kubecek
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, jbenc-H+wXaHxf7aLQT0dZR+AlfA
In-Reply-To: <20180913215839.GI27095-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On Thu, 2018-09-13 at 18:58 -0300, Marcelo Ricardo Leitner wrote:
> > It would be easier and IMHO cleaner if I could simply list these "read
> > only attributes" with NLA_REJECT policy for "set" request.
>
> Not that I'm against this. Point was fields that are considered output
> only today are probably being silently ignored, and we can't change
> them to be NLA_REJECT as it would break user applications.
Indeed.
> Then we
> will have fields that are rejected, and those old that are not. In the
> long run, nearly all output fields would be marked as NLA_REJECT,
> okay.
Perhaps, yes, though I assume it would only really be true for new
families that bother to mark as such.
> Then I ask my first question again: why reject these? They are not
> hurting anything, are they? It's different from your example I think.
> In there, the extra information which was ignored leads to a
> different behavior.
So in one case I was thinking of, there are some fields that simply
cannot be used for input, they're only used for output. But it may not
always be obvious to somebody using the API. Thus, I think it makes
sense to instruct the kernel to reject that, so that whoever gets
confused has immediate feedback that their usage is wrong. If we ignore
that, they may not realize their error immediately.
I think the ethtool case is similar: you can read and write some fields,
and only read others - but if you try to write the read-only fields
would you prefer to be told "sorry, this is not possible" vs. it being
silently ignored? I'd definitely prefer the former.
> Maybe it would be better to have NLA_IGNORE instead? </idea>
I don't think so, it doesn't give any feedback to the application author
that they're doing something wrong.
johannes
^ permalink raw reply
* Re: [PATCH 1/2] netlink: add NLA_REJECT policy type
From: Johannes Berg @ 2018-09-17 9:39 UTC (permalink / raw)
To: David Miller
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, mkubecek-AlSwsSmVLrQ
In-Reply-To: <20180913.155934.742447935316828936.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
On Thu, 2018-09-13 at 15:59 -0700, David Miller wrote:
> From: Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
> Date: Thu, 13 Sep 2018 10:46:02 +0200
>
> > + NL_SET_BAD_ATTR(extack, nla);
> > + if (extack && !extack->_msg)
> > + NL_SET_ERR_MSG(extack,
> > + "Attribute failed policy validation");
>
> Given the lively discussion that resulted from this conditional I am
> pretty sure we want to override existing messages.
>
> If we have an existing message, and we continued to process and
> parse anyways, then the existing message was informational or
> a warning.
>
> The message should be overridden when the action will be to fail, as
> it will be here when we return -EINVAL.
Not just -EINVAL, but yeah, I've just reworked the patch to do this.
johannes
^ permalink raw reply
* Re: [PATCH net] netfilter: bridge: Don't sabotage nf_hook calls from an l3mdev
From: David Ahern @ 2018-09-17 4:14 UTC (permalink / raw)
To: dsahern, netdev, pablo, fw; +Cc: ndsouza, idosch
In-Reply-To: <20180907220813.7141-1-dsahern@kernel.org>
Pablo:
DaveM has this marked as waiting for upstream. Any comment on this patch?
Thanks,
David
On 9/7/18 3:08 PM, dsahern@kernel.org wrote:
> From: David Ahern <dsahern@gmail.com>
>
> For starters, the bridge netfilter code registers operations that
> are invoked any time nh_hook is called. Specifically, ip_sabotage_in
> watches for nested calls for NF_INET_PRE_ROUTING when a bridge is in
> the stack.
>
> Packet wise, the bridge netfilter hook runs first. br_nf_pre_routing
> allocates nf_bridge, sets in_prerouting to 1 and calls NF_HOOK for
> NF_INET_PRE_ROUTING. It's finish function, br_nf_pre_routing_finish,
> then resets in_prerouting flag to 0 and the packet continues up the
> stack. The packet eventually makes it to the VRF driver and it invokes
> nf_hook for NF_INET_PRE_ROUTING in case any rules have been added against
> the vrf device.
>
> Because of the registered operations the call to nf_hook causes
> ip_sabotage_in to be invoked. That function sees the nf_bridge on the
> skb and that in_prerouting is not set. Thinking it is an invalid nested
> call it steals (drops) the packet.
>
> Update ip_sabotage_in to recognize that the bridge or one of its upper
> devices (e.g., vlan) can be enslaved to a VRF (L3 master device) and
> allow the packet to go through the nf_hook a second time.
>
> Fixes: 73e20b761acf ("net: vrf: Add support for PREROUTING rules on vrf device")
> Reported-by: D'Souza, Nelson <ndsouza@ciena.com>
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
> net/bridge/br_netfilter_hooks.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
> index 6e0dc6bcd32a..37278dc280eb 100644
> --- a/net/bridge/br_netfilter_hooks.c
> +++ b/net/bridge/br_netfilter_hooks.c
> @@ -835,7 +835,8 @@ static unsigned int ip_sabotage_in(void *priv,
> struct sk_buff *skb,
> const struct nf_hook_state *state)
> {
> - if (skb->nf_bridge && !skb->nf_bridge->in_prerouting) {
> + if (skb->nf_bridge && !skb->nf_bridge->in_prerouting &&
> + !netif_is_l3_master(skb->dev)) {
> state->okfn(state->net, state->sk, skb);
> return NF_STOLEN;
> }
>
^ permalink raw reply
* [PATCH] net: ethernet: Fix a unused function warning.
From: zhong jiang @ 2018-09-17 10:44 UTC (permalink / raw)
To: davem, bryan.whitehead, UNGLinuxDriver; +Cc: netdev, linux-kernel
Fix the following compile warning:
drivers/net/ethernet/microchip/lan743x_main.c:2964:12: warning: lan743x_pm_suspend defined but not used [-Wunused-function]
static int lan743x_pm_suspend(struct device *dev)
drivers/net/ethernet/microchip/lan743x_main.c:2987:12: warning: lan743x_pm_resume defined but not used [-Wunused-function]
static int lan743x_pm_resume(struct device *dev)
Signed-off-by: zhong jiang <zhongjiang@huawei.com>
---
drivers/net/ethernet/microchip/lan743x_main.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index e7dce79..001b5f7 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -2850,7 +2850,7 @@ static void lan743x_pcidev_shutdown(struct pci_dev *pdev)
lan743x_hardware_cleanup(adapter);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static u16 lan743x_pm_wakeframe_crc16(const u8 *buf, int len)
{
return bitrev16(crc16(0xFFFF, buf, len));
@@ -3016,7 +3016,7 @@ static int lan743x_pm_resume(struct device *dev)
static const struct dev_pm_ops lan743x_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(lan743x_pm_suspend, lan743x_pm_resume)
};
-#endif /*CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
static const struct pci_device_id lan743x_pcidev_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) },
@@ -3028,7 +3028,7 @@ static int lan743x_pm_resume(struct device *dev)
.id_table = lan743x_pcidev_tbl,
.probe = lan743x_pcidev_probe,
.remove = lan743x_pcidev_remove,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
.driver.pm = &lan743x_pm_ops,
#endif
.shutdown = lan743x_pcidev_shutdown,
--
1.7.12.4
^ permalink raw reply related
* [PATCH net-next] liquidio: Add the features to show FEC settings and set FEC settings
From: Felix Manlunas @ 2018-09-17 5:43 UTC (permalink / raw)
To: davem
Cc: netdev, raghu.vatsavayi, derek.chickles, satananda.burla,
felix.manlunas, weilin.chang
From: Weilin Chang <weilin.chang@cavium.com>
1. Add functions for get_fecparam and set_fecparam.
2. Modify lio_get_link_ksettings to display FEC setting.
Signed-off-by: Weilin Chang <weilin.chang@cavium.com>
Acked-by: Derek Chickles <derek.chickles@cavium.com>
Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com>
---
drivers/net/ethernet/cavium/liquidio/lio_core.c | 148 +++++++++++++++++++++
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 76 ++++++++++-
drivers/net/ethernet/cavium/liquidio/lio_main.c | 8 ++
.../net/ethernet/cavium/liquidio/liquidio_common.h | 5 +
.../net/ethernet/cavium/liquidio/octeon_device.h | 2 +
.../net/ethernet/cavium/liquidio/octeon_network.h | 7 +-
6 files changed, 243 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 52b32b8..eb96b06 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -1654,3 +1654,151 @@ int liquidio_get_speed(struct lio *lio)
return retval;
}
+
+int liquidio_set_fec(struct lio *lio, int on_off)
+{
+ struct oct_nic_seapi_resp *resp;
+ struct octeon_soft_command *sc;
+ struct octeon_device *oct;
+ union octnet_cmd *ncmd;
+ int retval;
+ u32 var;
+
+ oct = lio->oct_dev;
+
+ if (oct->props[lio->ifidx].fec == on_off)
+ return 0;
+
+ if (!OCTEON_CN23XX_PF(oct)) {
+ dev_err(&oct->pci_dev->dev, "%s: SET FEC only for PF\n",
+ __func__);
+ return -1;
+ }
+
+ if (oct->speed_boot != 25) {
+ dev_err(&oct->pci_dev->dev,
+ "Set FEC only when link speed is 25G during insmod\n");
+ return -1;
+ }
+
+ sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+ sizeof(struct oct_nic_seapi_resp), 0);
+
+ ncmd = sc->virtdptr;
+ resp = sc->virtrptr;
+ memset(resp, 0, sizeof(struct oct_nic_seapi_resp));
+
+ init_completion(&sc->complete);
+ sc->sc_status = OCTEON_REQUEST_PENDING;
+
+ ncmd->u64 = 0;
+ ncmd->s.cmd = SEAPI_CMD_FEC_SET;
+ ncmd->s.param1 = on_off;
+ /* SEAPI_CMD_FEC_DISABLE(0) or SEAPI_CMD_FEC_RS(1) */
+
+ octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
+
+ sc->iq_no = lio->linfo.txpciq[0].s.q_no;
+
+ octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
+ OPCODE_NIC_UBOOT_CTL, 0, 0, 0);
+
+ retval = octeon_send_soft_command(oct, sc);
+ if (retval == IQ_SEND_FAILED) {
+ dev_info(&oct->pci_dev->dev, "Failed to send soft command\n");
+ octeon_free_soft_command(oct, sc);
+ return -EIO;
+ }
+
+ retval = wait_for_sc_completion_timeout(oct, sc, 0);
+ if (retval)
+ return (-EIO);
+
+ var = be32_to_cpu(resp->fec_setting);
+ resp->fec_setting = var;
+ if (var != on_off) {
+ dev_err(&oct->pci_dev->dev,
+ "Setting failed fec= %x, expect %x\n",
+ var, on_off);
+ oct->props[lio->ifidx].fec = var;
+ if (resp->fec_setting == SEAPI_CMD_FEC_SET_RS)
+ oct->props[lio->ifidx].fec = 1;
+ else
+ oct->props[lio->ifidx].fec = 0;
+ }
+
+ WRITE_ONCE(sc->caller_is_done, true);
+
+ if (oct->props[lio->ifidx].fec !=
+ oct->props[lio->ifidx].fec_boot) {
+ dev_dbg(&oct->pci_dev->dev,
+ "Reloade driver to chang fec to %s\n",
+ oct->props[lio->ifidx].fec ? "on" : "off");
+ }
+
+ return retval;
+}
+
+int liquidio_get_fec(struct lio *lio)
+{
+ struct oct_nic_seapi_resp *resp;
+ struct octeon_soft_command *sc;
+ struct octeon_device *oct;
+ union octnet_cmd *ncmd;
+ int retval;
+ u32 var;
+
+ oct = lio->oct_dev;
+
+ sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+ sizeof(struct oct_nic_seapi_resp), 0);
+ if (!sc)
+ return -ENOMEM;
+
+ ncmd = sc->virtdptr;
+ resp = sc->virtrptr;
+ memset(resp, 0, sizeof(struct oct_nic_seapi_resp));
+
+ init_completion(&sc->complete);
+ sc->sc_status = OCTEON_REQUEST_PENDING;
+
+ ncmd->u64 = 0;
+ ncmd->s.cmd = SEAPI_CMD_FEC_GET;
+
+ octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
+
+ sc->iq_no = lio->linfo.txpciq[0].s.q_no;
+
+ octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
+ OPCODE_NIC_UBOOT_CTL, 0, 0, 0);
+
+ retval = octeon_send_soft_command(oct, sc);
+ if (retval == IQ_SEND_FAILED) {
+ dev_info(&oct->pci_dev->dev,
+ "%s: Failed to send soft command\n", __func__);
+ octeon_free_soft_command(oct, sc);
+ return -EIO;
+ }
+
+ retval = wait_for_sc_completion_timeout(oct, sc, 0);
+ if (retval)
+ return retval;
+
+ var = be32_to_cpu(resp->fec_setting);
+ resp->fec_setting = var;
+ if (resp->fec_setting == SEAPI_CMD_FEC_SET_RS)
+ oct->props[lio->ifidx].fec = 1;
+ else
+ oct->props[lio->ifidx].fec = 0;
+
+ WRITE_ONCE(sc->caller_is_done, true);
+
+ if (oct->props[lio->ifidx].fec !=
+ oct->props[lio->ifidx].fec_boot) {
+ dev_dbg(&oct->pci_dev->dev,
+ "Reloade driver to chang fec to %s\n",
+ oct->props[lio->ifidx].fec ? "on" : "off");
+ }
+
+ return retval;
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 9e53cdb..4c3925a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -244,6 +244,7 @@ static int lio_get_link_ksettings(struct net_device *netdev,
linfo->link.s.if_mode == INTERFACE_MODE_XLAUI ||
linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
dev_dbg(&oct->pci_dev->dev, "ecmd->base.transceiver is XCVR_EXTERNAL\n");
+ ecmd->base.transceiver = XCVR_EXTERNAL;
} else {
dev_err(&oct->pci_dev->dev, "Unknown link interface mode: %d\n",
linfo->link.s.if_mode);
@@ -277,10 +278,12 @@ static int lio_get_link_ksettings(struct net_device *netdev,
10000baseCR_Full);
}
- if (oct->no_speed_setting == 0)
+ if (oct->no_speed_setting == 0) {
liquidio_get_speed(lio);
- else
+ liquidio_get_fec(lio);
+ } else {
oct->speed_setting = 25;
+ }
if (oct->speed_setting == 10) {
ethtool_link_ksettings_add_link_mode
@@ -304,6 +307,24 @@ static int lio_get_link_ksettings(struct net_device *netdev,
(ecmd, advertising,
25000baseCR_Full);
}
+
+ if (oct->no_speed_setting)
+ break;
+
+ ethtool_link_ksettings_add_link_mode
+ (ecmd, supported, FEC_RS);
+ ethtool_link_ksettings_add_link_mode
+ (ecmd, supported, FEC_NONE);
+ /*FEC_OFF*/
+ if (oct->props[lio->ifidx].fec == 1) {
+ /* ETHTOOL_FEC_RS */
+ ethtool_link_ksettings_add_link_mode
+ (ecmd, advertising, FEC_RS);
+ } else {
+ /* ETHTOOL_FEC_OFF */
+ ethtool_link_ksettings_add_link_mode
+ (ecmd, advertising, FEC_NONE);
+ }
} else { /* VF */
if (linfo->link.s.speed == 10000) {
ethtool_link_ksettings_add_link_mode
@@ -3029,9 +3050,60 @@ static int lio_set_priv_flags(struct net_device *netdev, u32 flags)
return 0;
}
+static int lio_get_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fec)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ fec->active_fec = ETHTOOL_FEC_NONE;
+ fec->fec = ETHTOOL_FEC_NONE;
+
+ if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
+ oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
+ if (oct->no_speed_setting == 1)
+ return 0;
+
+ liquidio_get_fec(lio);
+ fec->fec = (ETHTOOL_FEC_RS | ETHTOOL_FEC_OFF);
+ if (oct->props[lio->ifidx].fec == 1)
+ fec->active_fec = ETHTOOL_FEC_RS;
+ else
+ fec->active_fec = ETHTOOL_FEC_OFF;
+ }
+
+ return 0;
+}
+
+static int lio_set_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fec)
+{
+ struct lio *lio = GET_LIO(netdev);
+ struct octeon_device *oct = lio->oct_dev;
+
+ if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
+ oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
+ if (oct->no_speed_setting == 1)
+ return -EOPNOTSUPP;
+
+ if (fec->fec & ETHTOOL_FEC_OFF)
+ liquidio_set_fec(lio, 0);
+ else if (fec->fec & ETHTOOL_FEC_RS)
+ liquidio_set_fec(lio, 1);
+ else
+ return -EOPNOTSUPP;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static const struct ethtool_ops lio_ethtool_ops = {
.get_link_ksettings = lio_get_link_ksettings,
.set_link_ksettings = lio_set_link_ksettings,
+ .get_fecparam = lio_get_fecparam,
+ .set_fecparam = lio_set_fecparam,
.get_link = ethtool_op_get_link,
.get_drvinfo = lio_get_drvinfo,
.get_ringparam = lio_ethtool_get_ringparam,
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 0aba1f7..f42c1b0 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3761,6 +3761,14 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
octeon_dev->speed_setting = 10;
}
octeon_dev->speed_boot = octeon_dev->speed_setting;
+
+ /* don't read FEC setting if unsupported by f/w (see above) */
+ if (octeon_dev->speed_boot == 25 &&
+ !octeon_dev->no_speed_setting) {
+ liquidio_get_fec(lio);
+ octeon_dev->props[lio->ifidx].fec_boot =
+ octeon_dev->props[lio->ifidx].fec;
+ }
}
devlink = devlink_alloc(&liquidio_devlink_ops,
diff --git a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
index 8fcb07d..a5e0e9f 100644
--- a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
+++ b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
@@ -260,6 +260,11 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,
#define OCTNET_CMD_FAIL 0x1
+#define SEAPI_CMD_FEC_SET 0x0
+#define SEAPI_CMD_FEC_SET_DISABLE 0x0
+#define SEAPI_CMD_FEC_SET_RS 0x1
+#define SEAPI_CMD_FEC_GET 0x1
+
#define SEAPI_CMD_SPEED_SET 0x2
#define SEAPI_CMD_SPEED_GET 0x3
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
index 881e40d..3d01d36 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
@@ -316,6 +316,8 @@ struct octdev_props {
* device pointer (used for OS specific calls).
*/
int rx_on;
+ int fec;
+ int fec_boot;
int napi_enabled;
int gmxport;
struct net_device *netdev;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
index beb3eec..50201fc 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
@@ -84,7 +84,10 @@ struct oct_nic_stats_ctrl {
struct oct_nic_seapi_resp {
u64 rh;
- u32 speed;
+ union {
+ u32 fec_setting;
+ u32 speed;
+ };
u64 status;
};
@@ -236,6 +239,8 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_qs);
int liquidio_get_speed(struct lio *lio);
int liquidio_set_speed(struct lio *lio, int speed);
+int liquidio_get_fec(struct lio *lio);
+int liquidio_set_fec(struct lio *lio, int on_off);
/**
* \brief Net device change_mtu
^ permalink raw reply related
* Re: [PATCH net-next v4 18/20] crypto: port ChaCha20 to Zinc
From: kbuild test robot @ 2018-09-17 11:35 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: kbuild-all, linux-kernel, netdev, linux-crypto, davem, gregkh,
Jason A. Donenfeld, Samuel Neves, Andy Lutomirski,
Jean-Philippe Aumasson, Eric Biggers
In-Reply-To: <20180914162240.7925-19-Jason@zx2c4.com>
[-- Attachment #1: Type: text/plain, Size: 672 bytes --]
Hi Jason,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Jason-A-Donenfeld/WireGuard-Secure-Network-Tunnel/20180916-043623
config: i386-randconfig-s3-09171149 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
>> ERROR: "chacha20" [crypto/chacha20_zinc.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29188 bytes --]
^ permalink raw reply
* Wohltätigkeitsspende in Höhe von € 2.000.000,00
From: mxicali @ 2018-09-16 17:51 UTC (permalink / raw)
To: Recipients
Lieber Freund,
Ich bin Herr Tayeb Souami, New Jersey, Vereinigte Staaten von Amerika, der Mega-Gewinner von $ 315million In Mega Millions Jackpot, spende ich an 5 zufällige Personen, wenn Sie diese E-Mail erhalten, dann wurde Ihre E-Mail nach einem Spinball ausgewählt.Ich habe den größten Teil meines Vermögens auf eine Reihe von Wohltätigkeitsorganisationen und Organisationen verteilt.Ich habe mich freiwillig dazu entschieden, die Summe von € 2.000.000,00 an Sie als eine der ausgewählten 5 zu spenden, um meine Gewinne zu überprüfen, sehen Sie bitte meine You Tube Seite unten.
UHR MICH HIER: https://www.youtube.com/watch?v=Z6ui8ZDQ6Ks
Das ist dein Spendencode: [DFC530342018]
Antworten Sie mit dem SPENDE-CODE an diese E-Mail: financialfundingcompany09@gmail.com
Ich hoffe, Sie und Ihre Familie glücklich zu machen.
Grüße
Herr Tayeb Souami
^ permalink raw reply
* Re: [PATCH] powerpc: fix csum_ipv6_magic() on little endian platforms
From: Christophe LEROY @ 2018-09-17 12:27 UTC (permalink / raw)
To: Michael Ellerman
Cc: Xin Long, benh, paulus, jishi, LKML, linuxppc-dev, stable,
netdev@vger.kernel.org, David Miller
In-Reply-To: <CADvbK_c+VVoC=tcX4z-NbX6xGHfkzzNuBXoMHFJfZdiBMzX3+w@mail.gmail.com>
Hi Michael,
Le 10/09/2018 à 16:28, Xin Long a écrit :
> On Mon, Sep 10, 2018 at 2:09 PM Christophe Leroy
> <christophe.leroy@c-s.fr> wrote:
>>
>> On little endian platforms, csum_ipv6_magic() keeps len and proto in
>> CPU byte order. This generates a bad results leading to ICMPv6 packets
>> from other hosts being dropped by powerpc64le platforms.
>>
>> In order to fix this, len and proto should be converted to network
>> byte order ie bigendian byte order. However checksumming 0x12345678
>> and 0x56341278 provide the exact same result so it is enough to
>> rotate the sum of len and proto by 1 byte.
>>
>> PPC32 only support bigendian so the fix is needed for PPC64 only
>>
>> Fixes: e9c4943a107b ("powerpc: Implement csum_ipv6_magic in assembly")
>> Reported-by: Jianlin Shi <jishi@redhat.com>
>> Reported-by: Xin Long <lucien.xin@gmail.com>
>> Cc: <stable@vger.kernel.org> # 4.18+
>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>> ---
>> arch/powerpc/lib/checksum_64.S | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
>> index 886ed94b9c13..2a68c43e13f5 100644
>> --- a/arch/powerpc/lib/checksum_64.S
>> +++ b/arch/powerpc/lib/checksum_64.S
>> @@ -443,6 +443,9 @@ _GLOBAL(csum_ipv6_magic)
>> addc r0, r8, r9
>> ld r10, 0(r4)
>> ld r11, 8(r4)
>> +#ifndef CONFIG_CPU_BIG_ENDIAN
>> + rotldi r5, r5, 8
>> +#endif
>> adde r0, r0, r10
>> add r5, r5, r7
>> adde r0, r0, r11
>> --
>> 2.13.3
>>
> Tested-by: Xin Long <lucien.xin@gmail.com>
>
Could you take this fix for 4.19 ?
Unless someone takes it through the netdev tree ?
Thanks
Christophe
^ permalink raw reply
* [PATCH net-next v2 00/10] Refactor classifier API to work with Qdisc/blocks without rtnl lock
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
Currently, all netlink protocol handlers for updating rules, actions and
qdiscs are protected with single global rtnl lock which removes any
possibility for parallelism. This patch set is a third step to remove
rtnl lock dependency from TC rules update path.
Recently, new rtnl registration flag RTNL_FLAG_DOIT_UNLOCKED was added.
Handlers registered with this flag are called without RTNL taken. End
goal is to have rule update handlers(RTM_NEWTFILTER, RTM_DELTFILTER,
etc.) to be registered with UNLOCKED flag to allow parallel execution.
However, there is no intention to completely remove or split rtnl lock
itself. This patch set addresses specific problems in implementation of
classifiers API that prevent its control path from being executed
concurrently. Additional changes are required to refactor classifiers
API and individual classifiers for parallel execution. This patch set
lays groundwork to eventually register rule update handlers as
rtnl-unlocked by modifying code in cls API that works with Qdiscs and
blocks. Following patch set does the same for chains and classifiers.
The goal of this change is to refactor tcf_block_find() and its
dependencies to allow concurrent execution:
- Extend Qdisc API with rcu to lookup and take reference to Qdisc
without relying on rtnl lock.
- Extend tcf_block with atomic reference counting and rcu.
- Always take reference to tcf_block while working with it.
- Implement tcf_block_release() to release resources obtained by
tcf_block_find()
- Create infrastructure to allow registering Qdiscs with class ops that
do not require the caller to hold rtnl lock.
All three netlink rule update handlers use tcf_block_find() to lookup
Qdisc and block, and this patch set introduces additional means of
synchronization to substitute rtnl lock in cls API.
Some functions in cls and sch APIs have historic names that no longer
clearly describe their intent. In order not make this code even more
confusing when introducing their concurrency-friendly versions, rename
these functions to describe actual implementation.
Changes from V1 to V2:
- Rebase on latest net-next.
- Patch 8 - remove.
- Patch 9 - fold into patch 11.
- Patch 11:
- Rename tcf_block_{get|put}() to tcf_block_refcnt_{get|put}().
- Patch 13 - remove.
Vlad Buslov (10):
net: core: netlink: add helper refcount dec and lock function
net: sched: rename qdisc_destroy() to qdisc_put()
net: sched: extend Qdisc with rcu
net: sched: add helper function to take reference to Qdisc
net: sched: use Qdisc rcu API instead of relying on rtnl lock
net: sched: change tcf block reference counter type to refcount_t
net: sched: implement functions to put and flush all chains
net: sched: protect block idr with spinlock
net: sched: implement tcf_block_refcnt_{get|put}()
net: sched: use reference counting for tcf blocks on rules update
include/linux/rtnetlink.h | 6 ++
include/net/pkt_sched.h | 1 +
include/net/sch_generic.h | 20 +++-
net/core/rtnetlink.c | 6 ++
net/sched/cls_api.c | 250 +++++++++++++++++++++++++++++++++-------------
net/sched/sch_api.c | 24 ++++-
net/sched/sch_atm.c | 2 +-
net/sched/sch_cbq.c | 2 +-
net/sched/sch_cbs.c | 2 +-
net/sched/sch_drr.c | 4 +-
net/sched/sch_dsmark.c | 2 +-
net/sched/sch_fifo.c | 2 +-
net/sched/sch_generic.c | 48 +++++++--
net/sched/sch_hfsc.c | 2 +-
net/sched/sch_htb.c | 4 +-
net/sched/sch_mq.c | 4 +-
net/sched/sch_mqprio.c | 4 +-
net/sched/sch_multiq.c | 6 +-
net/sched/sch_netem.c | 2 +-
net/sched/sch_prio.c | 6 +-
net/sched/sch_qfq.c | 4 +-
net/sched/sch_red.c | 4 +-
net/sched/sch_sfb.c | 4 +-
net/sched/sch_tbf.c | 4 +-
24 files changed, 301 insertions(+), 112 deletions(-)
--
2.7.5
^ permalink raw reply
* [PATCH net-next v2 06/10] net: sched: change tcf block reference counter type to refcount_t
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
As a preparation for removing rtnl lock dependency from rules update path,
change tcf block reference counter type to refcount_t to allow modification
by concurrent users.
In block put function perform decrement and check reference counter once to
accommodate concurrent modification by unlocked users. After this change
tcf_chain_put at the end of block put function is called with
block->refcnt==0 and will deallocate block after the last chain is
released, so there is no need to manually deallocate block in this case.
However, if block reference counter reached 0 and there are no chains to
release, block must still be deallocated manually.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/sch_generic.h | 2 +-
net/sched/cls_api.c | 59 ++++++++++++++++++++++++++++-------------------
2 files changed, 36 insertions(+), 25 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 9a295e690efe..45fee65468d0 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -345,7 +345,7 @@ struct tcf_chain {
struct tcf_block {
struct list_head chain_list;
u32 index; /* block index for shared blocks */
- unsigned int refcnt;
+ refcount_t refcnt;
struct net *net;
struct Qdisc *q;
struct list_head cb_list;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index cfa4a02a6a1a..c3c7d4e2f84c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -240,7 +240,7 @@ static void tcf_chain_destroy(struct tcf_chain *chain)
if (!chain->index)
block->chain0.chain = NULL;
kfree(chain);
- if (list_empty(&block->chain_list) && block->refcnt == 0)
+ if (list_empty(&block->chain_list) && !refcount_read(&block->refcnt))
kfree(block);
}
@@ -510,7 +510,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
INIT_LIST_HEAD(&block->owner_list);
INIT_LIST_HEAD(&block->chain0.filter_chain_list);
- block->refcnt = 1;
+ refcount_set(&block->refcnt, 1);
block->net = net;
block->index = block_index;
@@ -719,7 +719,7 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
/* block_index not 0 means the shared block is requested */
block = tcf_block_lookup(net, ei->block_index);
if (block)
- block->refcnt++;
+ refcount_inc(&block->refcnt);
}
if (!block) {
@@ -762,7 +762,7 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
err_block_insert:
kfree(block);
} else {
- block->refcnt--;
+ refcount_dec(&block->refcnt);
}
return err;
}
@@ -802,34 +802,45 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
tcf_chain0_head_change_cb_del(block, ei);
tcf_block_owner_del(block, q, ei->binder_type);
- if (block->refcnt == 1) {
- if (tcf_block_shared(block))
- tcf_block_remove(block, block->net);
-
- /* Hold a refcnt for all chains, so that they don't disappear
- * while we are iterating.
+ if (refcount_dec_and_test(&block->refcnt)) {
+ /* Flushing/putting all chains will cause the block to be
+ * deallocated when last chain is freed. However, if chain_list
+ * is empty, block has to be manually deallocated. After block
+ * reference counter reached 0, it is no longer possible to
+ * increment it or add new chains to block.
*/
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_hold(chain);
+ bool free_block = list_empty(&block->chain_list);
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_flush(chain);
- }
+ if (tcf_block_shared(block))
+ tcf_block_remove(block, block->net);
- tcf_block_offload_unbind(block, q, ei);
+ if (!free_block) {
+ /* Hold a refcnt for all chains, so that they don't
+ * disappear while we are iterating.
+ */
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_hold(chain);
- if (block->refcnt == 1) {
- /* At this point, all the chains should have refcnt >= 1. */
- list_for_each_entry_safe(chain, tmp, &block->chain_list, list) {
- tcf_chain_put_explicitly_created(chain);
- tcf_chain_put(chain);
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_flush(chain);
}
- block->refcnt--;
- if (list_empty(&block->chain_list))
+ tcf_block_offload_unbind(block, q, ei);
+
+ if (free_block) {
kfree(block);
+ } else {
+ /* At this point, all the chains should have
+ * refcnt >= 1.
+ */
+ list_for_each_entry_safe(chain, tmp, &block->chain_list,
+ list) {
+ tcf_chain_put_explicitly_created(chain);
+ tcf_chain_put(chain);
+ }
+ }
} else {
- block->refcnt--;
+ tcf_block_offload_unbind(block, q, ei);
}
}
EXPORT_SYMBOL(tcf_block_put_ext);
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 05/10] net: sched: use Qdisc rcu API instead of relying on rtnl lock
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
As a preparation from removing rtnl lock dependency from rules update path,
use Qdisc rcu and reference counting capabilities instead of relying on
rtnl lock while working with Qdiscs. Create new tcf_block_release()
function, and use it to free resources taken by tcf_block_find().
Currently, this function only releases Qdisc and it is extended in next
patches in this series.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_api.c | 88 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 73 insertions(+), 15 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 1a67af8a6e8c..cfa4a02a6a1a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -527,6 +527,17 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index)
return idr_find(&tn->idr, block_index);
}
+static void tcf_qdisc_put(struct Qdisc *q, bool rtnl_held)
+{
+ if (!q)
+ return;
+
+ if (rtnl_held)
+ qdisc_put(q);
+ else
+ qdisc_put_unlocked(q);
+}
+
/* Find tcf block.
* Set q, parent, cl when appropriate.
*/
@@ -537,6 +548,7 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
struct netlink_ext_ack *extack)
{
struct tcf_block *block;
+ int err = 0;
if (ifindex == TCM_IFINDEX_MAGIC_BLOCK) {
block = tcf_block_lookup(net, block_index);
@@ -548,55 +560,91 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
const struct Qdisc_class_ops *cops;
struct net_device *dev;
+ rcu_read_lock();
+
/* Find link */
- dev = __dev_get_by_index(net, ifindex);
- if (!dev)
+ dev = dev_get_by_index_rcu(net, ifindex);
+ if (!dev) {
+ rcu_read_unlock();
return ERR_PTR(-ENODEV);
+ }
/* Find qdisc */
if (!*parent) {
*q = dev->qdisc;
*parent = (*q)->handle;
} else {
- *q = qdisc_lookup(dev, TC_H_MAJ(*parent));
+ *q = qdisc_lookup_rcu(dev, TC_H_MAJ(*parent));
if (!*q) {
NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists");
- return ERR_PTR(-EINVAL);
+ err = -EINVAL;
+ goto errout_rcu;
}
}
+ *q = qdisc_refcount_inc_nz(*q);
+ if (!*q) {
+ NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists");
+ err = -EINVAL;
+ goto errout_rcu;
+ }
+
/* Is it classful? */
cops = (*q)->ops->cl_ops;
if (!cops) {
NL_SET_ERR_MSG(extack, "Qdisc not classful");
- return ERR_PTR(-EINVAL);
+ err = -EINVAL;
+ goto errout_rcu;
}
if (!cops->tcf_block) {
NL_SET_ERR_MSG(extack, "Class doesn't support blocks");
- return ERR_PTR(-EOPNOTSUPP);
+ err = -EOPNOTSUPP;
+ goto errout_rcu;
}
+ /* At this point we know that qdisc is not noop_qdisc,
+ * which means that qdisc holds a reference to net_device
+ * and we hold a reference to qdisc, so it is safe to release
+ * rcu read lock.
+ */
+ rcu_read_unlock();
+
/* Do we search for filter, attached to class? */
if (TC_H_MIN(*parent)) {
*cl = cops->find(*q, *parent);
if (*cl == 0) {
NL_SET_ERR_MSG(extack, "Specified class doesn't exist");
- return ERR_PTR(-ENOENT);
+ err = -ENOENT;
+ goto errout_qdisc;
}
}
/* And the last stroke */
block = cops->tcf_block(*q, *cl, extack);
- if (!block)
- return ERR_PTR(-EINVAL);
+ if (!block) {
+ err = -EINVAL;
+ goto errout_qdisc;
+ }
if (tcf_block_shared(block)) {
NL_SET_ERR_MSG(extack, "This filter block is shared. Please use the block index to manipulate the filters");
- return ERR_PTR(-EOPNOTSUPP);
+ err = -EOPNOTSUPP;
+ goto errout_qdisc;
}
}
return block;
+
+errout_rcu:
+ rcu_read_unlock();
+errout_qdisc:
+ tcf_qdisc_put(*q, true);
+ return ERR_PTR(err);
+}
+
+static void tcf_block_release(struct Qdisc *q, struct tcf_block *block)
+{
+ tcf_qdisc_put(q, true);
}
struct tcf_block_owner_item {
@@ -1332,6 +1380,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
errout:
if (chain)
tcf_chain_put(chain);
+ tcf_block_release(q, block);
if (err == -EAGAIN)
/* Replay the request. */
goto replay;
@@ -1453,6 +1502,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
errout:
if (chain)
tcf_chain_put(chain);
+ tcf_block_release(q, block);
return err;
}
@@ -1538,6 +1588,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
errout:
if (chain)
tcf_chain_put(chain);
+ tcf_block_release(q, block);
return err;
}
@@ -1854,7 +1905,8 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0;
if (chain_index > TC_ACT_EXT_VAL_MASK) {
NL_SET_ERR_MSG(extack, "Specified chain index exceeds upper limit");
- return -EINVAL;
+ err = -EINVAL;
+ goto errout_block;
}
chain = tcf_chain_lookup(block, chain_index);
if (n->nlmsg_type == RTM_NEWCHAIN) {
@@ -1866,23 +1918,27 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
tcf_chain_hold(chain);
} else {
NL_SET_ERR_MSG(extack, "Filter chain already exists");
- return -EEXIST;
+ err = -EEXIST;
+ goto errout_block;
}
} else {
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain");
- return -ENOENT;
+ err = -ENOENT;
+ goto errout_block;
}
chain = tcf_chain_create(block, chain_index);
if (!chain) {
NL_SET_ERR_MSG(extack, "Failed to create filter chain");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto errout_block;
}
}
} else {
if (!chain || tcf_chain_held_by_acts_only(chain)) {
NL_SET_ERR_MSG(extack, "Cannot find specified filter chain");
- return -EINVAL;
+ err = -EINVAL;
+ goto errout_block;
}
tcf_chain_hold(chain);
}
@@ -1924,6 +1980,8 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
errout:
tcf_chain_put(chain);
+errout_block:
+ tcf_block_release(q, block);
if (err == -EAGAIN)
/* Replay the request. */
goto replay;
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 10/10] net: sched: use reference counting for tcf blocks on rules update
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
In order to remove dependency on rtnl lock on rules update path, always
take reference to block while using it on rules update path. Change
tcf_block_get() error handling to properly release block with reference
counting, instead of just destroying it, in order to accommodate potential
concurrent users.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_api.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 0a7a3ace2da9..6a3eec5dbdf1 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -633,7 +633,7 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
int err = 0;
if (ifindex == TCM_IFINDEX_MAGIC_BLOCK) {
- block = tcf_block_lookup(net, block_index);
+ block = tcf_block_refcnt_get(net, block_index);
if (!block) {
NL_SET_ERR_MSG(extack, "Block of given index was not found");
return ERR_PTR(-EINVAL);
@@ -713,6 +713,14 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
err = -EOPNOTSUPP;
goto errout_qdisc;
}
+
+ /* Always take reference to block in order to support execution
+ * of rules update path of cls API without rtnl lock. Caller
+ * must release block when it is finished using it. 'if' block
+ * of this conditional obtain reference to block by calling
+ * tcf_block_refcnt_get().
+ */
+ refcount_inc(&block->refcnt);
}
return block;
@@ -726,6 +734,8 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
static void tcf_block_release(struct Qdisc *q, struct tcf_block *block)
{
+ if (!IS_ERR_OR_NULL(block))
+ tcf_block_refcnt_put(block);
tcf_qdisc_put(q, true);
}
@@ -794,21 +804,16 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
{
struct net *net = qdisc_net(q);
struct tcf_block *block = NULL;
- bool created = false;
int err;
- if (ei->block_index) {
+ if (ei->block_index)
/* block_index not 0 means the shared block is requested */
- block = tcf_block_lookup(net, ei->block_index);
- if (block)
- refcount_inc(&block->refcnt);
- }
+ block = tcf_block_refcnt_get(net, ei->block_index);
if (!block) {
block = tcf_block_create(net, q, ei->block_index, extack);
if (IS_ERR(block))
return PTR_ERR(block);
- created = true;
if (tcf_block_shared(block)) {
err = tcf_block_insert(block, net, extack);
if (err)
@@ -838,14 +843,8 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
err_chain0_head_change_cb_add:
tcf_block_owner_del(block, q, ei->binder_type);
err_block_owner_add:
- if (created) {
- if (tcf_block_shared(block))
- tcf_block_remove(block, net);
err_block_insert:
- kfree_rcu(block, rcu);
- } else {
- refcount_dec(&block->refcnt);
- }
+ tcf_block_refcnt_put(block);
return err;
}
EXPORT_SYMBOL(tcf_block_get_ext);
@@ -1739,7 +1738,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
return err;
if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) {
- block = tcf_block_lookup(net, tcm->tcm_block_index);
+ block = tcf_block_refcnt_get(net, tcm->tcm_block_index);
if (!block)
goto out;
/* If we work with block index, q is NULL and parent value
@@ -1798,6 +1797,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
}
}
+ if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK)
+ tcf_block_refcnt_put(block);
cb->args[0] = index;
out:
@@ -2062,7 +2063,7 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
return err;
if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) {
- block = tcf_block_lookup(net, tcm->tcm_block_index);
+ block = tcf_block_refcnt_get(net, tcm->tcm_block_index);
if (!block)
goto out;
/* If we work with block index, q is NULL and parent value
@@ -2129,6 +2130,8 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
index++;
}
+ if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK)
+ tcf_block_refcnt_put(block);
cb->args[0] = index;
out:
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 02/10] net: sched: rename qdisc_destroy() to qdisc_put()
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
Current implementation of qdisc_destroy() decrements Qdisc reference
counter and only actually destroy Qdisc if reference counter value reached
zero. Rename qdisc_destroy() to qdisc_put() in order for it to better
describe the way in which this function currently implemented and used.
Extract code that deallocates Qdisc into new private qdisc_destroy()
function. It is intended to be shared between regular qdisc_put() and its
unlocked version that is introduced in next patch in this series.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/sch_generic.h | 2 +-
net/sched/sch_api.c | 6 +++---
net/sched/sch_atm.c | 2 +-
net/sched/sch_cbq.c | 2 +-
net/sched/sch_cbs.c | 2 +-
net/sched/sch_drr.c | 4 ++--
net/sched/sch_dsmark.c | 2 +-
net/sched/sch_fifo.c | 2 +-
net/sched/sch_generic.c | 23 ++++++++++++++---------
net/sched/sch_hfsc.c | 2 +-
net/sched/sch_htb.c | 4 ++--
net/sched/sch_mq.c | 4 ++--
net/sched/sch_mqprio.c | 4 ++--
net/sched/sch_multiq.c | 6 +++---
net/sched/sch_netem.c | 2 +-
net/sched/sch_prio.c | 6 +++---
net/sched/sch_qfq.c | 4 ++--
net/sched/sch_red.c | 4 ++--
net/sched/sch_sfb.c | 4 ++--
net/sched/sch_tbf.c | 4 ++--
20 files changed, 47 insertions(+), 42 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index d326fd553b58..fadb1a4d4ee8 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -554,7 +554,7 @@ void dev_deactivate_many(struct list_head *head);
struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
struct Qdisc *qdisc);
void qdisc_reset(struct Qdisc *qdisc);
-void qdisc_destroy(struct Qdisc *qdisc);
+void qdisc_put(struct Qdisc *qdisc);
void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
unsigned int len);
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 411c40344b77..2096138c4bf6 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -920,7 +920,7 @@ static void notify_and_destroy(struct net *net, struct sk_buff *skb,
qdisc_notify(net, skb, n, clid, old, new);
if (old)
- qdisc_destroy(old);
+ qdisc_put(old);
}
/* Graft qdisc "new" to class "classid" of qdisc "parent" or
@@ -973,7 +973,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
qdisc_refcount_inc(new);
if (!ingress)
- qdisc_destroy(old);
+ qdisc_put(old);
}
skip:
@@ -1561,7 +1561,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
err = qdisc_graft(dev, p, skb, n, clid, q, NULL, extack);
if (err) {
if (q)
- qdisc_destroy(q);
+ qdisc_put(q);
return err;
}
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index cd49afca9617..d714d3747bcb 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -150,7 +150,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
pr_debug("atm_tc_put: destroying\n");
list_del_init(&flow->list);
pr_debug("atm_tc_put: qdisc %p\n", flow->q);
- qdisc_destroy(flow->q);
+ qdisc_put(flow->q);
tcf_block_put(flow->block);
if (flow->sock) {
pr_debug("atm_tc_put: f_count %ld\n",
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index f42025d53cfe..4dc05409e3fb 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1418,7 +1418,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
WARN_ON(cl->filters);
tcf_block_put(cl->block);
- qdisc_destroy(cl->q);
+ qdisc_put(cl->q);
qdisc_put_rtab(cl->R_tab);
gen_kill_estimator(&cl->rate_est);
if (cl != &q->link)
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index e26a24017faa..e689e11b6d0f 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -379,7 +379,7 @@ static void cbs_destroy(struct Qdisc *sch)
cbs_disable_offload(dev, q);
if (q->qdisc)
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
}
static int cbs_dump(struct Qdisc *sch, struct sk_buff *skb)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index e0b0cf8a9939..cdebaed0f8cf 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -134,7 +134,7 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
tca[TCA_RATE]);
if (err) {
NL_SET_ERR_MSG(extack, "Failed to replace estimator");
- qdisc_destroy(cl->qdisc);
+ qdisc_put(cl->qdisc);
kfree(cl);
return err;
}
@@ -153,7 +153,7 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
static void drr_destroy_class(struct Qdisc *sch, struct drr_class *cl)
{
gen_kill_estimator(&cl->rate_est);
- qdisc_destroy(cl->qdisc);
+ qdisc_put(cl->qdisc);
kfree(cl);
}
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 049714c57075..f6f480784bc6 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -412,7 +412,7 @@ static void dsmark_destroy(struct Qdisc *sch)
pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
tcf_block_put(p->block);
- qdisc_destroy(p->q);
+ qdisc_put(p->q);
if (p->mv != p->embedded)
kfree(p->mv);
}
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 24893d3b5d22..3809c9bf8896 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -177,7 +177,7 @@ struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
if (q) {
err = fifo_set_limit(q, limit);
if (err < 0) {
- qdisc_destroy(q);
+ qdisc_put(q);
q = NULL;
}
}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index a64132a5db36..3e7696f3e053 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -901,7 +901,7 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
if (!ops->init || ops->init(sch, NULL, extack) == 0)
return sch;
- qdisc_destroy(sch);
+ qdisc_put(sch);
return NULL;
}
EXPORT_SYMBOL(qdisc_create_dflt);
@@ -941,15 +941,11 @@ void qdisc_free(struct Qdisc *qdisc)
kfree((char *) qdisc - qdisc->padded);
}
-void qdisc_destroy(struct Qdisc *qdisc)
+static void qdisc_destroy(struct Qdisc *qdisc)
{
const struct Qdisc_ops *ops = qdisc->ops;
struct sk_buff *skb, *tmp;
- if (qdisc->flags & TCQ_F_BUILTIN ||
- !refcount_dec_and_test(&qdisc->refcnt))
- return;
-
#ifdef CONFIG_NET_SCHED
qdisc_hash_del(qdisc);
@@ -976,7 +972,16 @@ void qdisc_destroy(struct Qdisc *qdisc)
qdisc_free(qdisc);
}
-EXPORT_SYMBOL(qdisc_destroy);
+
+void qdisc_put(struct Qdisc *qdisc)
+{
+ if (qdisc->flags & TCQ_F_BUILTIN ||
+ !refcount_dec_and_test(&qdisc->refcnt))
+ return;
+
+ qdisc_destroy(qdisc);
+}
+EXPORT_SYMBOL(qdisc_put);
/* Attach toplevel qdisc to device queue. */
struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
@@ -1270,7 +1275,7 @@ static void shutdown_scheduler_queue(struct net_device *dev,
rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
dev_queue->qdisc_sleeping = qdisc_default;
- qdisc_destroy(qdisc);
+ qdisc_put(qdisc);
}
}
@@ -1279,7 +1284,7 @@ void dev_shutdown(struct net_device *dev)
netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
if (dev_ingress_queue(dev))
shutdown_scheduler_queue(dev, dev_ingress_queue(dev), &noop_qdisc);
- qdisc_destroy(dev->qdisc);
+ qdisc_put(dev->qdisc);
dev->qdisc = &noop_qdisc;
WARN_ON(timer_pending(&dev->watchdog_timer));
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 3278a76f6861..b18ec1f6de60 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1092,7 +1092,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
struct hfsc_sched *q = qdisc_priv(sch);
tcf_block_put(cl->block);
- qdisc_destroy(cl->qdisc);
+ qdisc_put(cl->qdisc);
gen_kill_estimator(&cl->rate_est);
if (cl != &q->root)
kfree(cl);
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 18ac2d6ca294..58b449490757 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1208,7 +1208,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
{
if (!cl->level) {
WARN_ON(!cl->leaf.q);
- qdisc_destroy(cl->leaf.q);
+ qdisc_put(cl->leaf.q);
}
gen_kill_estimator(&cl->rate_est);
tcf_block_put(cl->block);
@@ -1409,7 +1409,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
/* turn parent into inner node */
qdisc_reset(parent->leaf.q);
qdisc_tree_reduce_backlog(parent->leaf.q, qlen, backlog);
- qdisc_destroy(parent->leaf.q);
+ qdisc_put(parent->leaf.q);
if (parent->prio_activity)
htb_deactivate(q, parent);
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index d6b8ae4ed7a3..f20f3a0f8424 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -65,7 +65,7 @@ static void mq_destroy(struct Qdisc *sch)
if (!priv->qdiscs)
return;
for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
- qdisc_destroy(priv->qdiscs[ntx]);
+ qdisc_put(priv->qdiscs[ntx]);
kfree(priv->qdiscs);
}
@@ -119,7 +119,7 @@ static void mq_attach(struct Qdisc *sch)
qdisc = priv->qdiscs[ntx];
old = dev_graft_qdisc(qdisc->dev_queue, qdisc);
if (old)
- qdisc_destroy(old);
+ qdisc_put(old);
#ifdef CONFIG_NET_SCHED
if (ntx < dev->real_num_tx_queues)
qdisc_hash_add(qdisc, false);
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index 0e9d761cdd80..d364e63c396d 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -40,7 +40,7 @@ static void mqprio_destroy(struct Qdisc *sch)
for (ntx = 0;
ntx < dev->num_tx_queues && priv->qdiscs[ntx];
ntx++)
- qdisc_destroy(priv->qdiscs[ntx]);
+ qdisc_put(priv->qdiscs[ntx]);
kfree(priv->qdiscs);
}
@@ -300,7 +300,7 @@ static void mqprio_attach(struct Qdisc *sch)
qdisc = priv->qdiscs[ntx];
old = dev_graft_qdisc(qdisc->dev_queue, qdisc);
if (old)
- qdisc_destroy(old);
+ qdisc_put(old);
if (ntx < dev->real_num_tx_queues)
qdisc_hash_add(qdisc, false);
}
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 1da7ea8de0ad..7410ce4d0321 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -175,7 +175,7 @@ multiq_destroy(struct Qdisc *sch)
tcf_block_put(q->block);
for (band = 0; band < q->bands; band++)
- qdisc_destroy(q->queues[band]);
+ qdisc_put(q->queues[band]);
kfree(q->queues);
}
@@ -204,7 +204,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
q->queues[i] = &noop_qdisc;
qdisc_tree_reduce_backlog(child, child->q.qlen,
child->qstats.backlog);
- qdisc_destroy(child);
+ qdisc_put(child);
}
}
@@ -228,7 +228,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
qdisc_tree_reduce_backlog(old,
old->q.qlen,
old->qstats.backlog);
- qdisc_destroy(old);
+ qdisc_put(old);
}
sch_tree_unlock(sch);
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 506e1960ed7f..57b3ad9394ad 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -1022,7 +1022,7 @@ static void netem_destroy(struct Qdisc *sch)
qdisc_watchdog_cancel(&q->watchdog);
if (q->qdisc)
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
dist_free(q->delay_dist);
dist_free(q->slot_dist);
}
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 222e53d3d27a..f8af98621179 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -175,7 +175,7 @@ prio_destroy(struct Qdisc *sch)
tcf_block_put(q->block);
prio_offload(sch, NULL);
for (prio = 0; prio < q->bands; prio++)
- qdisc_destroy(q->queues[prio]);
+ qdisc_put(q->queues[prio]);
}
static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
@@ -205,7 +205,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
extack);
if (!queues[i]) {
while (i > oldbands)
- qdisc_destroy(queues[--i]);
+ qdisc_put(queues[--i]);
return -ENOMEM;
}
}
@@ -220,7 +220,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
qdisc_tree_reduce_backlog(child, child->q.qlen,
child->qstats.backlog);
- qdisc_destroy(child);
+ qdisc_put(child);
}
for (i = oldbands; i < q->bands; i++) {
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index bb1a9c11fc54..dc37c4ead439 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -526,7 +526,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
return 0;
destroy_class:
- qdisc_destroy(cl->qdisc);
+ qdisc_put(cl->qdisc);
kfree(cl);
return err;
}
@@ -537,7 +537,7 @@ static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
qfq_rm_from_agg(q, cl);
gen_kill_estimator(&cl->rate_est);
- qdisc_destroy(cl->qdisc);
+ qdisc_put(cl->qdisc);
kfree(cl);
}
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 56c181c3feeb..3ce6c0a2c493 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -181,7 +181,7 @@ static void red_destroy(struct Qdisc *sch)
del_timer_sync(&q->adapt_timer);
red_offload(sch, false);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
}
static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
@@ -233,7 +233,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt,
if (child) {
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
q->qdisc->qstats.backlog);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
q->qdisc = child;
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 7cbdad8419b7..bab506b01a32 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -469,7 +469,7 @@ static void sfb_destroy(struct Qdisc *sch)
struct sfb_sched_data *q = qdisc_priv(sch);
tcf_block_put(q->block);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
}
static const struct nla_policy sfb_policy[TCA_SFB_MAX + 1] = {
@@ -523,7 +523,7 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt,
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
q->qdisc->qstats.backlog);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
q->qdisc = child;
q->rehash_interval = msecs_to_jiffies(ctl->rehash_interval);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index a4530e85bd02..942dcca09cf2 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -392,7 +392,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
if (child) {
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
q->qdisc->qstats.backlog);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
q->qdisc = child;
}
q->limit = qopt->limit;
@@ -438,7 +438,7 @@ static void tbf_destroy(struct Qdisc *sch)
struct tbf_sched_data *q = qdisc_priv(sch);
qdisc_watchdog_cancel(&q->watchdog);
- qdisc_destroy(q->qdisc);
+ qdisc_put(q->qdisc);
}
static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 08/10] net: sched: protect block idr with spinlock
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
Protect block idr access with spinlock, instead of relying on rtnl lock.
Take tn->idr_lock spinlock during block insertion and removal.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_api.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 58b2d8443f6a..924723fb74f6 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -473,6 +473,7 @@ tcf_chain0_head_change_cb_del(struct tcf_block *block,
}
struct tcf_net {
+ spinlock_t idr_lock; /* Protects idr */
struct idr idr;
};
@@ -482,16 +483,25 @@ static int tcf_block_insert(struct tcf_block *block, struct net *net,
struct netlink_ext_ack *extack)
{
struct tcf_net *tn = net_generic(net, tcf_net_id);
+ int err;
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&tn->idr_lock);
+ err = idr_alloc_u32(&tn->idr, block, &block->index, block->index,
+ GFP_NOWAIT);
+ spin_unlock(&tn->idr_lock);
+ idr_preload_end();
- return idr_alloc_u32(&tn->idr, block, &block->index, block->index,
- GFP_KERNEL);
+ return err;
}
static void tcf_block_remove(struct tcf_block *block, struct net *net)
{
struct tcf_net *tn = net_generic(net, tcf_net_id);
+ spin_lock(&tn->idr_lock);
idr_remove(&tn->idr, block->index);
+ spin_unlock(&tn->idr_lock);
}
static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
@@ -2285,6 +2295,7 @@ static __net_init int tcf_net_init(struct net *net)
{
struct tcf_net *tn = net_generic(net, tcf_net_id);
+ spin_lock_init(&tn->idr_lock);
idr_init(&tn->idr);
return 0;
}
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 07/10] net: sched: implement functions to put and flush all chains
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
Extract code that flushes and puts all chains on tcf block to two
standalone function to be shared with functions that locklessly get/put
reference to block.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_api.c | 55 +++++++++++++++++++++++++++++------------------------
1 file changed, 30 insertions(+), 25 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c3c7d4e2f84c..58b2d8443f6a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -538,6 +538,31 @@ static void tcf_qdisc_put(struct Qdisc *q, bool rtnl_held)
qdisc_put_unlocked(q);
}
+static void tcf_block_flush_all_chains(struct tcf_block *block)
+{
+ struct tcf_chain *chain;
+
+ /* Hold a refcnt for all chains, so that they don't disappear
+ * while we are iterating.
+ */
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_hold(chain);
+
+ list_for_each_entry(chain, &block->chain_list, list)
+ tcf_chain_flush(chain);
+}
+
+static void tcf_block_put_all_chains(struct tcf_block *block)
+{
+ struct tcf_chain *chain, *tmp;
+
+ /* At this point, all the chains should have refcnt >= 1. */
+ list_for_each_entry_safe(chain, tmp, &block->chain_list, list) {
+ tcf_chain_put_explicitly_created(chain);
+ tcf_chain_put(chain);
+ }
+}
+
/* Find tcf block.
* Set q, parent, cl when appropriate.
*/
@@ -795,8 +820,6 @@ EXPORT_SYMBOL(tcf_block_get);
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
struct tcf_block_ext_info *ei)
{
- struct tcf_chain *chain, *tmp;
-
if (!block)
return;
tcf_chain0_head_change_cb_del(block, ei);
@@ -813,32 +836,14 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
if (tcf_block_shared(block))
tcf_block_remove(block, block->net);
-
- if (!free_block) {
- /* Hold a refcnt for all chains, so that they don't
- * disappear while we are iterating.
- */
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_hold(chain);
-
- list_for_each_entry(chain, &block->chain_list, list)
- tcf_chain_flush(chain);
- }
-
+ if (!free_block)
+ tcf_block_flush_all_chains(block);
tcf_block_offload_unbind(block, q, ei);
- if (free_block) {
+ if (free_block)
kfree(block);
- } else {
- /* At this point, all the chains should have
- * refcnt >= 1.
- */
- list_for_each_entry_safe(chain, tmp, &block->chain_list,
- list) {
- tcf_chain_put_explicitly_created(chain);
- tcf_chain_put(chain);
- }
- }
+ else
+ tcf_block_put_all_chains(block);
} else {
tcf_block_offload_unbind(block, q, ei);
}
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 04/10] net: sched: add helper function to take reference to Qdisc
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
Implement function to take reference to Qdisc that relies on rcu read lock
instead of rtnl mutex. Function only takes reference to Qdisc if reference
counter isn't zero. Intended to be used by unlocked cls API.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/sch_generic.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 8a0d1523d11b..9a295e690efe 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -115,6 +115,19 @@ static inline void qdisc_refcount_inc(struct Qdisc *qdisc)
refcount_inc(&qdisc->refcnt);
}
+/* Intended to be used by unlocked users, when concurrent qdisc release is
+ * possible.
+ */
+
+static inline struct Qdisc *qdisc_refcount_inc_nz(struct Qdisc *qdisc)
+{
+ if (qdisc->flags & TCQ_F_BUILTIN)
+ return qdisc;
+ if (refcount_inc_not_zero(&qdisc->refcnt))
+ return qdisc;
+ return NULL;
+}
+
static inline bool qdisc_is_running(struct Qdisc *qdisc)
{
if (qdisc->flags & TCQ_F_NOLOCK)
--
2.7.5
^ permalink raw reply related
* [PATCH net-next v2 09/10] net: sched: implement tcf_block_refcnt_{get|put}()
From: Vlad Buslov @ 2018-09-17 7:17 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, jiri, davem, stephen, ktkhai,
nicolas.dichtel, gregkh, mark.rutland, leon, paulmck, fw, dsahern,
christian, lucien.xin, jakub.kicinski, jbenc, Vlad Buslov
In-Reply-To: <1537168660-24032-1-git-send-email-vladbu@mellanox.com>
Implement get/put function for blocks that only take/release the reference
and perform deallocation. These functions are intended to be used by
unlocked rules update path to always hold reference to block while working
with it. They use on new fine-grained locking mechanisms introduced in
previous patches in this set, instead of relying on global protection
provided by rtnl lock.
Extract code that is common with tcf_block_detach_ext() into common
function __tcf_block_put().
Extend tcf_block with rcu to allow safe deallocation when it is accessed
concurrently.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/sch_generic.h | 1 +
net/sched/cls_api.c | 74 ++++++++++++++++++++++++++++++++---------------
2 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 45fee65468d0..931fcdadf64a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -357,6 +357,7 @@ struct tcf_block {
struct tcf_chain *chain;
struct list_head filter_chain_list;
} chain0;
+ struct rcu_head rcu;
};
static inline void tcf_block_offload_inc(struct tcf_block *block, u32 *flags)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 924723fb74f6..0a7a3ace2da9 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -241,7 +241,7 @@ static void tcf_chain_destroy(struct tcf_chain *chain)
block->chain0.chain = NULL;
kfree(chain);
if (list_empty(&block->chain_list) && !refcount_read(&block->refcnt))
- kfree(block);
+ kfree_rcu(block, rcu);
}
static void tcf_chain_hold(struct tcf_chain *chain)
@@ -537,6 +537,19 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index)
return idr_find(&tn->idr, block_index);
}
+static struct tcf_block *tcf_block_refcnt_get(struct net *net, u32 block_index)
+{
+ struct tcf_block *block;
+
+ rcu_read_lock();
+ block = tcf_block_lookup(net, block_index);
+ if (block && !refcount_inc_not_zero(&block->refcnt))
+ block = NULL;
+ rcu_read_unlock();
+
+ return block;
+}
+
static void tcf_qdisc_put(struct Qdisc *q, bool rtnl_held)
{
if (!q)
@@ -573,6 +586,40 @@ static void tcf_block_put_all_chains(struct tcf_block *block)
}
}
+static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q,
+ struct tcf_block_ext_info *ei)
+{
+ if (refcount_dec_and_test(&block->refcnt)) {
+ /* Flushing/putting all chains will cause the block to be
+ * deallocated when last chain is freed. However, if chain_list
+ * is empty, block has to be manually deallocated. After block
+ * reference counter reached 0, it is no longer possible to
+ * increment it or add new chains to block.
+ */
+ bool free_block = list_empty(&block->chain_list);
+
+ if (tcf_block_shared(block))
+ tcf_block_remove(block, block->net);
+ if (!free_block)
+ tcf_block_flush_all_chains(block);
+
+ if (q)
+ tcf_block_offload_unbind(block, q, ei);
+
+ if (free_block)
+ kfree_rcu(block, rcu);
+ else
+ tcf_block_put_all_chains(block);
+ } else if (q) {
+ tcf_block_offload_unbind(block, q, ei);
+ }
+}
+
+static void tcf_block_refcnt_put(struct tcf_block *block)
+{
+ __tcf_block_put(block, NULL, NULL);
+}
+
/* Find tcf block.
* Set q, parent, cl when appropriate.
*/
@@ -795,7 +842,7 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
if (tcf_block_shared(block))
tcf_block_remove(block, net);
err_block_insert:
- kfree(block);
+ kfree_rcu(block, rcu);
} else {
refcount_dec(&block->refcnt);
}
@@ -835,28 +882,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
tcf_chain0_head_change_cb_del(block, ei);
tcf_block_owner_del(block, q, ei->binder_type);
- if (refcount_dec_and_test(&block->refcnt)) {
- /* Flushing/putting all chains will cause the block to be
- * deallocated when last chain is freed. However, if chain_list
- * is empty, block has to be manually deallocated. After block
- * reference counter reached 0, it is no longer possible to
- * increment it or add new chains to block.
- */
- bool free_block = list_empty(&block->chain_list);
-
- if (tcf_block_shared(block))
- tcf_block_remove(block, block->net);
- if (!free_block)
- tcf_block_flush_all_chains(block);
- tcf_block_offload_unbind(block, q, ei);
-
- if (free_block)
- kfree(block);
- else
- tcf_block_put_all_chains(block);
- } else {
- tcf_block_offload_unbind(block, q, ei);
- }
+ __tcf_block_put(block, q, ei);
}
EXPORT_SYMBOL(tcf_block_put_ext);
--
2.7.5
^ 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