]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/hv_netvsc-refactor-assignments-of-struct-netvsc_devi.patch
Linux 4.14.105
[thirdparty/kernel/stable-queue.git] / queue-4.19 / hv_netvsc-refactor-assignments-of-struct-netvsc_devi.patch
1 From 6e780175fc320cdbef7a9a199b7735f63c17f035 Mon Sep 17 00:00:00 2001
2 From: Haiyang Zhang <haiyangz@microsoft.com>
3 Date: Tue, 15 Jan 2019 00:51:43 +0000
4 Subject: hv_netvsc: Refactor assignments of struct netvsc_device_info
5
6 [ Upstream commit 7c9f335a3ff20557a92584199f3d35c7e992bbe5 ]
7
8 These assignments occur in multiple places. The patch refactor them
9 to a function for simplicity. It also puts the struct to heap area
10 for future expension.
11
12 Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
13 Reviewed-by: Michael Kelley <mikelley@microsoft.com>
14 [sl: fix up subject line]
15 Signed-off-by: Sasha Levin <sashal@kernel.org>
16 ---
17 drivers/net/hyperv/netvsc_drv.c | 134 ++++++++++++++++++++------------
18 1 file changed, 85 insertions(+), 49 deletions(-)
19
20 diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
21 index 1c37a821895b7..bece935567c14 100644
22 --- a/drivers/net/hyperv/netvsc_drv.c
23 +++ b/drivers/net/hyperv/netvsc_drv.c
24 @@ -856,6 +856,36 @@ static void netvsc_get_channels(struct net_device *net,
25 }
26 }
27
28 +/* Alloc struct netvsc_device_info, and initialize it from either existing
29 + * struct netvsc_device, or from default values.
30 + */
31 +static struct netvsc_device_info *netvsc_devinfo_get
32 + (struct netvsc_device *nvdev)
33 +{
34 + struct netvsc_device_info *dev_info;
35 +
36 + dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);
37 +
38 + if (!dev_info)
39 + return NULL;
40 +
41 + if (nvdev) {
42 + dev_info->num_chn = nvdev->num_chn;
43 + dev_info->send_sections = nvdev->send_section_cnt;
44 + dev_info->send_section_size = nvdev->send_section_size;
45 + dev_info->recv_sections = nvdev->recv_section_cnt;
46 + dev_info->recv_section_size = nvdev->recv_section_size;
47 + } else {
48 + dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
49 + dev_info->send_sections = NETVSC_DEFAULT_TX;
50 + dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
51 + dev_info->recv_sections = NETVSC_DEFAULT_RX;
52 + dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
53 + }
54 +
55 + return dev_info;
56 +}
57 +
58 static int netvsc_detach(struct net_device *ndev,
59 struct netvsc_device *nvdev)
60 {
61 @@ -941,7 +971,7 @@ static int netvsc_set_channels(struct net_device *net,
62 struct net_device_context *net_device_ctx = netdev_priv(net);
63 struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
64 unsigned int orig, count = channels->combined_count;
65 - struct netvsc_device_info device_info;
66 + struct netvsc_device_info *device_info;
67 int ret;
68
69 /* We do not support separate count for rx, tx, or other */
70 @@ -960,24 +990,26 @@ static int netvsc_set_channels(struct net_device *net,
71
72 orig = nvdev->num_chn;
73
74 - memset(&device_info, 0, sizeof(device_info));
75 - device_info.num_chn = count;
76 - device_info.send_sections = nvdev->send_section_cnt;
77 - device_info.send_section_size = nvdev->send_section_size;
78 - device_info.recv_sections = nvdev->recv_section_cnt;
79 - device_info.recv_section_size = nvdev->recv_section_size;
80 + device_info = netvsc_devinfo_get(nvdev);
81 +
82 + if (!device_info)
83 + return -ENOMEM;
84 +
85 + device_info->num_chn = count;
86
87 ret = netvsc_detach(net, nvdev);
88 if (ret)
89 - return ret;
90 + goto out;
91
92 - ret = netvsc_attach(net, &device_info);
93 + ret = netvsc_attach(net, device_info);
94 if (ret) {
95 - device_info.num_chn = orig;
96 - if (netvsc_attach(net, &device_info))
97 + device_info->num_chn = orig;
98 + if (netvsc_attach(net, device_info))
99 netdev_err(net, "restoring channel setting failed\n");
100 }
101
102 +out:
103 + kfree(device_info);
104 return ret;
105 }
106
107 @@ -1044,48 +1076,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
108 struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
109 struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
110 int orig_mtu = ndev->mtu;
111 - struct netvsc_device_info device_info;
112 + struct netvsc_device_info *device_info;
113 int ret = 0;
114
115 if (!nvdev || nvdev->destroy)
116 return -ENODEV;
117
118 + device_info = netvsc_devinfo_get(nvdev);
119 +
120 + if (!device_info)
121 + return -ENOMEM;
122 +
123 /* Change MTU of underlying VF netdev first. */
124 if (vf_netdev) {
125 ret = dev_set_mtu(vf_netdev, mtu);
126 if (ret)
127 - return ret;
128 + goto out;
129 }
130
131 - memset(&device_info, 0, sizeof(device_info));
132 - device_info.num_chn = nvdev->num_chn;
133 - device_info.send_sections = nvdev->send_section_cnt;
134 - device_info.send_section_size = nvdev->send_section_size;
135 - device_info.recv_sections = nvdev->recv_section_cnt;
136 - device_info.recv_section_size = nvdev->recv_section_size;
137 -
138 ret = netvsc_detach(ndev, nvdev);
139 if (ret)
140 goto rollback_vf;
141
142 ndev->mtu = mtu;
143
144 - ret = netvsc_attach(ndev, &device_info);
145 - if (ret)
146 - goto rollback;
147 -
148 - return 0;
149 + ret = netvsc_attach(ndev, device_info);
150 + if (!ret)
151 + goto out;
152
153 -rollback:
154 /* Attempt rollback to original MTU */
155 ndev->mtu = orig_mtu;
156
157 - if (netvsc_attach(ndev, &device_info))
158 + if (netvsc_attach(ndev, device_info))
159 netdev_err(ndev, "restoring mtu failed\n");
160 rollback_vf:
161 if (vf_netdev)
162 dev_set_mtu(vf_netdev, orig_mtu);
163
164 +out:
165 + kfree(device_info);
166 return ret;
167 }
168
169 @@ -1690,7 +1719,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
170 {
171 struct net_device_context *ndevctx = netdev_priv(ndev);
172 struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
173 - struct netvsc_device_info device_info;
174 + struct netvsc_device_info *device_info;
175 struct ethtool_ringparam orig;
176 u32 new_tx, new_rx;
177 int ret = 0;
178 @@ -1710,26 +1739,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
179 new_rx == orig.rx_pending)
180 return 0; /* no change */
181
182 - memset(&device_info, 0, sizeof(device_info));
183 - device_info.num_chn = nvdev->num_chn;
184 - device_info.send_sections = new_tx;
185 - device_info.send_section_size = nvdev->send_section_size;
186 - device_info.recv_sections = new_rx;
187 - device_info.recv_section_size = nvdev->recv_section_size;
188 + device_info = netvsc_devinfo_get(nvdev);
189 +
190 + if (!device_info)
191 + return -ENOMEM;
192 +
193 + device_info->send_sections = new_tx;
194 + device_info->recv_sections = new_rx;
195
196 ret = netvsc_detach(ndev, nvdev);
197 if (ret)
198 - return ret;
199 + goto out;
200
201 - ret = netvsc_attach(ndev, &device_info);
202 + ret = netvsc_attach(ndev, device_info);
203 if (ret) {
204 - device_info.send_sections = orig.tx_pending;
205 - device_info.recv_sections = orig.rx_pending;
206 + device_info->send_sections = orig.tx_pending;
207 + device_info->recv_sections = orig.rx_pending;
208
209 - if (netvsc_attach(ndev, &device_info))
210 + if (netvsc_attach(ndev, device_info))
211 netdev_err(ndev, "restoring ringparam failed");
212 }
213
214 +out:
215 + kfree(device_info);
216 return ret;
217 }
218
219 @@ -2158,7 +2190,7 @@ static int netvsc_probe(struct hv_device *dev,
220 {
221 struct net_device *net = NULL;
222 struct net_device_context *net_device_ctx;
223 - struct netvsc_device_info device_info;
224 + struct netvsc_device_info *device_info = NULL;
225 struct netvsc_device *nvdev;
226 int ret = -ENOMEM;
227
228 @@ -2205,21 +2237,21 @@ static int netvsc_probe(struct hv_device *dev,
229 netif_set_real_num_rx_queues(net, 1);
230
231 /* Notify the netvsc driver of the new device */
232 - memset(&device_info, 0, sizeof(device_info));
233 - device_info.num_chn = VRSS_CHANNEL_DEFAULT;
234 - device_info.send_sections = NETVSC_DEFAULT_TX;
235 - device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
236 - device_info.recv_sections = NETVSC_DEFAULT_RX;
237 - device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
238 -
239 - nvdev = rndis_filter_device_add(dev, &device_info);
240 + device_info = netvsc_devinfo_get(NULL);
241 +
242 + if (!device_info) {
243 + ret = -ENOMEM;
244 + goto devinfo_failed;
245 + }
246 +
247 + nvdev = rndis_filter_device_add(dev, device_info);
248 if (IS_ERR(nvdev)) {
249 ret = PTR_ERR(nvdev);
250 netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
251 goto rndis_failed;
252 }
253
254 - memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
255 + memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);
256
257 /* We must get rtnl lock before scheduling nvdev->subchan_work,
258 * otherwise netvsc_subchan_work() can get rtnl lock first and wait
259 @@ -2257,12 +2289,16 @@ static int netvsc_probe(struct hv_device *dev,
260
261 list_add(&net_device_ctx->list, &netvsc_dev_list);
262 rtnl_unlock();
263 +
264 + kfree(device_info);
265 return 0;
266
267 register_failed:
268 rtnl_unlock();
269 rndis_filter_device_remove(dev, nvdev);
270 rndis_failed:
271 + kfree(device_info);
272 +devinfo_failed:
273 free_percpu(net_device_ctx->vf_stats);
274 no_stats:
275 hv_set_drvdata(dev, NULL);
276 --
277 2.19.1
278