1 |
commit: 2c0f6c3b92e2248ee19155496c89a7eead78472a |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Oct 3 16:12:47 2015 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Oct 3 16:12:47 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=2c0f6c3b |
7 |
|
8 |
Linux patch 4.2.3 |
9 |
|
10 |
0000_README | 4 + |
11 |
1002_linux-4.2.3.patch | 1532 ++++++++++++++++++++++++++++++++++++++++++++++++ |
12 |
2 files changed, 1536 insertions(+) |
13 |
|
14 |
diff --git a/0000_README b/0000_README |
15 |
index 9428abc..5a14372 100644 |
16 |
--- a/0000_README |
17 |
+++ b/0000_README |
18 |
@@ -51,6 +51,10 @@ Patch: 1001_linux-4.2.2.patch |
19 |
From: http://www.kernel.org |
20 |
Desc: Linux 4.2.2 |
21 |
|
22 |
+Patch: 1002_linux-4.2.3.patch |
23 |
+From: http://www.kernel.org |
24 |
+Desc: Linux 4.2.3 |
25 |
+ |
26 |
Patch: 1500_XATTR_USER_PREFIX.patch |
27 |
From: https://bugs.gentoo.org/show_bug.cgi?id=470644 |
28 |
Desc: Support for namespace user.pax.* on tmpfs. |
29 |
|
30 |
diff --git a/1002_linux-4.2.3.patch b/1002_linux-4.2.3.patch |
31 |
new file mode 100644 |
32 |
index 0000000..018e36c |
33 |
--- /dev/null |
34 |
+++ b/1002_linux-4.2.3.patch |
35 |
@@ -0,0 +1,1532 @@ |
36 |
+diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt |
37 |
+index 41b3f3f864e8..5d88f37480b6 100644 |
38 |
+--- a/Documentation/devicetree/bindings/net/ethernet.txt |
39 |
++++ b/Documentation/devicetree/bindings/net/ethernet.txt |
40 |
+@@ -25,7 +25,11 @@ The following properties are common to the Ethernet controllers: |
41 |
+ flow control thresholds. |
42 |
+ - tx-fifo-depth: the size of the controller's transmit fifo in bytes. This |
43 |
+ is used for components that can have configurable fifo sizes. |
44 |
++- managed: string, specifies the PHY management type. Supported values are: |
45 |
++ "auto", "in-band-status". "auto" is the default, it usess MDIO for |
46 |
++ management if fixed-link is not specified. |
47 |
+ |
48 |
+ Child nodes of the Ethernet controller are typically the individual PHY devices |
49 |
+ connected via the MDIO bus (sometimes the MDIO bus controller is separate). |
50 |
+ They are described in the phy.txt file in this same directory. |
51 |
++For non-MDIO PHY management see fixed-link.txt. |
52 |
+diff --git a/Makefile b/Makefile |
53 |
+index 3578b4426ecf..a6edbb11a69a 100644 |
54 |
+--- a/Makefile |
55 |
++++ b/Makefile |
56 |
+@@ -1,6 +1,6 @@ |
57 |
+ VERSION = 4 |
58 |
+ PATCHLEVEL = 2 |
59 |
+-SUBLEVEL = 2 |
60 |
++SUBLEVEL = 3 |
61 |
+ EXTRAVERSION = |
62 |
+ NAME = Hurr durr I'ma sheep |
63 |
+ |
64 |
+diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c |
65 |
+index 965d1afb0eaa..5cb13ca3a3ac 100644 |
66 |
+--- a/drivers/block/zram/zcomp.c |
67 |
++++ b/drivers/block/zram/zcomp.c |
68 |
+@@ -330,12 +330,14 @@ void zcomp_destroy(struct zcomp *comp) |
69 |
+ * allocate new zcomp and initialize it. return compressing |
70 |
+ * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL) |
71 |
+ * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in |
72 |
+- * case of allocation error. |
73 |
++ * case of allocation error, or any other error potentially |
74 |
++ * returned by functions zcomp_strm_{multi,single}_create. |
75 |
+ */ |
76 |
+ struct zcomp *zcomp_create(const char *compress, int max_strm) |
77 |
+ { |
78 |
+ struct zcomp *comp; |
79 |
+ struct zcomp_backend *backend; |
80 |
++ int error; |
81 |
+ |
82 |
+ backend = find_backend(compress); |
83 |
+ if (!backend) |
84 |
+@@ -347,12 +349,12 @@ struct zcomp *zcomp_create(const char *compress, int max_strm) |
85 |
+ |
86 |
+ comp->backend = backend; |
87 |
+ if (max_strm > 1) |
88 |
+- zcomp_strm_multi_create(comp, max_strm); |
89 |
++ error = zcomp_strm_multi_create(comp, max_strm); |
90 |
+ else |
91 |
+- zcomp_strm_single_create(comp); |
92 |
+- if (!comp->stream) { |
93 |
++ error = zcomp_strm_single_create(comp); |
94 |
++ if (error) { |
95 |
+ kfree(comp); |
96 |
+- return ERR_PTR(-ENOMEM); |
97 |
++ return ERR_PTR(error); |
98 |
+ } |
99 |
+ return comp; |
100 |
+ } |
101 |
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c |
102 |
+index 079897b3a955..9d56515f4c4d 100644 |
103 |
+--- a/drivers/net/dsa/bcm_sf2.c |
104 |
++++ b/drivers/net/dsa/bcm_sf2.c |
105 |
+@@ -418,7 +418,7 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) |
106 |
+ core_writel(priv, port, CORE_FAST_AGE_PORT); |
107 |
+ |
108 |
+ reg = core_readl(priv, CORE_FAST_AGE_CTRL); |
109 |
+- reg |= EN_AGE_PORT | FAST_AGE_STR_DONE; |
110 |
++ reg |= EN_AGE_PORT | EN_AGE_DYNAMIC | FAST_AGE_STR_DONE; |
111 |
+ core_writel(priv, reg, CORE_FAST_AGE_CTRL); |
112 |
+ |
113 |
+ do { |
114 |
+@@ -432,6 +432,8 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) |
115 |
+ if (!timeout) |
116 |
+ return -ETIMEDOUT; |
117 |
+ |
118 |
++ core_writel(priv, 0, CORE_FAST_AGE_CTRL); |
119 |
++ |
120 |
+ return 0; |
121 |
+ } |
122 |
+ |
123 |
+@@ -507,7 +509,7 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, |
124 |
+ u32 reg; |
125 |
+ |
126 |
+ reg = core_readl(priv, CORE_G_PCTL_PORT(port)); |
127 |
+- cur_hw_state = reg >> G_MISTP_STATE_SHIFT; |
128 |
++ cur_hw_state = reg & (G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT); |
129 |
+ |
130 |
+ switch (state) { |
131 |
+ case BR_STATE_DISABLED: |
132 |
+@@ -531,10 +533,12 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, |
133 |
+ } |
134 |
+ |
135 |
+ /* Fast-age ARL entries if we are moving a port from Learning or |
136 |
+- * Forwarding state to Disabled, Blocking or Listening state |
137 |
++ * Forwarding (cur_hw_state) state to Disabled, Blocking or Listening |
138 |
++ * state (hw_state) |
139 |
+ */ |
140 |
+ if (cur_hw_state != hw_state) { |
141 |
+- if (cur_hw_state & 4 && !(hw_state & 4)) { |
142 |
++ if (cur_hw_state >= G_MISTP_LEARN_STATE && |
143 |
++ hw_state <= G_MISTP_LISTEN_STATE) { |
144 |
+ ret = bcm_sf2_sw_fast_age_port(ds, port); |
145 |
+ if (ret) { |
146 |
+ pr_err("%s: fast-ageing failed\n", __func__); |
147 |
+@@ -901,15 +905,11 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, |
148 |
+ struct fixed_phy_status *status) |
149 |
+ { |
150 |
+ struct bcm_sf2_priv *priv = ds_to_priv(ds); |
151 |
+- u32 duplex, pause, speed; |
152 |
++ u32 duplex, pause; |
153 |
+ u32 reg; |
154 |
+ |
155 |
+ duplex = core_readl(priv, CORE_DUPSTS); |
156 |
+ pause = core_readl(priv, CORE_PAUSESTS); |
157 |
+- speed = core_readl(priv, CORE_SPDSTS); |
158 |
+- |
159 |
+- speed >>= (port * SPDSTS_SHIFT); |
160 |
+- speed &= SPDSTS_MASK; |
161 |
+ |
162 |
+ status->link = 0; |
163 |
+ |
164 |
+@@ -944,18 +944,6 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, |
165 |
+ reg &= ~LINK_STS; |
166 |
+ core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); |
167 |
+ |
168 |
+- switch (speed) { |
169 |
+- case SPDSTS_10: |
170 |
+- status->speed = SPEED_10; |
171 |
+- break; |
172 |
+- case SPDSTS_100: |
173 |
+- status->speed = SPEED_100; |
174 |
+- break; |
175 |
+- case SPDSTS_1000: |
176 |
+- status->speed = SPEED_1000; |
177 |
+- break; |
178 |
+- } |
179 |
+- |
180 |
+ if ((pause & (1 << port)) && |
181 |
+ (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) { |
182 |
+ status->asym_pause = 1; |
183 |
+diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h |
184 |
+index 22e2ebf31333..789d7b7737da 100644 |
185 |
+--- a/drivers/net/dsa/bcm_sf2.h |
186 |
++++ b/drivers/net/dsa/bcm_sf2.h |
187 |
+@@ -112,8 +112,8 @@ static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off) \ |
188 |
+ spin_unlock(&priv->indir_lock); \ |
189 |
+ return (u64)indir << 32 | dir; \ |
190 |
+ } \ |
191 |
+-static inline void name##_writeq(struct bcm_sf2_priv *priv, u32 off, \ |
192 |
+- u64 val) \ |
193 |
++static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \ |
194 |
++ u32 off) \ |
195 |
+ { \ |
196 |
+ spin_lock(&priv->indir_lock); \ |
197 |
+ reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE); \ |
198 |
+diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c |
199 |
+index 561342466076..26ec2fbfaa89 100644 |
200 |
+--- a/drivers/net/dsa/mv88e6xxx.c |
201 |
++++ b/drivers/net/dsa/mv88e6xxx.c |
202 |
+@@ -1387,6 +1387,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) |
203 |
+ reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL); |
204 |
+ if (dsa_is_cpu_port(ds, port) || |
205 |
+ ds->dsa_port_mask & (1 << port)) { |
206 |
++ reg &= ~PORT_PCS_CTRL_UNFORCED; |
207 |
+ reg |= PORT_PCS_CTRL_FORCE_LINK | |
208 |
+ PORT_PCS_CTRL_LINK_UP | |
209 |
+ PORT_PCS_CTRL_DUPLEX_FULL | |
210 |
+diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c |
211 |
+index da48e66377b5..8207877d6237 100644 |
212 |
+--- a/drivers/net/ethernet/altera/altera_tse_main.c |
213 |
++++ b/drivers/net/ethernet/altera/altera_tse_main.c |
214 |
+@@ -511,8 +511,7 @@ static int tse_poll(struct napi_struct *napi, int budget) |
215 |
+ |
216 |
+ if (rxcomplete < budget) { |
217 |
+ |
218 |
+- napi_gro_flush(napi, false); |
219 |
+- __napi_complete(napi); |
220 |
++ napi_complete(napi); |
221 |
+ |
222 |
+ netdev_dbg(priv->dev, |
223 |
+ "NAPI Complete, did %d packets with budget %d\n", |
224 |
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c |
225 |
+index b349e6f36ea7..de63266de16b 100644 |
226 |
+--- a/drivers/net/ethernet/freescale/fec_main.c |
227 |
++++ b/drivers/net/ethernet/freescale/fec_main.c |
228 |
+@@ -1402,6 +1402,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) |
229 |
+ if ((status & BD_ENET_RX_LAST) == 0) |
230 |
+ netdev_err(ndev, "rcv is not +last\n"); |
231 |
+ |
232 |
++ writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); |
233 |
+ |
234 |
+ /* Check for errors. */ |
235 |
+ if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | |
236 |
+diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c |
237 |
+index 62e48bc0cb23..09ec32e33076 100644 |
238 |
+--- a/drivers/net/ethernet/marvell/mvneta.c |
239 |
++++ b/drivers/net/ethernet/marvell/mvneta.c |
240 |
+@@ -1479,6 +1479,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, |
241 |
+ struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq); |
242 |
+ struct sk_buff *skb; |
243 |
+ unsigned char *data; |
244 |
++ dma_addr_t phys_addr; |
245 |
+ u32 rx_status; |
246 |
+ int rx_bytes, err; |
247 |
+ |
248 |
+@@ -1486,6 +1487,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, |
249 |
+ rx_status = rx_desc->status; |
250 |
+ rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); |
251 |
+ data = (unsigned char *)rx_desc->buf_cookie; |
252 |
++ phys_addr = rx_desc->buf_phys_addr; |
253 |
+ |
254 |
+ if (!mvneta_rxq_desc_is_first_last(rx_status) || |
255 |
+ (rx_status & MVNETA_RXD_ERR_SUMMARY)) { |
256 |
+@@ -1534,7 +1536,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, |
257 |
+ if (!skb) |
258 |
+ goto err_drop_frame; |
259 |
+ |
260 |
+- dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr, |
261 |
++ dma_unmap_single(dev->dev.parent, phys_addr, |
262 |
+ MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE); |
263 |
+ |
264 |
+ rcvd_pkts++; |
265 |
+@@ -3027,8 +3029,8 @@ static int mvneta_probe(struct platform_device *pdev) |
266 |
+ const char *dt_mac_addr; |
267 |
+ char hw_mac_addr[ETH_ALEN]; |
268 |
+ const char *mac_from; |
269 |
++ const char *managed; |
270 |
+ int phy_mode; |
271 |
+- int fixed_phy = 0; |
272 |
+ int err; |
273 |
+ |
274 |
+ /* Our multiqueue support is not complete, so for now, only |
275 |
+@@ -3062,7 +3064,6 @@ static int mvneta_probe(struct platform_device *pdev) |
276 |
+ dev_err(&pdev->dev, "cannot register fixed PHY\n"); |
277 |
+ goto err_free_irq; |
278 |
+ } |
279 |
+- fixed_phy = 1; |
280 |
+ |
281 |
+ /* In the case of a fixed PHY, the DT node associated |
282 |
+ * to the PHY is the Ethernet MAC DT node. |
283 |
+@@ -3086,8 +3087,10 @@ static int mvneta_probe(struct platform_device *pdev) |
284 |
+ pp = netdev_priv(dev); |
285 |
+ pp->phy_node = phy_node; |
286 |
+ pp->phy_interface = phy_mode; |
287 |
+- pp->use_inband_status = (phy_mode == PHY_INTERFACE_MODE_SGMII) && |
288 |
+- fixed_phy; |
289 |
++ |
290 |
++ err = of_property_read_string(dn, "managed", &managed); |
291 |
++ pp->use_inband_status = (err == 0 && |
292 |
++ strcmp(managed, "in-band-status") == 0); |
293 |
+ |
294 |
+ pp->clk = devm_clk_get(&pdev->dev, NULL); |
295 |
+ if (IS_ERR(pp->clk)) { |
296 |
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
297 |
+index 9c145dddd717..4f95fa7b594d 100644 |
298 |
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
299 |
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
300 |
+@@ -1250,8 +1250,6 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) |
301 |
+ rss_context->hash_fn = MLX4_RSS_HASH_TOP; |
302 |
+ memcpy(rss_context->rss_key, priv->rss_key, |
303 |
+ MLX4_EN_RSS_KEY_SIZE); |
304 |
+- netdev_rss_key_fill(rss_context->rss_key, |
305 |
+- MLX4_EN_RSS_KEY_SIZE); |
306 |
+ } else { |
307 |
+ en_err(priv, "Unknown RSS hash function requested\n"); |
308 |
+ err = -EINVAL; |
309 |
+diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c |
310 |
+index 29c2a017a450..a408977a531a 100644 |
311 |
+--- a/drivers/net/ethernet/mellanox/mlx4/main.c |
312 |
++++ b/drivers/net/ethernet/mellanox/mlx4/main.c |
313 |
+@@ -2654,9 +2654,14 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) |
314 |
+ |
315 |
+ if (msi_x) { |
316 |
+ int nreq = dev->caps.num_ports * num_online_cpus() + 1; |
317 |
++ bool shared_ports = false; |
318 |
+ |
319 |
+ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, |
320 |
+ nreq); |
321 |
++ if (nreq > MAX_MSIX) { |
322 |
++ nreq = MAX_MSIX; |
323 |
++ shared_ports = true; |
324 |
++ } |
325 |
+ |
326 |
+ entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); |
327 |
+ if (!entries) |
328 |
+@@ -2679,6 +2684,9 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) |
329 |
+ bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports, |
330 |
+ dev->caps.num_ports); |
331 |
+ |
332 |
++ if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) |
333 |
++ shared_ports = true; |
334 |
++ |
335 |
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) { |
336 |
+ if (i == MLX4_EQ_ASYNC) |
337 |
+ continue; |
338 |
+@@ -2686,7 +2694,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) |
339 |
+ priv->eq_table.eq[i].irq = |
340 |
+ entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector; |
341 |
+ |
342 |
+- if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) { |
343 |
++ if (shared_ports) { |
344 |
+ bitmap_fill(priv->eq_table.eq[i].actv_ports.ports, |
345 |
+ dev->caps.num_ports); |
346 |
+ /* We don't set affinity hint when there |
347 |
+diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c |
348 |
+index edd77342773a..248478c6f6e4 100644 |
349 |
+--- a/drivers/net/macvtap.c |
350 |
++++ b/drivers/net/macvtap.c |
351 |
+@@ -1111,10 +1111,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, |
352 |
+ return 0; |
353 |
+ |
354 |
+ case TUNSETSNDBUF: |
355 |
+- if (get_user(u, up)) |
356 |
++ if (get_user(s, sp)) |
357 |
+ return -EFAULT; |
358 |
+ |
359 |
+- q->sk.sk_sndbuf = u; |
360 |
++ q->sk.sk_sndbuf = s; |
361 |
+ return 0; |
362 |
+ |
363 |
+ case TUNGETVNETHDRSZ: |
364 |
+diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c |
365 |
+index d7a65247f952..99d9bc19c94a 100644 |
366 |
+--- a/drivers/net/phy/fixed_phy.c |
367 |
++++ b/drivers/net/phy/fixed_phy.c |
368 |
+@@ -52,6 +52,10 @@ static int fixed_phy_update_regs(struct fixed_phy *fp) |
369 |
+ u16 lpagb = 0; |
370 |
+ u16 lpa = 0; |
371 |
+ |
372 |
++ if (!fp->status.link) |
373 |
++ goto done; |
374 |
++ bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; |
375 |
++ |
376 |
+ if (fp->status.duplex) { |
377 |
+ bmcr |= BMCR_FULLDPLX; |
378 |
+ |
379 |
+@@ -96,15 +100,13 @@ static int fixed_phy_update_regs(struct fixed_phy *fp) |
380 |
+ } |
381 |
+ } |
382 |
+ |
383 |
+- if (fp->status.link) |
384 |
+- bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; |
385 |
+- |
386 |
+ if (fp->status.pause) |
387 |
+ lpa |= LPA_PAUSE_CAP; |
388 |
+ |
389 |
+ if (fp->status.asym_pause) |
390 |
+ lpa |= LPA_PAUSE_ASYM; |
391 |
+ |
392 |
++done: |
393 |
+ fp->regs[MII_PHYSID1] = 0; |
394 |
+ fp->regs[MII_PHYSID2] = 0; |
395 |
+ |
396 |
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c |
397 |
+index 46a14cbb0215..02a4615b65f8 100644 |
398 |
+--- a/drivers/net/phy/mdio_bus.c |
399 |
++++ b/drivers/net/phy/mdio_bus.c |
400 |
+@@ -303,12 +303,12 @@ void mdiobus_unregister(struct mii_bus *bus) |
401 |
+ BUG_ON(bus->state != MDIOBUS_REGISTERED); |
402 |
+ bus->state = MDIOBUS_UNREGISTERED; |
403 |
+ |
404 |
+- device_del(&bus->dev); |
405 |
+ for (i = 0; i < PHY_MAX_ADDR; i++) { |
406 |
+ if (bus->phy_map[i]) |
407 |
+ device_unregister(&bus->phy_map[i]->dev); |
408 |
+ bus->phy_map[i] = NULL; |
409 |
+ } |
410 |
++ device_del(&bus->dev); |
411 |
+ } |
412 |
+ EXPORT_SYMBOL(mdiobus_unregister); |
413 |
+ |
414 |
+diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c |
415 |
+index fa8f5046afe9..487be20b6b12 100644 |
416 |
+--- a/drivers/net/ppp/ppp_generic.c |
417 |
++++ b/drivers/net/ppp/ppp_generic.c |
418 |
+@@ -2742,6 +2742,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit, |
419 |
+ */ |
420 |
+ dev_net_set(dev, net); |
421 |
+ |
422 |
++ rtnl_lock(); |
423 |
+ mutex_lock(&pn->all_ppp_mutex); |
424 |
+ |
425 |
+ if (unit < 0) { |
426 |
+@@ -2772,7 +2773,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit, |
427 |
+ ppp->file.index = unit; |
428 |
+ sprintf(dev->name, "ppp%d", unit); |
429 |
+ |
430 |
+- ret = register_netdev(dev); |
431 |
++ ret = register_netdevice(dev); |
432 |
+ if (ret != 0) { |
433 |
+ unit_put(&pn->units_idr, unit); |
434 |
+ netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", |
435 |
+@@ -2784,6 +2785,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit, |
436 |
+ |
437 |
+ atomic_inc(&ppp_unit_count); |
438 |
+ mutex_unlock(&pn->all_ppp_mutex); |
439 |
++ rtnl_unlock(); |
440 |
+ |
441 |
+ *retp = 0; |
442 |
+ return ppp; |
443 |
+diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c |
444 |
+index fdc60db60829..7c8c23cc6896 100644 |
445 |
+--- a/drivers/of/of_mdio.c |
446 |
++++ b/drivers/of/of_mdio.c |
447 |
+@@ -266,7 +266,8 @@ EXPORT_SYMBOL(of_phy_attach); |
448 |
+ bool of_phy_is_fixed_link(struct device_node *np) |
449 |
+ { |
450 |
+ struct device_node *dn; |
451 |
+- int len; |
452 |
++ int len, err; |
453 |
++ const char *managed; |
454 |
+ |
455 |
+ /* New binding */ |
456 |
+ dn = of_get_child_by_name(np, "fixed-link"); |
457 |
+@@ -275,6 +276,10 @@ bool of_phy_is_fixed_link(struct device_node *np) |
458 |
+ return true; |
459 |
+ } |
460 |
+ |
461 |
++ err = of_property_read_string(np, "managed", &managed); |
462 |
++ if (err == 0 && strcmp(managed, "auto") != 0) |
463 |
++ return true; |
464 |
++ |
465 |
+ /* Old binding */ |
466 |
+ if (of_get_property(np, "fixed-link", &len) && |
467 |
+ len == (5 * sizeof(__be32))) |
468 |
+@@ -289,8 +294,18 @@ int of_phy_register_fixed_link(struct device_node *np) |
469 |
+ struct fixed_phy_status status = {}; |
470 |
+ struct device_node *fixed_link_node; |
471 |
+ const __be32 *fixed_link_prop; |
472 |
+- int len; |
473 |
++ int len, err; |
474 |
+ struct phy_device *phy; |
475 |
++ const char *managed; |
476 |
++ |
477 |
++ err = of_property_read_string(np, "managed", &managed); |
478 |
++ if (err == 0) { |
479 |
++ if (strcmp(managed, "in-band-status") == 0) { |
480 |
++ /* status is zeroed, namely its .link member */ |
481 |
++ phy = fixed_phy_register(PHY_POLL, &status, np); |
482 |
++ return IS_ERR(phy) ? PTR_ERR(phy) : 0; |
483 |
++ } |
484 |
++ } |
485 |
+ |
486 |
+ /* New binding */ |
487 |
+ fixed_link_node = of_get_child_by_name(np, "fixed-link"); |
488 |
+diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c |
489 |
+index 06697315a088..fb4dd7b3ee71 100644 |
490 |
+--- a/drivers/platform/x86/hp-wmi.c |
491 |
++++ b/drivers/platform/x86/hp-wmi.c |
492 |
+@@ -54,8 +54,9 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); |
493 |
+ #define HPWMI_HARDWARE_QUERY 0x4 |
494 |
+ #define HPWMI_WIRELESS_QUERY 0x5 |
495 |
+ #define HPWMI_BIOS_QUERY 0x9 |
496 |
++#define HPWMI_FEATURE_QUERY 0xb |
497 |
+ #define HPWMI_HOTKEY_QUERY 0xc |
498 |
+-#define HPWMI_FEATURE_QUERY 0xd |
499 |
++#define HPWMI_FEATURE2_QUERY 0xd |
500 |
+ #define HPWMI_WIRELESS2_QUERY 0x1b |
501 |
+ #define HPWMI_POSTCODEERROR_QUERY 0x2a |
502 |
+ |
503 |
+@@ -295,25 +296,33 @@ static int hp_wmi_tablet_state(void) |
504 |
+ return (state & 0x4) ? 1 : 0; |
505 |
+ } |
506 |
+ |
507 |
+-static int __init hp_wmi_bios_2009_later(void) |
508 |
++static int __init hp_wmi_bios_2008_later(void) |
509 |
+ { |
510 |
+ int state = 0; |
511 |
+ int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, |
512 |
+ sizeof(state), sizeof(state)); |
513 |
+- if (ret) |
514 |
+- return ret; |
515 |
++ if (!ret) |
516 |
++ return 1; |
517 |
+ |
518 |
+- return (state & 0x10) ? 1 : 0; |
519 |
++ return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; |
520 |
+ } |
521 |
+ |
522 |
+-static int hp_wmi_enable_hotkeys(void) |
523 |
++static int __init hp_wmi_bios_2009_later(void) |
524 |
+ { |
525 |
+- int ret; |
526 |
+- int query = 0x6e; |
527 |
++ int state = 0; |
528 |
++ int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state, |
529 |
++ sizeof(state), sizeof(state)); |
530 |
++ if (!ret) |
531 |
++ return 1; |
532 |
+ |
533 |
+- ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query), |
534 |
+- 0); |
535 |
++ return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; |
536 |
++} |
537 |
+ |
538 |
++static int __init hp_wmi_enable_hotkeys(void) |
539 |
++{ |
540 |
++ int value = 0x6e; |
541 |
++ int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value, |
542 |
++ sizeof(value), 0); |
543 |
+ if (ret) |
544 |
+ return -EINVAL; |
545 |
+ return 0; |
546 |
+@@ -663,7 +672,7 @@ static int __init hp_wmi_input_setup(void) |
547 |
+ hp_wmi_tablet_state()); |
548 |
+ input_sync(hp_wmi_input_dev); |
549 |
+ |
550 |
+- if (hp_wmi_bios_2009_later() == 4) |
551 |
++ if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) |
552 |
+ hp_wmi_enable_hotkeys(); |
553 |
+ |
554 |
+ status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); |
555 |
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c |
556 |
+index 1285eaf5dc22..03cdb9e18d57 100644 |
557 |
+--- a/net/bridge/br_multicast.c |
558 |
++++ b/net/bridge/br_multicast.c |
559 |
+@@ -991,7 +991,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, |
560 |
+ |
561 |
+ ih = igmpv3_report_hdr(skb); |
562 |
+ num = ntohs(ih->ngrec); |
563 |
+- len = sizeof(*ih); |
564 |
++ len = skb_transport_offset(skb) + sizeof(*ih); |
565 |
+ |
566 |
+ for (i = 0; i < num; i++) { |
567 |
+ len += sizeof(*grec); |
568 |
+@@ -1052,7 +1052,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, |
569 |
+ |
570 |
+ icmp6h = icmp6_hdr(skb); |
571 |
+ num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); |
572 |
+- len = sizeof(*icmp6h); |
573 |
++ len = skb_transport_offset(skb) + sizeof(*icmp6h); |
574 |
+ |
575 |
+ for (i = 0; i < num; i++) { |
576 |
+ __be16 *nsrcs, _nsrcs; |
577 |
+diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c |
578 |
+index 9a12668f7d62..0ad144fb0c79 100644 |
579 |
+--- a/net/core/fib_rules.c |
580 |
++++ b/net/core/fib_rules.c |
581 |
+@@ -615,15 +615,17 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, |
582 |
+ { |
583 |
+ int idx = 0; |
584 |
+ struct fib_rule *rule; |
585 |
++ int err = 0; |
586 |
+ |
587 |
+ rcu_read_lock(); |
588 |
+ list_for_each_entry_rcu(rule, &ops->rules_list, list) { |
589 |
+ if (idx < cb->args[1]) |
590 |
+ goto skip; |
591 |
+ |
592 |
+- if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
593 |
+- cb->nlh->nlmsg_seq, RTM_NEWRULE, |
594 |
+- NLM_F_MULTI, ops) < 0) |
595 |
++ err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
596 |
++ cb->nlh->nlmsg_seq, RTM_NEWRULE, |
597 |
++ NLM_F_MULTI, ops); |
598 |
++ if (err) |
599 |
+ break; |
600 |
+ skip: |
601 |
+ idx++; |
602 |
+@@ -632,7 +634,7 @@ skip: |
603 |
+ cb->args[1] = idx; |
604 |
+ rules_ops_put(ops); |
605 |
+ |
606 |
+- return skb->len; |
607 |
++ return err; |
608 |
+ } |
609 |
+ |
610 |
+ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
611 |
+@@ -648,7 +650,9 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
612 |
+ if (ops == NULL) |
613 |
+ return -EAFNOSUPPORT; |
614 |
+ |
615 |
+- return dump_rules(skb, cb, ops); |
616 |
++ dump_rules(skb, cb, ops); |
617 |
++ |
618 |
++ return skb->len; |
619 |
+ } |
620 |
+ |
621 |
+ rcu_read_lock(); |
622 |
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c |
623 |
+index dc004b1e1f85..0861018be708 100644 |
624 |
+--- a/net/core/rtnetlink.c |
625 |
++++ b/net/core/rtnetlink.c |
626 |
+@@ -3021,6 +3021,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) |
627 |
+ u32 portid = NETLINK_CB(cb->skb).portid; |
628 |
+ u32 seq = cb->nlh->nlmsg_seq; |
629 |
+ u32 filter_mask = 0; |
630 |
++ int err; |
631 |
+ |
632 |
+ if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { |
633 |
+ struct nlattr *extfilt; |
634 |
+@@ -3041,20 +3042,25 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) |
635 |
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
636 |
+ |
637 |
+ if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { |
638 |
+- if (idx >= cb->args[0] && |
639 |
+- br_dev->netdev_ops->ndo_bridge_getlink( |
640 |
+- skb, portid, seq, dev, filter_mask, |
641 |
+- NLM_F_MULTI) < 0) |
642 |
+- break; |
643 |
++ if (idx >= cb->args[0]) { |
644 |
++ err = br_dev->netdev_ops->ndo_bridge_getlink( |
645 |
++ skb, portid, seq, dev, |
646 |
++ filter_mask, NLM_F_MULTI); |
647 |
++ if (err < 0 && err != -EOPNOTSUPP) |
648 |
++ break; |
649 |
++ } |
650 |
+ idx++; |
651 |
+ } |
652 |
+ |
653 |
+ if (ops->ndo_bridge_getlink) { |
654 |
+- if (idx >= cb->args[0] && |
655 |
+- ops->ndo_bridge_getlink(skb, portid, seq, dev, |
656 |
+- filter_mask, |
657 |
+- NLM_F_MULTI) < 0) |
658 |
+- break; |
659 |
++ if (idx >= cb->args[0]) { |
660 |
++ err = ops->ndo_bridge_getlink(skb, portid, |
661 |
++ seq, dev, |
662 |
++ filter_mask, |
663 |
++ NLM_F_MULTI); |
664 |
++ if (err < 0 && err != -EOPNOTSUPP) |
665 |
++ break; |
666 |
++ } |
667 |
+ idx++; |
668 |
+ } |
669 |
+ } |
670 |
+diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c |
671 |
+index d79866c5f8bc..817622f3dbb7 100644 |
672 |
+--- a/net/core/sock_diag.c |
673 |
++++ b/net/core/sock_diag.c |
674 |
+@@ -90,6 +90,9 @@ int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk, |
675 |
+ goto out; |
676 |
+ |
677 |
+ fprog = filter->prog->orig_prog; |
678 |
++ if (!fprog) |
679 |
++ goto out; |
680 |
++ |
681 |
+ flen = bpf_classic_proglen(fprog); |
682 |
+ |
683 |
+ attr = nla_reserve(skb, attrtype, flen); |
684 |
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c |
685 |
+index b1c218df2c85..b7dedd9d36d8 100644 |
686 |
+--- a/net/ipv4/tcp_output.c |
687 |
++++ b/net/ipv4/tcp_output.c |
688 |
+@@ -2898,6 +2898,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) |
689 |
+ skb_reserve(skb, MAX_TCP_HEADER); |
690 |
+ tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk), |
691 |
+ TCPHDR_ACK | TCPHDR_RST); |
692 |
++ skb_mstamp_get(&skb->skb_mstamp); |
693 |
+ /* Send it off. */ |
694 |
+ if (tcp_transmit_skb(sk, skb, 0, priority)) |
695 |
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED); |
696 |
+diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c |
697 |
+index 447a7fbd1bb6..f5e2ba1c18bf 100644 |
698 |
+--- a/net/ipv6/exthdrs_offload.c |
699 |
++++ b/net/ipv6/exthdrs_offload.c |
700 |
+@@ -36,6 +36,6 @@ out: |
701 |
+ return ret; |
702 |
+ |
703 |
+ out_rt: |
704 |
+- inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); |
705 |
++ inet6_del_offload(&rthdr_offload, IPPROTO_ROUTING); |
706 |
+ goto out; |
707 |
+ } |
708 |
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c |
709 |
+index 74ceb73c1c9a..5f36266b1f5e 100644 |
710 |
+--- a/net/ipv6/ip6mr.c |
711 |
++++ b/net/ipv6/ip6mr.c |
712 |
+@@ -550,7 +550,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
713 |
+ |
714 |
+ if (it->cache == &mrt->mfc6_unres_queue) |
715 |
+ spin_unlock_bh(&mfc_unres_lock); |
716 |
+- else if (it->cache == mrt->mfc6_cache_array) |
717 |
++ else if (it->cache == &mrt->mfc6_cache_array[it->ct]) |
718 |
+ read_unlock(&mrt_lock); |
719 |
+ } |
720 |
+ |
721 |
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
722 |
+index d15586490cec..00b64d402a57 100644 |
723 |
+--- a/net/ipv6/route.c |
724 |
++++ b/net/ipv6/route.c |
725 |
+@@ -1727,7 +1727,7 @@ static int ip6_convert_metrics(struct mx6_config *mxc, |
726 |
+ return -EINVAL; |
727 |
+ } |
728 |
+ |
729 |
+-int ip6_route_add(struct fib6_config *cfg) |
730 |
++int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret) |
731 |
+ { |
732 |
+ int err; |
733 |
+ struct net *net = cfg->fc_nlinfo.nl_net; |
734 |
+@@ -1735,7 +1735,6 @@ int ip6_route_add(struct fib6_config *cfg) |
735 |
+ struct net_device *dev = NULL; |
736 |
+ struct inet6_dev *idev = NULL; |
737 |
+ struct fib6_table *table; |
738 |
+- struct mx6_config mxc = { .mx = NULL, }; |
739 |
+ int addr_type; |
740 |
+ |
741 |
+ if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128) |
742 |
+@@ -1941,6 +1940,32 @@ install_route: |
743 |
+ |
744 |
+ cfg->fc_nlinfo.nl_net = dev_net(dev); |
745 |
+ |
746 |
++ *rt_ret = rt; |
747 |
++ |
748 |
++ return 0; |
749 |
++out: |
750 |
++ if (dev) |
751 |
++ dev_put(dev); |
752 |
++ if (idev) |
753 |
++ in6_dev_put(idev); |
754 |
++ if (rt) |
755 |
++ dst_free(&rt->dst); |
756 |
++ |
757 |
++ *rt_ret = NULL; |
758 |
++ |
759 |
++ return err; |
760 |
++} |
761 |
++ |
762 |
++int ip6_route_add(struct fib6_config *cfg) |
763 |
++{ |
764 |
++ struct mx6_config mxc = { .mx = NULL, }; |
765 |
++ struct rt6_info *rt = NULL; |
766 |
++ int err; |
767 |
++ |
768 |
++ err = ip6_route_info_create(cfg, &rt); |
769 |
++ if (err) |
770 |
++ goto out; |
771 |
++ |
772 |
+ err = ip6_convert_metrics(&mxc, cfg); |
773 |
+ if (err) |
774 |
+ goto out; |
775 |
+@@ -1948,14 +1973,12 @@ install_route: |
776 |
+ err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc); |
777 |
+ |
778 |
+ kfree(mxc.mx); |
779 |
++ |
780 |
+ return err; |
781 |
+ out: |
782 |
+- if (dev) |
783 |
+- dev_put(dev); |
784 |
+- if (idev) |
785 |
+- in6_dev_put(idev); |
786 |
+ if (rt) |
787 |
+ dst_free(&rt->dst); |
788 |
++ |
789 |
+ return err; |
790 |
+ } |
791 |
+ |
792 |
+@@ -2727,19 +2750,78 @@ errout: |
793 |
+ return err; |
794 |
+ } |
795 |
+ |
796 |
+-static int ip6_route_multipath(struct fib6_config *cfg, int add) |
797 |
++struct rt6_nh { |
798 |
++ struct rt6_info *rt6_info; |
799 |
++ struct fib6_config r_cfg; |
800 |
++ struct mx6_config mxc; |
801 |
++ struct list_head next; |
802 |
++}; |
803 |
++ |
804 |
++static void ip6_print_replace_route_err(struct list_head *rt6_nh_list) |
805 |
++{ |
806 |
++ struct rt6_nh *nh; |
807 |
++ |
808 |
++ list_for_each_entry(nh, rt6_nh_list, next) { |
809 |
++ pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6 nexthop %pI6 ifi %d\n", |
810 |
++ &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway, |
811 |
++ nh->r_cfg.fc_ifindex); |
812 |
++ } |
813 |
++} |
814 |
++ |
815 |
++static int ip6_route_info_append(struct list_head *rt6_nh_list, |
816 |
++ struct rt6_info *rt, struct fib6_config *r_cfg) |
817 |
++{ |
818 |
++ struct rt6_nh *nh; |
819 |
++ struct rt6_info *rtnh; |
820 |
++ int err = -EEXIST; |
821 |
++ |
822 |
++ list_for_each_entry(nh, rt6_nh_list, next) { |
823 |
++ /* check if rt6_info already exists */ |
824 |
++ rtnh = nh->rt6_info; |
825 |
++ |
826 |
++ if (rtnh->dst.dev == rt->dst.dev && |
827 |
++ rtnh->rt6i_idev == rt->rt6i_idev && |
828 |
++ ipv6_addr_equal(&rtnh->rt6i_gateway, |
829 |
++ &rt->rt6i_gateway)) |
830 |
++ return err; |
831 |
++ } |
832 |
++ |
833 |
++ nh = kzalloc(sizeof(*nh), GFP_KERNEL); |
834 |
++ if (!nh) |
835 |
++ return -ENOMEM; |
836 |
++ nh->rt6_info = rt; |
837 |
++ err = ip6_convert_metrics(&nh->mxc, r_cfg); |
838 |
++ if (err) { |
839 |
++ kfree(nh); |
840 |
++ return err; |
841 |
++ } |
842 |
++ memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg)); |
843 |
++ list_add_tail(&nh->next, rt6_nh_list); |
844 |
++ |
845 |
++ return 0; |
846 |
++} |
847 |
++ |
848 |
++static int ip6_route_multipath_add(struct fib6_config *cfg) |
849 |
+ { |
850 |
+ struct fib6_config r_cfg; |
851 |
+ struct rtnexthop *rtnh; |
852 |
++ struct rt6_info *rt; |
853 |
++ struct rt6_nh *err_nh; |
854 |
++ struct rt6_nh *nh, *nh_safe; |
855 |
+ int remaining; |
856 |
+ int attrlen; |
857 |
+- int err = 0, last_err = 0; |
858 |
++ int err = 1; |
859 |
++ int nhn = 0; |
860 |
++ int replace = (cfg->fc_nlinfo.nlh && |
861 |
++ (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE)); |
862 |
++ LIST_HEAD(rt6_nh_list); |
863 |
+ |
864 |
+ remaining = cfg->fc_mp_len; |
865 |
+-beginning: |
866 |
+ rtnh = (struct rtnexthop *)cfg->fc_mp; |
867 |
+ |
868 |
+- /* Parse a Multipath Entry */ |
869 |
++ /* Parse a Multipath Entry and build a list (rt6_nh_list) of |
870 |
++ * rt6_info structs per nexthop |
871 |
++ */ |
872 |
+ while (rtnh_ok(rtnh, remaining)) { |
873 |
+ memcpy(&r_cfg, cfg, sizeof(*cfg)); |
874 |
+ if (rtnh->rtnh_ifindex) |
875 |
+@@ -2755,22 +2837,32 @@ beginning: |
876 |
+ r_cfg.fc_flags |= RTF_GATEWAY; |
877 |
+ } |
878 |
+ } |
879 |
+- err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg); |
880 |
++ |
881 |
++ err = ip6_route_info_create(&r_cfg, &rt); |
882 |
++ if (err) |
883 |
++ goto cleanup; |
884 |
++ |
885 |
++ err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg); |
886 |
+ if (err) { |
887 |
+- last_err = err; |
888 |
+- /* If we are trying to remove a route, do not stop the |
889 |
+- * loop when ip6_route_del() fails (because next hop is |
890 |
+- * already gone), we should try to remove all next hops. |
891 |
+- */ |
892 |
+- if (add) { |
893 |
+- /* If add fails, we should try to delete all |
894 |
+- * next hops that have been already added. |
895 |
+- */ |
896 |
+- add = 0; |
897 |
+- remaining = cfg->fc_mp_len - remaining; |
898 |
+- goto beginning; |
899 |
+- } |
900 |
++ dst_free(&rt->dst); |
901 |
++ goto cleanup; |
902 |
++ } |
903 |
++ |
904 |
++ rtnh = rtnh_next(rtnh, &remaining); |
905 |
++ } |
906 |
++ |
907 |
++ err_nh = NULL; |
908 |
++ list_for_each_entry(nh, &rt6_nh_list, next) { |
909 |
++ err = __ip6_ins_rt(nh->rt6_info, &cfg->fc_nlinfo, &nh->mxc); |
910 |
++ /* nh->rt6_info is used or freed at this point, reset to NULL*/ |
911 |
++ nh->rt6_info = NULL; |
912 |
++ if (err) { |
913 |
++ if (replace && nhn) |
914 |
++ ip6_print_replace_route_err(&rt6_nh_list); |
915 |
++ err_nh = nh; |
916 |
++ goto add_errout; |
917 |
+ } |
918 |
++ |
919 |
+ /* Because each route is added like a single route we remove |
920 |
+ * these flags after the first nexthop: if there is a collision, |
921 |
+ * we have already failed to add the first nexthop: |
922 |
+@@ -2780,6 +2872,63 @@ beginning: |
923 |
+ */ |
924 |
+ cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | |
925 |
+ NLM_F_REPLACE); |
926 |
++ nhn++; |
927 |
++ } |
928 |
++ |
929 |
++ goto cleanup; |
930 |
++ |
931 |
++add_errout: |
932 |
++ /* Delete routes that were already added */ |
933 |
++ list_for_each_entry(nh, &rt6_nh_list, next) { |
934 |
++ if (err_nh == nh) |
935 |
++ break; |
936 |
++ ip6_route_del(&nh->r_cfg); |
937 |
++ } |
938 |
++ |
939 |
++cleanup: |
940 |
++ list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) { |
941 |
++ if (nh->rt6_info) |
942 |
++ dst_free(&nh->rt6_info->dst); |
943 |
++ if (nh->mxc.mx) |
944 |
++ kfree(nh->mxc.mx); |
945 |
++ list_del(&nh->next); |
946 |
++ kfree(nh); |
947 |
++ } |
948 |
++ |
949 |
++ return err; |
950 |
++} |
951 |
++ |
952 |
++static int ip6_route_multipath_del(struct fib6_config *cfg) |
953 |
++{ |
954 |
++ struct fib6_config r_cfg; |
955 |
++ struct rtnexthop *rtnh; |
956 |
++ int remaining; |
957 |
++ int attrlen; |
958 |
++ int err = 1, last_err = 0; |
959 |
++ |
960 |
++ remaining = cfg->fc_mp_len; |
961 |
++ rtnh = (struct rtnexthop *)cfg->fc_mp; |
962 |
++ |
963 |
++ /* Parse a Multipath Entry */ |
964 |
++ while (rtnh_ok(rtnh, remaining)) { |
965 |
++ memcpy(&r_cfg, cfg, sizeof(*cfg)); |
966 |
++ if (rtnh->rtnh_ifindex) |
967 |
++ r_cfg.fc_ifindex = rtnh->rtnh_ifindex; |
968 |
++ |
969 |
++ attrlen = rtnh_attrlen(rtnh); |
970 |
++ if (attrlen > 0) { |
971 |
++ struct nlattr *nla, *attrs = rtnh_attrs(rtnh); |
972 |
++ |
973 |
++ nla = nla_find(attrs, attrlen, RTA_GATEWAY); |
974 |
++ if (nla) { |
975 |
++ nla_memcpy(&r_cfg.fc_gateway, nla, 16); |
976 |
++ r_cfg.fc_flags |= RTF_GATEWAY; |
977 |
++ } |
978 |
++ } |
979 |
++ err = ip6_route_del(&r_cfg); |
980 |
++ if (err) |
981 |
++ last_err = err; |
982 |
++ |
983 |
+ rtnh = rtnh_next(rtnh, &remaining); |
984 |
+ } |
985 |
+ |
986 |
+@@ -2796,7 +2945,7 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh) |
987 |
+ return err; |
988 |
+ |
989 |
+ if (cfg.fc_mp) |
990 |
+- return ip6_route_multipath(&cfg, 0); |
991 |
++ return ip6_route_multipath_del(&cfg); |
992 |
+ else |
993 |
+ return ip6_route_del(&cfg); |
994 |
+ } |
995 |
+@@ -2811,7 +2960,7 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) |
996 |
+ return err; |
997 |
+ |
998 |
+ if (cfg.fc_mp) |
999 |
+- return ip6_route_multipath(&cfg, 1); |
1000 |
++ return ip6_route_multipath_add(&cfg); |
1001 |
+ else |
1002 |
+ return ip6_route_add(&cfg); |
1003 |
+ } |
1004 |
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c |
1005 |
+index a774985489e2..0857f7243797 100644 |
1006 |
+--- a/net/netlink/af_netlink.c |
1007 |
++++ b/net/netlink/af_netlink.c |
1008 |
+@@ -124,6 +124,24 @@ static inline u32 netlink_group_mask(u32 group) |
1009 |
+ return group ? 1 << (group - 1) : 0; |
1010 |
+ } |
1011 |
+ |
1012 |
++static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb, |
1013 |
++ gfp_t gfp_mask) |
1014 |
++{ |
1015 |
++ unsigned int len = skb_end_offset(skb); |
1016 |
++ struct sk_buff *new; |
1017 |
++ |
1018 |
++ new = alloc_skb(len, gfp_mask); |
1019 |
++ if (new == NULL) |
1020 |
++ return NULL; |
1021 |
++ |
1022 |
++ NETLINK_CB(new).portid = NETLINK_CB(skb).portid; |
1023 |
++ NETLINK_CB(new).dst_group = NETLINK_CB(skb).dst_group; |
1024 |
++ NETLINK_CB(new).creds = NETLINK_CB(skb).creds; |
1025 |
++ |
1026 |
++ memcpy(skb_put(new, len), skb->data, len); |
1027 |
++ return new; |
1028 |
++} |
1029 |
++ |
1030 |
+ int netlink_add_tap(struct netlink_tap *nt) |
1031 |
+ { |
1032 |
+ if (unlikely(nt->dev->type != ARPHRD_NETLINK)) |
1033 |
+@@ -205,7 +223,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, |
1034 |
+ int ret = -ENOMEM; |
1035 |
+ |
1036 |
+ dev_hold(dev); |
1037 |
+- nskb = skb_clone(skb, GFP_ATOMIC); |
1038 |
++ |
1039 |
++ if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head)) |
1040 |
++ nskb = netlink_to_full_skb(skb, GFP_ATOMIC); |
1041 |
++ else |
1042 |
++ nskb = skb_clone(skb, GFP_ATOMIC); |
1043 |
+ if (nskb) { |
1044 |
+ nskb->dev = dev; |
1045 |
+ nskb->protocol = htons((u16) sk->sk_protocol); |
1046 |
+@@ -278,11 +300,6 @@ static void netlink_rcv_wake(struct sock *sk) |
1047 |
+ } |
1048 |
+ |
1049 |
+ #ifdef CONFIG_NETLINK_MMAP |
1050 |
+-static bool netlink_skb_is_mmaped(const struct sk_buff *skb) |
1051 |
+-{ |
1052 |
+- return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; |
1053 |
+-} |
1054 |
+- |
1055 |
+ static bool netlink_rx_is_mmaped(struct sock *sk) |
1056 |
+ { |
1057 |
+ return nlk_sk(sk)->rx_ring.pg_vec != NULL; |
1058 |
+@@ -834,7 +851,6 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) |
1059 |
+ } |
1060 |
+ |
1061 |
+ #else /* CONFIG_NETLINK_MMAP */ |
1062 |
+-#define netlink_skb_is_mmaped(skb) false |
1063 |
+ #define netlink_rx_is_mmaped(sk) false |
1064 |
+ #define netlink_tx_is_mmaped(sk) false |
1065 |
+ #define netlink_mmap sock_no_mmap |
1066 |
+@@ -1082,8 +1098,8 @@ static int netlink_insert(struct sock *sk, u32 portid) |
1067 |
+ |
1068 |
+ lock_sock(sk); |
1069 |
+ |
1070 |
+- err = -EBUSY; |
1071 |
+- if (nlk_sk(sk)->portid) |
1072 |
++ err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY; |
1073 |
++ if (nlk_sk(sk)->bound) |
1074 |
+ goto err; |
1075 |
+ |
1076 |
+ err = -ENOMEM; |
1077 |
+@@ -1103,10 +1119,14 @@ static int netlink_insert(struct sock *sk, u32 portid) |
1078 |
+ err = -EOVERFLOW; |
1079 |
+ if (err == -EEXIST) |
1080 |
+ err = -EADDRINUSE; |
1081 |
+- nlk_sk(sk)->portid = 0; |
1082 |
+ sock_put(sk); |
1083 |
++ goto err; |
1084 |
+ } |
1085 |
+ |
1086 |
++ /* We need to ensure that the socket is hashed and visible. */ |
1087 |
++ smp_wmb(); |
1088 |
++ nlk_sk(sk)->bound = portid; |
1089 |
++ |
1090 |
+ err: |
1091 |
+ release_sock(sk); |
1092 |
+ return err; |
1093 |
+@@ -1491,6 +1511,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
1094 |
+ struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
1095 |
+ int err; |
1096 |
+ long unsigned int groups = nladdr->nl_groups; |
1097 |
++ bool bound; |
1098 |
+ |
1099 |
+ if (addr_len < sizeof(struct sockaddr_nl)) |
1100 |
+ return -EINVAL; |
1101 |
+@@ -1507,9 +1528,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
1102 |
+ return err; |
1103 |
+ } |
1104 |
+ |
1105 |
+- if (nlk->portid) |
1106 |
++ bound = nlk->bound; |
1107 |
++ if (bound) { |
1108 |
++ /* Ensure nlk->portid is up-to-date. */ |
1109 |
++ smp_rmb(); |
1110 |
++ |
1111 |
+ if (nladdr->nl_pid != nlk->portid) |
1112 |
+ return -EINVAL; |
1113 |
++ } |
1114 |
+ |
1115 |
+ if (nlk->netlink_bind && groups) { |
1116 |
+ int group; |
1117 |
+@@ -1525,7 +1551,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
1118 |
+ } |
1119 |
+ } |
1120 |
+ |
1121 |
+- if (!nlk->portid) { |
1122 |
++ /* No need for barriers here as we return to user-space without |
1123 |
++ * using any of the bound attributes. |
1124 |
++ */ |
1125 |
++ if (!bound) { |
1126 |
+ err = nladdr->nl_pid ? |
1127 |
+ netlink_insert(sk, nladdr->nl_pid) : |
1128 |
+ netlink_autobind(sock); |
1129 |
+@@ -1573,7 +1602,10 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, |
1130 |
+ !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
1131 |
+ return -EPERM; |
1132 |
+ |
1133 |
+- if (!nlk->portid) |
1134 |
++ /* No need for barriers here as we return to user-space without |
1135 |
++ * using any of the bound attributes. |
1136 |
++ */ |
1137 |
++ if (!nlk->bound) |
1138 |
+ err = netlink_autobind(sock); |
1139 |
+ |
1140 |
+ if (err == 0) { |
1141 |
+@@ -2391,10 +2423,13 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
1142 |
+ dst_group = nlk->dst_group; |
1143 |
+ } |
1144 |
+ |
1145 |
+- if (!nlk->portid) { |
1146 |
++ if (!nlk->bound) { |
1147 |
+ err = netlink_autobind(sock); |
1148 |
+ if (err) |
1149 |
+ goto out; |
1150 |
++ } else { |
1151 |
++ /* Ensure nlk is hashed and visible. */ |
1152 |
++ smp_rmb(); |
1153 |
+ } |
1154 |
+ |
1155 |
+ /* It's a really convoluted way for userland to ask for mmaped |
1156 |
+diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h |
1157 |
+index 89008405d6b4..14437d9b1965 100644 |
1158 |
+--- a/net/netlink/af_netlink.h |
1159 |
++++ b/net/netlink/af_netlink.h |
1160 |
+@@ -35,6 +35,7 @@ struct netlink_sock { |
1161 |
+ unsigned long state; |
1162 |
+ size_t max_recvmsg_len; |
1163 |
+ wait_queue_head_t wait; |
1164 |
++ bool bound; |
1165 |
+ bool cb_running; |
1166 |
+ struct netlink_callback cb; |
1167 |
+ struct mutex *cb_mutex; |
1168 |
+@@ -59,6 +60,15 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) |
1169 |
+ return container_of(sk, struct netlink_sock, sk); |
1170 |
+ } |
1171 |
+ |
1172 |
++static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb) |
1173 |
++{ |
1174 |
++#ifdef CONFIG_NETLINK_MMAP |
1175 |
++ return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; |
1176 |
++#else |
1177 |
++ return false; |
1178 |
++#endif /* CONFIG_NETLINK_MMAP */ |
1179 |
++} |
1180 |
++ |
1181 |
+ struct netlink_table { |
1182 |
+ struct rhashtable hash; |
1183 |
+ struct hlist_head mc_list; |
1184 |
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c |
1185 |
+index ff8c4a4c1609..ff332d1b94bc 100644 |
1186 |
+--- a/net/openvswitch/datapath.c |
1187 |
++++ b/net/openvswitch/datapath.c |
1188 |
+@@ -920,7 +920,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) |
1189 |
+ if (error) |
1190 |
+ goto err_kfree_flow; |
1191 |
+ |
1192 |
+- ovs_flow_mask_key(&new_flow->key, &key, &mask); |
1193 |
++ ovs_flow_mask_key(&new_flow->key, &key, true, &mask); |
1194 |
+ |
1195 |
+ /* Extract flow identifier. */ |
1196 |
+ error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], |
1197 |
+@@ -1047,7 +1047,7 @@ static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, |
1198 |
+ struct sw_flow_key masked_key; |
1199 |
+ int error; |
1200 |
+ |
1201 |
+- ovs_flow_mask_key(&masked_key, key, mask); |
1202 |
++ ovs_flow_mask_key(&masked_key, key, true, mask); |
1203 |
+ error = ovs_nla_copy_actions(a, &masked_key, &acts, log); |
1204 |
+ if (error) { |
1205 |
+ OVS_NLERR(log, |
1206 |
+diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c |
1207 |
+index 65523948fb95..b5c3bba87fc8 100644 |
1208 |
+--- a/net/openvswitch/flow_table.c |
1209 |
++++ b/net/openvswitch/flow_table.c |
1210 |
+@@ -56,20 +56,21 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range) |
1211 |
+ } |
1212 |
+ |
1213 |
+ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, |
1214 |
+- const struct sw_flow_mask *mask) |
1215 |
++ bool full, const struct sw_flow_mask *mask) |
1216 |
+ { |
1217 |
+- const long *m = (const long *)((const u8 *)&mask->key + |
1218 |
+- mask->range.start); |
1219 |
+- const long *s = (const long *)((const u8 *)src + |
1220 |
+- mask->range.start); |
1221 |
+- long *d = (long *)((u8 *)dst + mask->range.start); |
1222 |
++ int start = full ? 0 : mask->range.start; |
1223 |
++ int len = full ? sizeof *dst : range_n_bytes(&mask->range); |
1224 |
++ const long *m = (const long *)((const u8 *)&mask->key + start); |
1225 |
++ const long *s = (const long *)((const u8 *)src + start); |
1226 |
++ long *d = (long *)((u8 *)dst + start); |
1227 |
+ int i; |
1228 |
+ |
1229 |
+- /* The memory outside of the 'mask->range' are not set since |
1230 |
+- * further operations on 'dst' only uses contents within |
1231 |
+- * 'mask->range'. |
1232 |
++ /* If 'full' is true then all of 'dst' is fully initialized. Otherwise, |
1233 |
++ * if 'full' is false the memory outside of the 'mask->range' is left |
1234 |
++ * uninitialized. This can be used as an optimization when further |
1235 |
++ * operations on 'dst' only use contents within 'mask->range'. |
1236 |
+ */ |
1237 |
+- for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long)) |
1238 |
++ for (i = 0; i < len; i += sizeof(long)) |
1239 |
+ *d++ = *s++ & *m++; |
1240 |
+ } |
1241 |
+ |
1242 |
+@@ -473,7 +474,7 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti, |
1243 |
+ u32 hash; |
1244 |
+ struct sw_flow_key masked_key; |
1245 |
+ |
1246 |
+- ovs_flow_mask_key(&masked_key, unmasked, mask); |
1247 |
++ ovs_flow_mask_key(&masked_key, unmasked, false, mask); |
1248 |
+ hash = flow_hash(&masked_key, &mask->range); |
1249 |
+ head = find_bucket(ti, hash); |
1250 |
+ hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) { |
1251 |
+diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h |
1252 |
+index 616eda10d955..2dd9900f533d 100644 |
1253 |
+--- a/net/openvswitch/flow_table.h |
1254 |
++++ b/net/openvswitch/flow_table.h |
1255 |
+@@ -86,5 +86,5 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *, |
1256 |
+ bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *); |
1257 |
+ |
1258 |
+ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, |
1259 |
+- const struct sw_flow_mask *mask); |
1260 |
++ bool full, const struct sw_flow_mask *mask); |
1261 |
+ #endif /* flow_table.h */ |
1262 |
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c |
1263 |
+index ed458b315ef4..7851b1222a36 100644 |
1264 |
+--- a/net/packet/af_packet.c |
1265 |
++++ b/net/packet/af_packet.c |
1266 |
+@@ -229,6 +229,8 @@ struct packet_skb_cb { |
1267 |
+ } sa; |
1268 |
+ }; |
1269 |
+ |
1270 |
++#define vio_le() virtio_legacy_is_little_endian() |
1271 |
++ |
1272 |
+ #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) |
1273 |
+ |
1274 |
+ #define GET_PBDQC_FROM_RB(x) ((struct tpacket_kbdq_core *)(&(x)->prb_bdqc)) |
1275 |
+@@ -2561,15 +2563,15 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) |
1276 |
+ goto out_unlock; |
1277 |
+ |
1278 |
+ if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
1279 |
+- (__virtio16_to_cpu(false, vnet_hdr.csum_start) + |
1280 |
+- __virtio16_to_cpu(false, vnet_hdr.csum_offset) + 2 > |
1281 |
+- __virtio16_to_cpu(false, vnet_hdr.hdr_len))) |
1282 |
+- vnet_hdr.hdr_len = __cpu_to_virtio16(false, |
1283 |
+- __virtio16_to_cpu(false, vnet_hdr.csum_start) + |
1284 |
+- __virtio16_to_cpu(false, vnet_hdr.csum_offset) + 2); |
1285 |
++ (__virtio16_to_cpu(vio_le(), vnet_hdr.csum_start) + |
1286 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset) + 2 > |
1287 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len))) |
1288 |
++ vnet_hdr.hdr_len = __cpu_to_virtio16(vio_le(), |
1289 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start) + |
1290 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset) + 2); |
1291 |
+ |
1292 |
+ err = -EINVAL; |
1293 |
+- if (__virtio16_to_cpu(false, vnet_hdr.hdr_len) > len) |
1294 |
++ if (__virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len) > len) |
1295 |
+ goto out_unlock; |
1296 |
+ |
1297 |
+ if (vnet_hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
1298 |
+@@ -2612,7 +2614,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) |
1299 |
+ hlen = LL_RESERVED_SPACE(dev); |
1300 |
+ tlen = dev->needed_tailroom; |
1301 |
+ skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, |
1302 |
+- __virtio16_to_cpu(false, vnet_hdr.hdr_len), |
1303 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len), |
1304 |
+ msg->msg_flags & MSG_DONTWAIT, &err); |
1305 |
+ if (skb == NULL) |
1306 |
+ goto out_unlock; |
1307 |
+@@ -2659,8 +2661,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) |
1308 |
+ |
1309 |
+ if (po->has_vnet_hdr) { |
1310 |
+ if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { |
1311 |
+- u16 s = __virtio16_to_cpu(false, vnet_hdr.csum_start); |
1312 |
+- u16 o = __virtio16_to_cpu(false, vnet_hdr.csum_offset); |
1313 |
++ u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start); |
1314 |
++ u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset); |
1315 |
+ if (!skb_partial_csum_set(skb, s, o)) { |
1316 |
+ err = -EINVAL; |
1317 |
+ goto out_free; |
1318 |
+@@ -2668,7 +2670,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) |
1319 |
+ } |
1320 |
+ |
1321 |
+ skb_shinfo(skb)->gso_size = |
1322 |
+- __virtio16_to_cpu(false, vnet_hdr.gso_size); |
1323 |
++ __virtio16_to_cpu(vio_le(), vnet_hdr.gso_size); |
1324 |
+ skb_shinfo(skb)->gso_type = gso_type; |
1325 |
+ |
1326 |
+ /* Header must be checked, and gso_segs computed. */ |
1327 |
+@@ -3042,9 +3044,9 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, |
1328 |
+ |
1329 |
+ /* This is a hint as to how much should be linear. */ |
1330 |
+ vnet_hdr.hdr_len = |
1331 |
+- __cpu_to_virtio16(false, skb_headlen(skb)); |
1332 |
++ __cpu_to_virtio16(vio_le(), skb_headlen(skb)); |
1333 |
+ vnet_hdr.gso_size = |
1334 |
+- __cpu_to_virtio16(false, sinfo->gso_size); |
1335 |
++ __cpu_to_virtio16(vio_le(), sinfo->gso_size); |
1336 |
+ if (sinfo->gso_type & SKB_GSO_TCPV4) |
1337 |
+ vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
1338 |
+ else if (sinfo->gso_type & SKB_GSO_TCPV6) |
1339 |
+@@ -3062,9 +3064,9 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, |
1340 |
+ |
1341 |
+ if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1342 |
+ vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; |
1343 |
+- vnet_hdr.csum_start = __cpu_to_virtio16(false, |
1344 |
++ vnet_hdr.csum_start = __cpu_to_virtio16(vio_le(), |
1345 |
+ skb_checksum_start_offset(skb)); |
1346 |
+- vnet_hdr.csum_offset = __cpu_to_virtio16(false, |
1347 |
++ vnet_hdr.csum_offset = __cpu_to_virtio16(vio_le(), |
1348 |
+ skb->csum_offset); |
1349 |
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { |
1350 |
+ vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID; |
1351 |
+diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c |
1352 |
+index 715e01e5910a..f23a3b68bba6 100644 |
1353 |
+--- a/net/sched/cls_fw.c |
1354 |
++++ b/net/sched/cls_fw.c |
1355 |
+@@ -33,7 +33,6 @@ |
1356 |
+ |
1357 |
+ struct fw_head { |
1358 |
+ u32 mask; |
1359 |
+- bool mask_set; |
1360 |
+ struct fw_filter __rcu *ht[HTSIZE]; |
1361 |
+ struct rcu_head rcu; |
1362 |
+ }; |
1363 |
+@@ -84,7 +83,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
1364 |
+ } |
1365 |
+ } |
1366 |
+ } else { |
1367 |
+- /* old method */ |
1368 |
++ /* Old method: classify the packet using its skb mark. */ |
1369 |
+ if (id && (TC_H_MAJ(id) == 0 || |
1370 |
+ !(TC_H_MAJ(id ^ tp->q->handle)))) { |
1371 |
+ res->classid = id; |
1372 |
+@@ -114,14 +113,9 @@ static unsigned long fw_get(struct tcf_proto *tp, u32 handle) |
1373 |
+ |
1374 |
+ static int fw_init(struct tcf_proto *tp) |
1375 |
+ { |
1376 |
+- struct fw_head *head; |
1377 |
+- |
1378 |
+- head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); |
1379 |
+- if (head == NULL) |
1380 |
+- return -ENOBUFS; |
1381 |
+- |
1382 |
+- head->mask_set = false; |
1383 |
+- rcu_assign_pointer(tp->root, head); |
1384 |
++ /* We don't allocate fw_head here, because in the old method |
1385 |
++ * we don't need it at all. |
1386 |
++ */ |
1387 |
+ return 0; |
1388 |
+ } |
1389 |
+ |
1390 |
+@@ -252,7 +246,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, |
1391 |
+ int err; |
1392 |
+ |
1393 |
+ if (!opt) |
1394 |
+- return handle ? -EINVAL : 0; |
1395 |
++ return handle ? -EINVAL : 0; /* Succeed if it is old method. */ |
1396 |
+ |
1397 |
+ err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy); |
1398 |
+ if (err < 0) |
1399 |
+@@ -302,11 +296,17 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, |
1400 |
+ if (!handle) |
1401 |
+ return -EINVAL; |
1402 |
+ |
1403 |
+- if (!head->mask_set) { |
1404 |
+- head->mask = 0xFFFFFFFF; |
1405 |
++ if (!head) { |
1406 |
++ u32 mask = 0xFFFFFFFF; |
1407 |
+ if (tb[TCA_FW_MASK]) |
1408 |
+- head->mask = nla_get_u32(tb[TCA_FW_MASK]); |
1409 |
+- head->mask_set = true; |
1410 |
++ mask = nla_get_u32(tb[TCA_FW_MASK]); |
1411 |
++ |
1412 |
++ head = kzalloc(sizeof(*head), GFP_KERNEL); |
1413 |
++ if (!head) |
1414 |
++ return -ENOBUFS; |
1415 |
++ head->mask = mask; |
1416 |
++ |
1417 |
++ rcu_assign_pointer(tp->root, head); |
1418 |
+ } |
1419 |
+ |
1420 |
+ f = kzalloc(sizeof(struct fw_filter), GFP_KERNEL); |
1421 |
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c |
1422 |
+index 59e80356672b..3ac604f96da0 100644 |
1423 |
+--- a/net/sctp/protocol.c |
1424 |
++++ b/net/sctp/protocol.c |
1425 |
+@@ -1166,7 +1166,7 @@ static void sctp_v4_del_protocol(void) |
1426 |
+ unregister_inetaddr_notifier(&sctp_inetaddr_notifier); |
1427 |
+ } |
1428 |
+ |
1429 |
+-static int __net_init sctp_net_init(struct net *net) |
1430 |
++static int __net_init sctp_defaults_init(struct net *net) |
1431 |
+ { |
1432 |
+ int status; |
1433 |
+ |
1434 |
+@@ -1259,12 +1259,6 @@ static int __net_init sctp_net_init(struct net *net) |
1435 |
+ |
1436 |
+ sctp_dbg_objcnt_init(net); |
1437 |
+ |
1438 |
+- /* Initialize the control inode/socket for handling OOTB packets. */ |
1439 |
+- if ((status = sctp_ctl_sock_init(net))) { |
1440 |
+- pr_err("Failed to initialize the SCTP control sock\n"); |
1441 |
+- goto err_ctl_sock_init; |
1442 |
+- } |
1443 |
+- |
1444 |
+ /* Initialize the local address list. */ |
1445 |
+ INIT_LIST_HEAD(&net->sctp.local_addr_list); |
1446 |
+ spin_lock_init(&net->sctp.local_addr_lock); |
1447 |
+@@ -1280,9 +1274,6 @@ static int __net_init sctp_net_init(struct net *net) |
1448 |
+ |
1449 |
+ return 0; |
1450 |
+ |
1451 |
+-err_ctl_sock_init: |
1452 |
+- sctp_dbg_objcnt_exit(net); |
1453 |
+- sctp_proc_exit(net); |
1454 |
+ err_init_proc: |
1455 |
+ cleanup_sctp_mibs(net); |
1456 |
+ err_init_mibs: |
1457 |
+@@ -1291,15 +1282,12 @@ err_sysctl_register: |
1458 |
+ return status; |
1459 |
+ } |
1460 |
+ |
1461 |
+-static void __net_exit sctp_net_exit(struct net *net) |
1462 |
++static void __net_exit sctp_defaults_exit(struct net *net) |
1463 |
+ { |
1464 |
+ /* Free the local address list */ |
1465 |
+ sctp_free_addr_wq(net); |
1466 |
+ sctp_free_local_addr_list(net); |
1467 |
+ |
1468 |
+- /* Free the control endpoint. */ |
1469 |
+- inet_ctl_sock_destroy(net->sctp.ctl_sock); |
1470 |
+- |
1471 |
+ sctp_dbg_objcnt_exit(net); |
1472 |
+ |
1473 |
+ sctp_proc_exit(net); |
1474 |
+@@ -1307,9 +1295,32 @@ static void __net_exit sctp_net_exit(struct net *net) |
1475 |
+ sctp_sysctl_net_unregister(net); |
1476 |
+ } |
1477 |
+ |
1478 |
+-static struct pernet_operations sctp_net_ops = { |
1479 |
+- .init = sctp_net_init, |
1480 |
+- .exit = sctp_net_exit, |
1481 |
++static struct pernet_operations sctp_defaults_ops = { |
1482 |
++ .init = sctp_defaults_init, |
1483 |
++ .exit = sctp_defaults_exit, |
1484 |
++}; |
1485 |
++ |
1486 |
++static int __net_init sctp_ctrlsock_init(struct net *net) |
1487 |
++{ |
1488 |
++ int status; |
1489 |
++ |
1490 |
++ /* Initialize the control inode/socket for handling OOTB packets. */ |
1491 |
++ status = sctp_ctl_sock_init(net); |
1492 |
++ if (status) |
1493 |
++ pr_err("Failed to initialize the SCTP control sock\n"); |
1494 |
++ |
1495 |
++ return status; |
1496 |
++} |
1497 |
++ |
1498 |
++static void __net_init sctp_ctrlsock_exit(struct net *net) |
1499 |
++{ |
1500 |
++ /* Free the control endpoint. */ |
1501 |
++ inet_ctl_sock_destroy(net->sctp.ctl_sock); |
1502 |
++} |
1503 |
++ |
1504 |
++static struct pernet_operations sctp_ctrlsock_ops = { |
1505 |
++ .init = sctp_ctrlsock_init, |
1506 |
++ .exit = sctp_ctrlsock_exit, |
1507 |
+ }; |
1508 |
+ |
1509 |
+ /* Initialize the universe into something sensible. */ |
1510 |
+@@ -1442,8 +1453,11 @@ static __init int sctp_init(void) |
1511 |
+ sctp_v4_pf_init(); |
1512 |
+ sctp_v6_pf_init(); |
1513 |
+ |
1514 |
+- status = sctp_v4_protosw_init(); |
1515 |
++ status = register_pernet_subsys(&sctp_defaults_ops); |
1516 |
++ if (status) |
1517 |
++ goto err_register_defaults; |
1518 |
+ |
1519 |
++ status = sctp_v4_protosw_init(); |
1520 |
+ if (status) |
1521 |
+ goto err_protosw_init; |
1522 |
+ |
1523 |
+@@ -1451,9 +1465,9 @@ static __init int sctp_init(void) |
1524 |
+ if (status) |
1525 |
+ goto err_v6_protosw_init; |
1526 |
+ |
1527 |
+- status = register_pernet_subsys(&sctp_net_ops); |
1528 |
++ status = register_pernet_subsys(&sctp_ctrlsock_ops); |
1529 |
+ if (status) |
1530 |
+- goto err_register_pernet_subsys; |
1531 |
++ goto err_register_ctrlsock; |
1532 |
+ |
1533 |
+ status = sctp_v4_add_protocol(); |
1534 |
+ if (status) |
1535 |
+@@ -1469,12 +1483,14 @@ out: |
1536 |
+ err_v6_add_protocol: |
1537 |
+ sctp_v4_del_protocol(); |
1538 |
+ err_add_protocol: |
1539 |
+- unregister_pernet_subsys(&sctp_net_ops); |
1540 |
+-err_register_pernet_subsys: |
1541 |
++ unregister_pernet_subsys(&sctp_ctrlsock_ops); |
1542 |
++err_register_ctrlsock: |
1543 |
+ sctp_v6_protosw_exit(); |
1544 |
+ err_v6_protosw_init: |
1545 |
+ sctp_v4_protosw_exit(); |
1546 |
+ err_protosw_init: |
1547 |
++ unregister_pernet_subsys(&sctp_defaults_ops); |
1548 |
++err_register_defaults: |
1549 |
+ sctp_v4_pf_exit(); |
1550 |
+ sctp_v6_pf_exit(); |
1551 |
+ sctp_sysctl_unregister(); |
1552 |
+@@ -1507,12 +1523,14 @@ static __exit void sctp_exit(void) |
1553 |
+ sctp_v6_del_protocol(); |
1554 |
+ sctp_v4_del_protocol(); |
1555 |
+ |
1556 |
+- unregister_pernet_subsys(&sctp_net_ops); |
1557 |
++ unregister_pernet_subsys(&sctp_ctrlsock_ops); |
1558 |
+ |
1559 |
+ /* Free protosw registrations */ |
1560 |
+ sctp_v6_protosw_exit(); |
1561 |
+ sctp_v4_protosw_exit(); |
1562 |
+ |
1563 |
++ unregister_pernet_subsys(&sctp_defaults_ops); |
1564 |
++ |
1565 |
+ /* Unregister with socket layer. */ |
1566 |
+ sctp_v6_pf_exit(); |
1567 |
+ sctp_v4_pf_exit(); |