]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.0/net-hns3-fix-null-deref-when-unloading-driver.patch
autosel patches for 5.0
[thirdparty/kernel/stable-queue.git] / queue-5.0 / net-hns3-fix-null-deref-when-unloading-driver.patch
1 From 5b03e2a62bf9fb506b584c6c8641f37465834aa1 Mon Sep 17 00:00:00 2001
2 From: Huazhong Tan <tanhuazhong@huawei.com>
3 Date: Thu, 31 Jan 2019 04:55:46 +0800
4 Subject: net: hns3: Fix NULL deref when unloading driver
5
6 [ Upstream commit c8a8045b2d0a974149d65bbe6a7acbcde93cf85b ]
7
8 When the driver is unloading, if there is a calling of ndo_open occurs
9 between phy_disconnect() and unregister_netdev(), it will end up
10 causing the kernel to eventually hit a NULL deref:
11
12 [14942.417828] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
13 [14942.529878] Mem abort info:
14 [14942.551166] ESR = 0x96000006
15 [14942.567070] Exception class = DABT (current EL), IL = 32 bits
16 [14942.623081] SET = 0, FnV = 0
17 [14942.639112] EA = 0, S1PTW = 0
18 [14942.643628] Data abort info:
19 [14942.659227] ISV = 0, ISS = 0x00000006
20 [14942.674870] CM = 0, WnR = 0
21 [14942.679449] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000224ad6ad
22 [14942.695595] [0000000000000048] pgd=00000021e6673003, pud=00000021dbf01003, pmd=0000000000000000
23 [14942.723163] Internal error: Oops: 96000006 [#1] PREEMPT SMP
24 [14942.729358] Modules linked in: hns3(O) hclge(O) pv680_mii(O) hnae3(O) [last unloaded: hclge]
25 [14942.738907] CPU: 1 PID: 26629 Comm: kworker/u4:13 Tainted: G O 4.18.0-rc1-12928-ga960791-dirty #145
26 [14942.749491] Hardware name: Huawei Technologies Co., Ltd. D05/D05, BIOS Hi1620 FPGA TB BOOT BIOS B763 08/17/2018
27 [14942.760392] Workqueue: events_power_efficient phy_state_machine
28 [14942.766644] pstate: 80c00009 (Nzcv daif +PAN +UAO)
29 [14942.771918] pc : test_and_set_bit+0x18/0x38
30 [14942.776589] lr : netif_carrier_off+0x24/0x70
31 [14942.781033] sp : ffff0000121abd20
32 [14942.784518] x29: ffff0000121abd20 x28: 0000000000000000
33 [14942.790208] x27: ffff0000164d3cd8 x26: ffff8021da68b7b8
34 [14942.795832] x25: 0000000000000000 x24: ffff8021eb407800
35 [14942.801445] x23: 0000000000000000 x22: 0000000000000000
36 [14942.807046] x21: 0000000000000001 x20: 0000000000000000
37 [14942.812672] x19: 0000000000000000 x18: ffff000009781708
38 [14942.818284] x17: 00000000004970e8 x16: ffff00000816ad48
39 [14942.823900] x15: 0000000000000000 x14: 0000000000000008
40 [14942.829528] x13: 0000000000000000 x12: 0000000000000f65
41 [14942.835149] x11: 0000000000000001 x10: 00000000000009d0
42 [14942.840753] x9 : ffff0000121abaa0 x8 : 0000000000000000
43 [14942.846360] x7 : ffff000009781708 x6 : 0000000000000003
44 [14942.851970] x5 : 0000000000000020 x4 : 0000000000000004
45 [14942.857575] x3 : 0000000000000002 x2 : 0000000000000001
46 [14942.863180] x1 : 0000000000000048 x0 : 0000000000000000
47 [14942.868875] Process kworker/u4:13 (pid: 26629, stack limit = 0x00000000c909dbf3)
48 [14942.876464] Call trace:
49 [14942.879200] test_and_set_bit+0x18/0x38
50 [14942.883376] phy_link_change+0x38/0x78
51 [14942.887378] phy_state_machine+0x3dc/0x4f8
52 [14942.891968] process_one_work+0x158/0x470
53 [14942.896223] worker_thread+0x50/0x470
54 [14942.900219] kthread+0x104/0x130
55 [14942.903905] ret_from_fork+0x10/0x1c
56 [14942.907755] Code: d2800022 8b400c21 f9800031 9ac32044 (c85f7c22)
57 [14942.914185] ---[ end trace 968c9e12eb740b23 ]---
58
59 So this patch fixes it by modifying the timing to do phy_connect_direct()
60 and phy_disconnect().
61
62 Fixes: 256727da7395 ("net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC")
63 Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
64 Signed-off-by: Peng Li <lipeng321@huawei.com>
65 Signed-off-by: David S. Miller <davem@davemloft.net>
66 Signed-off-by: Sasha Levin <sashal@kernel.org>
67 ---
68 drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 ++
69 .../net/ethernet/hisilicon/hns3/hns3_enet.c | 28 +++++++++++++++++++
70 .../hisilicon/hns3/hns3pf/hclge_main.c | 20 ++-----------
71 .../hisilicon/hns3/hns3pf/hclge_mdio.c | 8 ++++--
72 .../hisilicon/hns3/hns3pf/hclge_mdio.h | 4 +--
73 5 files changed, 40 insertions(+), 22 deletions(-)
74
75 diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
76 index 09c774fe8853..854a55d4332a 100644
77 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
78 +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
79 @@ -463,6 +463,8 @@ struct hnae3_ae_ops {
80 int (*set_gro_en)(struct hnae3_handle *handle, int enable);
81 u16 (*get_global_queue_id)(struct hnae3_handle *handle, u16 queue_id);
82 void (*set_timer_task)(struct hnae3_handle *handle, bool enable);
83 + int (*mac_connect_phy)(struct hnae3_handle *handle);
84 + void (*mac_disconnect_phy)(struct hnae3_handle *handle);
85 };
86
87 struct hnae3_dcb_ops {
88 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
89 index d84c50068f66..40b69eaf2cb3 100644
90 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
91 +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
92 @@ -3519,6 +3519,25 @@ static int hns3_init_mac_addr(struct net_device *netdev, bool init)
93 return ret;
94 }
95
96 +static int hns3_init_phy(struct net_device *netdev)
97 +{
98 + struct hnae3_handle *h = hns3_get_handle(netdev);
99 + int ret = 0;
100 +
101 + if (h->ae_algo->ops->mac_connect_phy)
102 + ret = h->ae_algo->ops->mac_connect_phy(h);
103 +
104 + return ret;
105 +}
106 +
107 +static void hns3_uninit_phy(struct net_device *netdev)
108 +{
109 + struct hnae3_handle *h = hns3_get_handle(netdev);
110 +
111 + if (h->ae_algo->ops->mac_disconnect_phy)
112 + h->ae_algo->ops->mac_disconnect_phy(h);
113 +}
114 +
115 static int hns3_restore_fd_rules(struct net_device *netdev)
116 {
117 struct hnae3_handle *h = hns3_get_handle(netdev);
118 @@ -3627,6 +3646,10 @@ static int hns3_client_init(struct hnae3_handle *handle)
119 goto out_init_ring_data;
120 }
121
122 + ret = hns3_init_phy(netdev);
123 + if (ret)
124 + goto out_init_phy;
125 +
126 ret = register_netdev(netdev);
127 if (ret) {
128 dev_err(priv->dev, "probe register netdev fail!\n");
129 @@ -3651,6 +3674,9 @@ static int hns3_client_init(struct hnae3_handle *handle)
130 return ret;
131
132 out_reg_netdev_fail:
133 + hns3_uninit_phy(netdev);
134 +out_init_phy:
135 + hns3_uninit_all_ring(priv);
136 out_init_ring_data:
137 (void)hns3_nic_uninit_vector_data(priv);
138 out_init_vector_data:
139 @@ -3685,6 +3711,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
140
141 hns3_force_clear_all_rx_ring(handle);
142
143 + hns3_uninit_phy(netdev);
144 +
145 ret = hns3_nic_uninit_vector_data(priv);
146 if (ret)
147 netdev_err(netdev, "uninit vector error\n");
148 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
149 index f7637c08bb3a..cb7571747af7 100644
150 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
151 +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
152 @@ -6959,16 +6959,6 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle,
153 *tp_mdix = ETH_TP_MDI;
154 }
155
156 -static int hclge_init_instance_hw(struct hclge_dev *hdev)
157 -{
158 - return hclge_mac_connect_phy(hdev);
159 -}
160 -
161 -static void hclge_uninit_instance_hw(struct hclge_dev *hdev)
162 -{
163 - hclge_mac_disconnect_phy(hdev);
164 -}
165 -
166 static int hclge_init_client_instance(struct hnae3_client *client,
167 struct hnae3_ae_dev *ae_dev)
168 {
169 @@ -6988,13 +6978,6 @@ static int hclge_init_client_instance(struct hnae3_client *client,
170 if (ret)
171 goto clear_nic;
172
173 - ret = hclge_init_instance_hw(hdev);
174 - if (ret) {
175 - client->ops->uninit_instance(&vport->nic,
176 - 0);
177 - goto clear_nic;
178 - }
179 -
180 hnae3_set_client_init_flag(client, ae_dev, 1);
181
182 if (hdev->roce_client &&
183 @@ -7079,7 +7062,6 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
184 if (client->type == HNAE3_CLIENT_ROCE)
185 return;
186 if (hdev->nic_client && client->ops->uninit_instance) {
187 - hclge_uninit_instance_hw(hdev);
188 client->ops->uninit_instance(&vport->nic, 0);
189 hdev->nic_client = NULL;
190 vport->nic.client = NULL;
191 @@ -8012,6 +7994,8 @@ static const struct hnae3_ae_ops hclge_ops = {
192 .set_gro_en = hclge_gro_en,
193 .get_global_queue_id = hclge_covert_handle_qid_global,
194 .set_timer_task = hclge_set_timer_task,
195 + .mac_connect_phy = hclge_mac_connect_phy,
196 + .mac_disconnect_phy = hclge_mac_disconnect_phy,
197 };
198
199 static struct hnae3_ae_algo ae_algo = {
200 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
201 index dabb8437f8dc..84f28785ba28 100644
202 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
203 +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
204 @@ -195,8 +195,10 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
205 netdev_err(netdev, "failed to configure flow control.\n");
206 }
207
208 -int hclge_mac_connect_phy(struct hclge_dev *hdev)
209 +int hclge_mac_connect_phy(struct hnae3_handle *handle)
210 {
211 + struct hclge_vport *vport = hclge_get_vport(handle);
212 + struct hclge_dev *hdev = vport->back;
213 struct net_device *netdev = hdev->vport[0].nic.netdev;
214 struct phy_device *phydev = hdev->hw.mac.phydev;
215 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
216 @@ -229,8 +231,10 @@ int hclge_mac_connect_phy(struct hclge_dev *hdev)
217 return 0;
218 }
219
220 -void hclge_mac_disconnect_phy(struct hclge_dev *hdev)
221 +void hclge_mac_disconnect_phy(struct hnae3_handle *handle)
222 {
223 + struct hclge_vport *vport = hclge_get_vport(handle);
224 + struct hclge_dev *hdev = vport->back;
225 struct phy_device *phydev = hdev->hw.mac.phydev;
226
227 if (!phydev)
228 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
229 index 5fbf7dddb5d9..ef095d9c566f 100644
230 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
231 +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
232 @@ -5,8 +5,8 @@
233 #define __HCLGE_MDIO_H
234
235 int hclge_mac_mdio_config(struct hclge_dev *hdev);
236 -int hclge_mac_connect_phy(struct hclge_dev *hdev);
237 -void hclge_mac_disconnect_phy(struct hclge_dev *hdev);
238 +int hclge_mac_connect_phy(struct hnae3_handle *handle);
239 +void hclge_mac_disconnect_phy(struct hnae3_handle *handle);
240 void hclge_mac_start_phy(struct hclge_dev *hdev);
241 void hclge_mac_stop_phy(struct hclge_dev *hdev);
242
243 --
244 2.19.1
245