xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1*17fcb3dcSFan Gong // SPDX-License-Identifier: GPL-2.0
2*17fcb3dcSFan Gong // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3*17fcb3dcSFan Gong 
4*17fcb3dcSFan Gong #include <linux/delay.h>
5*17fcb3dcSFan Gong #include <linux/iopoll.h>
6*17fcb3dcSFan Gong 
7*17fcb3dcSFan Gong #include "hinic3_hw_cfg.h"
8*17fcb3dcSFan Gong #include "hinic3_hwdev.h"
9*17fcb3dcSFan Gong #include "hinic3_lld.h"
10*17fcb3dcSFan Gong #include "hinic3_mgmt.h"
11*17fcb3dcSFan Gong 
12*17fcb3dcSFan Gong #define HINIC3_VF_PCI_CFG_REG_BAR  0
13*17fcb3dcSFan Gong #define HINIC3_PCI_INTR_REG_BAR    2
14*17fcb3dcSFan Gong #define HINIC3_PCI_DB_BAR          4
15*17fcb3dcSFan Gong 
16*17fcb3dcSFan Gong #define HINIC3_EVENT_POLL_SLEEP_US   1000
17*17fcb3dcSFan Gong #define HINIC3_EVENT_POLL_TIMEOUT_US 10000000
18*17fcb3dcSFan Gong 
19*17fcb3dcSFan Gong static struct hinic3_adev_device {
20*17fcb3dcSFan Gong 	const char *name;
21*17fcb3dcSFan Gong } hinic3_adev_devices[HINIC3_SERVICE_T_MAX] = {
22*17fcb3dcSFan Gong 	[HINIC3_SERVICE_T_NIC] = {
23*17fcb3dcSFan Gong 		.name = "nic",
24*17fcb3dcSFan Gong 	},
25*17fcb3dcSFan Gong };
26*17fcb3dcSFan Gong 
27*17fcb3dcSFan Gong static bool hinic3_adev_svc_supported(struct hinic3_hwdev *hwdev,
28*17fcb3dcSFan Gong 				      enum hinic3_service_type svc_type)
29*17fcb3dcSFan Gong {
30*17fcb3dcSFan Gong 	switch (svc_type) {
31*17fcb3dcSFan Gong 	case HINIC3_SERVICE_T_NIC:
32*17fcb3dcSFan Gong 		return hinic3_support_nic(hwdev);
33*17fcb3dcSFan Gong 	default:
34*17fcb3dcSFan Gong 		break;
35*17fcb3dcSFan Gong 	}
36*17fcb3dcSFan Gong 
37*17fcb3dcSFan Gong 	return false;
38*17fcb3dcSFan Gong }
39*17fcb3dcSFan Gong 
40*17fcb3dcSFan Gong static void hinic3_comm_adev_release(struct device *dev)
41*17fcb3dcSFan Gong {
42*17fcb3dcSFan Gong 	struct hinic3_adev *hadev = container_of(dev, struct hinic3_adev,
43*17fcb3dcSFan Gong 						 adev.dev);
44*17fcb3dcSFan Gong 
45*17fcb3dcSFan Gong 	kfree(hadev);
46*17fcb3dcSFan Gong }
47*17fcb3dcSFan Gong 
48*17fcb3dcSFan Gong static struct hinic3_adev *hinic3_add_one_adev(struct hinic3_hwdev *hwdev,
49*17fcb3dcSFan Gong 					       enum hinic3_service_type svc_type)
50*17fcb3dcSFan Gong {
51*17fcb3dcSFan Gong 	struct hinic3_adev *hadev;
52*17fcb3dcSFan Gong 	const char *svc_name;
53*17fcb3dcSFan Gong 	int ret;
54*17fcb3dcSFan Gong 
55*17fcb3dcSFan Gong 	hadev = kzalloc(sizeof(*hadev), GFP_KERNEL);
56*17fcb3dcSFan Gong 	if (!hadev)
57*17fcb3dcSFan Gong 		return NULL;
58*17fcb3dcSFan Gong 
59*17fcb3dcSFan Gong 	svc_name = hinic3_adev_devices[svc_type].name;
60*17fcb3dcSFan Gong 	hadev->adev.name = svc_name;
61*17fcb3dcSFan Gong 	hadev->adev.id = hwdev->dev_id;
62*17fcb3dcSFan Gong 	hadev->adev.dev.parent = hwdev->dev;
63*17fcb3dcSFan Gong 	hadev->adev.dev.release = hinic3_comm_adev_release;
64*17fcb3dcSFan Gong 	hadev->svc_type = svc_type;
65*17fcb3dcSFan Gong 	hadev->hwdev = hwdev;
66*17fcb3dcSFan Gong 
67*17fcb3dcSFan Gong 	ret = auxiliary_device_init(&hadev->adev);
68*17fcb3dcSFan Gong 	if (ret) {
69*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "failed init adev %s %u\n",
70*17fcb3dcSFan Gong 			svc_name, hwdev->dev_id);
71*17fcb3dcSFan Gong 		kfree(hadev);
72*17fcb3dcSFan Gong 		return NULL;
73*17fcb3dcSFan Gong 	}
74*17fcb3dcSFan Gong 
75*17fcb3dcSFan Gong 	ret = auxiliary_device_add(&hadev->adev);
76*17fcb3dcSFan Gong 	if (ret) {
77*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "failed to add adev %s %u\n",
78*17fcb3dcSFan Gong 			svc_name, hwdev->dev_id);
79*17fcb3dcSFan Gong 		auxiliary_device_uninit(&hadev->adev);
80*17fcb3dcSFan Gong 		return NULL;
81*17fcb3dcSFan Gong 	}
82*17fcb3dcSFan Gong 
83*17fcb3dcSFan Gong 	return hadev;
84*17fcb3dcSFan Gong }
85*17fcb3dcSFan Gong 
86*17fcb3dcSFan Gong static void hinic3_del_one_adev(struct hinic3_hwdev *hwdev,
87*17fcb3dcSFan Gong 				enum hinic3_service_type svc_type)
88*17fcb3dcSFan Gong {
89*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = hwdev->adapter;
90*17fcb3dcSFan Gong 	struct hinic3_adev *hadev;
91*17fcb3dcSFan Gong 	int timeout;
92*17fcb3dcSFan Gong 	bool state;
93*17fcb3dcSFan Gong 
94*17fcb3dcSFan Gong 	timeout = read_poll_timeout(test_and_set_bit, state, !state,
95*17fcb3dcSFan Gong 				    HINIC3_EVENT_POLL_SLEEP_US,
96*17fcb3dcSFan Gong 				    HINIC3_EVENT_POLL_TIMEOUT_US,
97*17fcb3dcSFan Gong 				    false, svc_type, &pci_adapter->state);
98*17fcb3dcSFan Gong 
99*17fcb3dcSFan Gong 	hadev = pci_adapter->hadev[svc_type];
100*17fcb3dcSFan Gong 	auxiliary_device_delete(&hadev->adev);
101*17fcb3dcSFan Gong 	auxiliary_device_uninit(&hadev->adev);
102*17fcb3dcSFan Gong 	pci_adapter->hadev[svc_type] = NULL;
103*17fcb3dcSFan Gong 	if (!timeout)
104*17fcb3dcSFan Gong 		clear_bit(svc_type, &pci_adapter->state);
105*17fcb3dcSFan Gong }
106*17fcb3dcSFan Gong 
107*17fcb3dcSFan Gong static int hinic3_attach_aux_devices(struct hinic3_hwdev *hwdev)
108*17fcb3dcSFan Gong {
109*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = hwdev->adapter;
110*17fcb3dcSFan Gong 	enum hinic3_service_type svc_type;
111*17fcb3dcSFan Gong 
112*17fcb3dcSFan Gong 	mutex_lock(&pci_adapter->pdev_mutex);
113*17fcb3dcSFan Gong 
114*17fcb3dcSFan Gong 	for (svc_type = 0; svc_type < HINIC3_SERVICE_T_MAX; svc_type++) {
115*17fcb3dcSFan Gong 		if (!hinic3_adev_svc_supported(hwdev, svc_type))
116*17fcb3dcSFan Gong 			continue;
117*17fcb3dcSFan Gong 
118*17fcb3dcSFan Gong 		pci_adapter->hadev[svc_type] = hinic3_add_one_adev(hwdev,
119*17fcb3dcSFan Gong 								   svc_type);
120*17fcb3dcSFan Gong 		if (!pci_adapter->hadev[svc_type])
121*17fcb3dcSFan Gong 			goto err_del_adevs;
122*17fcb3dcSFan Gong 	}
123*17fcb3dcSFan Gong 	mutex_unlock(&pci_adapter->pdev_mutex);
124*17fcb3dcSFan Gong 	return 0;
125*17fcb3dcSFan Gong 
126*17fcb3dcSFan Gong err_del_adevs:
127*17fcb3dcSFan Gong 	while (svc_type > 0) {
128*17fcb3dcSFan Gong 		svc_type--;
129*17fcb3dcSFan Gong 		if (pci_adapter->hadev[svc_type]) {
130*17fcb3dcSFan Gong 			hinic3_del_one_adev(hwdev, svc_type);
131*17fcb3dcSFan Gong 			pci_adapter->hadev[svc_type] = NULL;
132*17fcb3dcSFan Gong 		}
133*17fcb3dcSFan Gong 	}
134*17fcb3dcSFan Gong 	mutex_unlock(&pci_adapter->pdev_mutex);
135*17fcb3dcSFan Gong 	return -ENOMEM;
136*17fcb3dcSFan Gong }
137*17fcb3dcSFan Gong 
138*17fcb3dcSFan Gong static void hinic3_detach_aux_devices(struct hinic3_hwdev *hwdev)
139*17fcb3dcSFan Gong {
140*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = hwdev->adapter;
141*17fcb3dcSFan Gong 	int i;
142*17fcb3dcSFan Gong 
143*17fcb3dcSFan Gong 	mutex_lock(&pci_adapter->pdev_mutex);
144*17fcb3dcSFan Gong 	for (i = 0; i < ARRAY_SIZE(hinic3_adev_devices); i++) {
145*17fcb3dcSFan Gong 		if (pci_adapter->hadev[i])
146*17fcb3dcSFan Gong 			hinic3_del_one_adev(hwdev, i);
147*17fcb3dcSFan Gong 	}
148*17fcb3dcSFan Gong 	mutex_unlock(&pci_adapter->pdev_mutex);
149*17fcb3dcSFan Gong }
150*17fcb3dcSFan Gong 
151*17fcb3dcSFan Gong struct hinic3_hwdev *hinic3_adev_get_hwdev(struct auxiliary_device *adev)
152*17fcb3dcSFan Gong {
153*17fcb3dcSFan Gong 	struct hinic3_adev *hadev;
154*17fcb3dcSFan Gong 
155*17fcb3dcSFan Gong 	hadev = container_of(adev, struct hinic3_adev, adev);
156*17fcb3dcSFan Gong 	return hadev->hwdev;
157*17fcb3dcSFan Gong }
158*17fcb3dcSFan Gong 
159*17fcb3dcSFan Gong void hinic3_adev_event_register(struct auxiliary_device *adev,
160*17fcb3dcSFan Gong 				void (*event_handler)(struct auxiliary_device *adev,
161*17fcb3dcSFan Gong 						      struct hinic3_event_info *event))
162*17fcb3dcSFan Gong {
163*17fcb3dcSFan Gong 	struct hinic3_adev *hadev;
164*17fcb3dcSFan Gong 
165*17fcb3dcSFan Gong 	hadev = container_of(adev, struct hinic3_adev, adev);
166*17fcb3dcSFan Gong 	hadev->event = event_handler;
167*17fcb3dcSFan Gong }
168*17fcb3dcSFan Gong 
169*17fcb3dcSFan Gong void hinic3_adev_event_unregister(struct auxiliary_device *adev)
170*17fcb3dcSFan Gong {
171*17fcb3dcSFan Gong 	struct hinic3_adev *hadev;
172*17fcb3dcSFan Gong 
173*17fcb3dcSFan Gong 	hadev = container_of(adev, struct hinic3_adev, adev);
174*17fcb3dcSFan Gong 	hadev->event = NULL;
175*17fcb3dcSFan Gong }
176*17fcb3dcSFan Gong 
177*17fcb3dcSFan Gong static int hinic3_mapping_bar(struct pci_dev *pdev,
178*17fcb3dcSFan Gong 			      struct hinic3_pcidev *pci_adapter)
179*17fcb3dcSFan Gong {
180*17fcb3dcSFan Gong 	pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev,
181*17fcb3dcSFan Gong 						    HINIC3_VF_PCI_CFG_REG_BAR);
182*17fcb3dcSFan Gong 	if (!pci_adapter->cfg_reg_base) {
183*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to map configuration regs\n");
184*17fcb3dcSFan Gong 		return -ENOMEM;
185*17fcb3dcSFan Gong 	}
186*17fcb3dcSFan Gong 
187*17fcb3dcSFan Gong 	pci_adapter->intr_reg_base = pci_ioremap_bar(pdev,
188*17fcb3dcSFan Gong 						     HINIC3_PCI_INTR_REG_BAR);
189*17fcb3dcSFan Gong 	if (!pci_adapter->intr_reg_base) {
190*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to map interrupt regs\n");
191*17fcb3dcSFan Gong 		goto err_unmap_cfg_reg_base;
192*17fcb3dcSFan Gong 	}
193*17fcb3dcSFan Gong 
194*17fcb3dcSFan Gong 	pci_adapter->db_base_phy = pci_resource_start(pdev, HINIC3_PCI_DB_BAR);
195*17fcb3dcSFan Gong 	pci_adapter->db_dwqe_len = pci_resource_len(pdev, HINIC3_PCI_DB_BAR);
196*17fcb3dcSFan Gong 	pci_adapter->db_base = pci_ioremap_bar(pdev, HINIC3_PCI_DB_BAR);
197*17fcb3dcSFan Gong 	if (!pci_adapter->db_base) {
198*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to map doorbell regs\n");
199*17fcb3dcSFan Gong 		goto err_unmap_intr_reg_base;
200*17fcb3dcSFan Gong 	}
201*17fcb3dcSFan Gong 
202*17fcb3dcSFan Gong 	return 0;
203*17fcb3dcSFan Gong 
204*17fcb3dcSFan Gong err_unmap_intr_reg_base:
205*17fcb3dcSFan Gong 	iounmap(pci_adapter->intr_reg_base);
206*17fcb3dcSFan Gong 
207*17fcb3dcSFan Gong err_unmap_cfg_reg_base:
208*17fcb3dcSFan Gong 	iounmap(pci_adapter->cfg_reg_base);
209*17fcb3dcSFan Gong 
210*17fcb3dcSFan Gong 	return -ENOMEM;
211*17fcb3dcSFan Gong }
212*17fcb3dcSFan Gong 
213*17fcb3dcSFan Gong static void hinic3_unmapping_bar(struct hinic3_pcidev *pci_adapter)
214*17fcb3dcSFan Gong {
215*17fcb3dcSFan Gong 	iounmap(pci_adapter->db_base);
216*17fcb3dcSFan Gong 	iounmap(pci_adapter->intr_reg_base);
217*17fcb3dcSFan Gong 	iounmap(pci_adapter->cfg_reg_base);
218*17fcb3dcSFan Gong }
219*17fcb3dcSFan Gong 
220*17fcb3dcSFan Gong static int hinic3_pci_init(struct pci_dev *pdev)
221*17fcb3dcSFan Gong {
222*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter;
223*17fcb3dcSFan Gong 	int err;
224*17fcb3dcSFan Gong 
225*17fcb3dcSFan Gong 	pci_adapter = kzalloc(sizeof(*pci_adapter), GFP_KERNEL);
226*17fcb3dcSFan Gong 	if (!pci_adapter)
227*17fcb3dcSFan Gong 		return -ENOMEM;
228*17fcb3dcSFan Gong 
229*17fcb3dcSFan Gong 	pci_adapter->pdev = pdev;
230*17fcb3dcSFan Gong 	mutex_init(&pci_adapter->pdev_mutex);
231*17fcb3dcSFan Gong 
232*17fcb3dcSFan Gong 	pci_set_drvdata(pdev, pci_adapter);
233*17fcb3dcSFan Gong 
234*17fcb3dcSFan Gong 	err = pci_enable_device(pdev);
235*17fcb3dcSFan Gong 	if (err) {
236*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to enable PCI device\n");
237*17fcb3dcSFan Gong 		goto err_free_pci_adapter;
238*17fcb3dcSFan Gong 	}
239*17fcb3dcSFan Gong 
240*17fcb3dcSFan Gong 	err = pci_request_regions(pdev, HINIC3_NIC_DRV_NAME);
241*17fcb3dcSFan Gong 	if (err) {
242*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to request regions\n");
243*17fcb3dcSFan Gong 		goto err_disable_device;
244*17fcb3dcSFan Gong 	}
245*17fcb3dcSFan Gong 
246*17fcb3dcSFan Gong 	pci_set_master(pdev);
247*17fcb3dcSFan Gong 
248*17fcb3dcSFan Gong 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
249*17fcb3dcSFan Gong 	if (err) {
250*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to set DMA mask\n");
251*17fcb3dcSFan Gong 		goto err_release_regions;
252*17fcb3dcSFan Gong 	}
253*17fcb3dcSFan Gong 
254*17fcb3dcSFan Gong 	return 0;
255*17fcb3dcSFan Gong 
256*17fcb3dcSFan Gong err_release_regions:
257*17fcb3dcSFan Gong 	pci_clear_master(pdev);
258*17fcb3dcSFan Gong 	pci_release_regions(pdev);
259*17fcb3dcSFan Gong 
260*17fcb3dcSFan Gong err_disable_device:
261*17fcb3dcSFan Gong 	pci_disable_device(pdev);
262*17fcb3dcSFan Gong 
263*17fcb3dcSFan Gong err_free_pci_adapter:
264*17fcb3dcSFan Gong 	pci_set_drvdata(pdev, NULL);
265*17fcb3dcSFan Gong 	mutex_destroy(&pci_adapter->pdev_mutex);
266*17fcb3dcSFan Gong 	kfree(pci_adapter);
267*17fcb3dcSFan Gong 
268*17fcb3dcSFan Gong 	return err;
269*17fcb3dcSFan Gong }
270*17fcb3dcSFan Gong 
271*17fcb3dcSFan Gong static void hinic3_pci_uninit(struct pci_dev *pdev)
272*17fcb3dcSFan Gong {
273*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
274*17fcb3dcSFan Gong 
275*17fcb3dcSFan Gong 	pci_clear_master(pdev);
276*17fcb3dcSFan Gong 	pci_release_regions(pdev);
277*17fcb3dcSFan Gong 	pci_disable_device(pdev);
278*17fcb3dcSFan Gong 	pci_set_drvdata(pdev, NULL);
279*17fcb3dcSFan Gong 	mutex_destroy(&pci_adapter->pdev_mutex);
280*17fcb3dcSFan Gong 	kfree(pci_adapter);
281*17fcb3dcSFan Gong }
282*17fcb3dcSFan Gong 
283*17fcb3dcSFan Gong static int hinic3_func_init(struct pci_dev *pdev,
284*17fcb3dcSFan Gong 			    struct hinic3_pcidev *pci_adapter)
285*17fcb3dcSFan Gong {
286*17fcb3dcSFan Gong 	int err;
287*17fcb3dcSFan Gong 
288*17fcb3dcSFan Gong 	err = hinic3_init_hwdev(pdev);
289*17fcb3dcSFan Gong 	if (err) {
290*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to initialize hardware device\n");
291*17fcb3dcSFan Gong 		return err;
292*17fcb3dcSFan Gong 	}
293*17fcb3dcSFan Gong 
294*17fcb3dcSFan Gong 	err = hinic3_attach_aux_devices(pci_adapter->hwdev);
295*17fcb3dcSFan Gong 	if (err)
296*17fcb3dcSFan Gong 		goto err_free_hwdev;
297*17fcb3dcSFan Gong 
298*17fcb3dcSFan Gong 	return 0;
299*17fcb3dcSFan Gong 
300*17fcb3dcSFan Gong err_free_hwdev:
301*17fcb3dcSFan Gong 	hinic3_free_hwdev(pci_adapter->hwdev);
302*17fcb3dcSFan Gong 
303*17fcb3dcSFan Gong 	return err;
304*17fcb3dcSFan Gong }
305*17fcb3dcSFan Gong 
306*17fcb3dcSFan Gong static void hinic3_func_uninit(struct pci_dev *pdev)
307*17fcb3dcSFan Gong {
308*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
309*17fcb3dcSFan Gong 
310*17fcb3dcSFan Gong 	hinic3_detach_aux_devices(pci_adapter->hwdev);
311*17fcb3dcSFan Gong 	hinic3_free_hwdev(pci_adapter->hwdev);
312*17fcb3dcSFan Gong }
313*17fcb3dcSFan Gong 
314*17fcb3dcSFan Gong static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
315*17fcb3dcSFan Gong {
316*17fcb3dcSFan Gong 	struct pci_dev *pdev = pci_adapter->pdev;
317*17fcb3dcSFan Gong 	int err;
318*17fcb3dcSFan Gong 
319*17fcb3dcSFan Gong 	err = hinic3_mapping_bar(pdev, pci_adapter);
320*17fcb3dcSFan Gong 	if (err) {
321*17fcb3dcSFan Gong 		dev_err(&pdev->dev, "Failed to map bar\n");
322*17fcb3dcSFan Gong 		goto err_out;
323*17fcb3dcSFan Gong 	}
324*17fcb3dcSFan Gong 
325*17fcb3dcSFan Gong 	err = hinic3_func_init(pdev, pci_adapter);
326*17fcb3dcSFan Gong 	if (err)
327*17fcb3dcSFan Gong 		goto err_unmap_bar;
328*17fcb3dcSFan Gong 
329*17fcb3dcSFan Gong 	return 0;
330*17fcb3dcSFan Gong 
331*17fcb3dcSFan Gong err_unmap_bar:
332*17fcb3dcSFan Gong 	hinic3_unmapping_bar(pci_adapter);
333*17fcb3dcSFan Gong 
334*17fcb3dcSFan Gong err_out:
335*17fcb3dcSFan Gong 	dev_err(&pdev->dev, "PCIe device probe function failed\n");
336*17fcb3dcSFan Gong 	return err;
337*17fcb3dcSFan Gong }
338*17fcb3dcSFan Gong 
339*17fcb3dcSFan Gong static void hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
340*17fcb3dcSFan Gong {
341*17fcb3dcSFan Gong 	struct pci_dev *pdev = pci_adapter->pdev;
342*17fcb3dcSFan Gong 
343*17fcb3dcSFan Gong 	hinic3_func_uninit(pdev);
344*17fcb3dcSFan Gong 	hinic3_unmapping_bar(pci_adapter);
345*17fcb3dcSFan Gong }
346*17fcb3dcSFan Gong 
347*17fcb3dcSFan Gong static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
348*17fcb3dcSFan Gong {
349*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter;
350*17fcb3dcSFan Gong 	int err;
351*17fcb3dcSFan Gong 
352*17fcb3dcSFan Gong 	err = hinic3_pci_init(pdev);
353*17fcb3dcSFan Gong 	if (err)
354*17fcb3dcSFan Gong 		goto err_out;
355*17fcb3dcSFan Gong 
356*17fcb3dcSFan Gong 	pci_adapter = pci_get_drvdata(pdev);
357*17fcb3dcSFan Gong 	err = hinic3_probe_func(pci_adapter);
358*17fcb3dcSFan Gong 	if (err)
359*17fcb3dcSFan Gong 		goto err_uninit_pci;
360*17fcb3dcSFan Gong 
361*17fcb3dcSFan Gong 	return 0;
362*17fcb3dcSFan Gong 
363*17fcb3dcSFan Gong err_uninit_pci:
364*17fcb3dcSFan Gong 	hinic3_pci_uninit(pdev);
365*17fcb3dcSFan Gong 
366*17fcb3dcSFan Gong err_out:
367*17fcb3dcSFan Gong 	dev_err(&pdev->dev, "PCIe device probe failed\n");
368*17fcb3dcSFan Gong 	return err;
369*17fcb3dcSFan Gong }
370*17fcb3dcSFan Gong 
371*17fcb3dcSFan Gong static void hinic3_remove(struct pci_dev *pdev)
372*17fcb3dcSFan Gong {
373*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
374*17fcb3dcSFan Gong 
375*17fcb3dcSFan Gong 	hinic3_remove_func(pci_adapter);
376*17fcb3dcSFan Gong 	hinic3_pci_uninit(pdev);
377*17fcb3dcSFan Gong }
378*17fcb3dcSFan Gong 
379*17fcb3dcSFan Gong static const struct pci_device_id hinic3_pci_table[] = {
380*17fcb3dcSFan Gong 	/* Completed by later submission due to LoC limit. */
381*17fcb3dcSFan Gong 	{0, 0}
382*17fcb3dcSFan Gong 
383*17fcb3dcSFan Gong };
384*17fcb3dcSFan Gong 
385*17fcb3dcSFan Gong MODULE_DEVICE_TABLE(pci, hinic3_pci_table);
386*17fcb3dcSFan Gong 
387*17fcb3dcSFan Gong static void hinic3_shutdown(struct pci_dev *pdev)
388*17fcb3dcSFan Gong {
389*17fcb3dcSFan Gong 	struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
390*17fcb3dcSFan Gong 
391*17fcb3dcSFan Gong 	pci_disable_device(pdev);
392*17fcb3dcSFan Gong 
393*17fcb3dcSFan Gong 	if (pci_adapter)
394*17fcb3dcSFan Gong 		hinic3_set_api_stop(pci_adapter->hwdev);
395*17fcb3dcSFan Gong }
396*17fcb3dcSFan Gong 
397*17fcb3dcSFan Gong static struct pci_driver hinic3_driver = {
398*17fcb3dcSFan Gong 	.name            = HINIC3_NIC_DRV_NAME,
399*17fcb3dcSFan Gong 	.id_table        = hinic3_pci_table,
400*17fcb3dcSFan Gong 	.probe           = hinic3_probe,
401*17fcb3dcSFan Gong 	.remove          = hinic3_remove,
402*17fcb3dcSFan Gong 	.shutdown        = hinic3_shutdown,
403*17fcb3dcSFan Gong 	.sriov_configure = pci_sriov_configure_simple
404*17fcb3dcSFan Gong };
405*17fcb3dcSFan Gong 
406*17fcb3dcSFan Gong int hinic3_lld_init(void)
407*17fcb3dcSFan Gong {
408*17fcb3dcSFan Gong 	return pci_register_driver(&hinic3_driver);
409*17fcb3dcSFan Gong }
410*17fcb3dcSFan Gong 
411*17fcb3dcSFan Gong void hinic3_lld_exit(void)
412*17fcb3dcSFan Gong {
413*17fcb3dcSFan Gong 	pci_unregister_driver(&hinic3_driver);
414*17fcb3dcSFan Gong }
415