net/ngbe: initialize and validate EEPROM
[dpdk.git] / drivers / net / ngbe / ngbe_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include <errno.h>
7 #include <rte_common.h>
8 #include <ethdev_pci.h>
9
10 #include "ngbe_logs.h"
11 #include "ngbe.h"
12 #include "ngbe_ethdev.h"
13
14 static int ngbe_dev_close(struct rte_eth_dev *dev);
15
16 /*
17  * The set of PCI devices this driver supports
18  */
19 static const struct rte_pci_id pci_id_ngbe_map[] = {
20         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2) },
21         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2S) },
22         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4) },
23         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4S) },
24         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2) },
25         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S) },
26         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4) },
27         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S) },
28         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860NCSI) },
29         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1) },
30         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1L) },
31         { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W) },
32         { .vendor_id = 0, /* sentinel */ },
33 };
34
35 /*
36  * Ensure that all locks are released before first NVM or PHY access
37  */
38 static void
39 ngbe_swfw_lock_reset(struct ngbe_hw *hw)
40 {
41         uint16_t mask;
42
43         /*
44          * These ones are more tricky since they are common to all ports; but
45          * swfw_sync retries last long enough (1s) to be almost sure that if
46          * lock can not be taken it is due to an improper lock of the
47          * semaphore.
48          */
49         mask = NGBE_MNGSEM_SWPHY |
50                NGBE_MNGSEM_SWMBX |
51                NGBE_MNGSEM_SWFLASH;
52         if (hw->mac.acquire_swfw_sync(hw, mask) < 0)
53                 PMD_DRV_LOG(DEBUG, "SWFW common locks released");
54
55         hw->mac.release_swfw_sync(hw, mask);
56 }
57
58 static int
59 eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
60 {
61         struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
62         struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
63         int err;
64
65         PMD_INIT_FUNC_TRACE();
66
67         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
68                 return 0;
69
70         rte_eth_copy_pci_info(eth_dev, pci_dev);
71
72         /* Vendor and Device ID need to be set before init of shared code */
73         hw->device_id = pci_dev->id.device_id;
74         hw->vendor_id = pci_dev->id.vendor_id;
75         hw->sub_system_id = pci_dev->id.subsystem_device_id;
76         ngbe_map_device_id(hw);
77         hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
78
79         /* Initialize the shared code (base driver) */
80         err = ngbe_init_shared_code(hw);
81         if (err != 0) {
82                 PMD_INIT_LOG(ERR, "Shared code init failed: %d", err);
83                 return -EIO;
84         }
85
86         /* Unlock any pending hardware semaphore */
87         ngbe_swfw_lock_reset(hw);
88
89         err = hw->rom.init_params(hw);
90         if (err != 0) {
91                 PMD_INIT_LOG(ERR, "The EEPROM init failed: %d", err);
92                 return -EIO;
93         }
94
95         /* Make sure we have a good EEPROM before we read from it */
96         err = hw->rom.validate_checksum(hw, NULL);
97         if (err != 0) {
98                 PMD_INIT_LOG(ERR, "The EEPROM checksum is not valid: %d", err);
99                 return -EIO;
100         }
101
102         return 0;
103 }
104
105 static int
106 eth_ngbe_dev_uninit(struct rte_eth_dev *eth_dev)
107 {
108         PMD_INIT_FUNC_TRACE();
109
110         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
111                 return 0;
112
113         ngbe_dev_close(eth_dev);
114
115         return -EINVAL;
116 }
117
118 static int
119 eth_ngbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
120                 struct rte_pci_device *pci_dev)
121 {
122         return rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
123                         sizeof(struct ngbe_adapter),
124                         eth_dev_pci_specific_init, pci_dev,
125                         eth_ngbe_dev_init, NULL);
126 }
127
128 static int eth_ngbe_pci_remove(struct rte_pci_device *pci_dev)
129 {
130         struct rte_eth_dev *ethdev;
131
132         ethdev = rte_eth_dev_allocated(pci_dev->device.name);
133         if (ethdev == NULL)
134                 return 0;
135
136         return rte_eth_dev_destroy(ethdev, eth_ngbe_dev_uninit);
137 }
138
139 static struct rte_pci_driver rte_ngbe_pmd = {
140         .id_table = pci_id_ngbe_map,
141         .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
142         .probe = eth_ngbe_pci_probe,
143         .remove = eth_ngbe_pci_remove,
144 };
145
146 /*
147  * Reset and stop device.
148  */
149 static int
150 ngbe_dev_close(struct rte_eth_dev *dev)
151 {
152         PMD_INIT_FUNC_TRACE();
153
154         RTE_SET_USED(dev);
155
156         return -EINVAL;
157 }
158
159 RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd);
160 RTE_PMD_REGISTER_PCI_TABLE(net_ngbe, pci_id_ngbe_map);
161 RTE_PMD_REGISTER_KMOD_DEP(net_ngbe, "* igb_uio | uio_pci_generic | vfio-pci");
162
163 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_init, init, NOTICE);
164 RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_driver, driver, NOTICE);
165
166 #ifdef RTE_ETHDEV_DEBUG_RX
167         RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_rx, rx, DEBUG);
168 #endif
169 #ifdef RTE_ETHDEV_DEBUG_TX
170         RTE_LOG_REGISTER_SUFFIX(ngbe_logtype_tx, tx, DEBUG);
171 #endif