11f4d4ed6SAlexander Lobakin // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2fe56b9e6SYuval Mintz /* QLogic qed NIC Driver
3e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation
4663eacd8SAlexander Lobakin * Copyright (c) 2019-2020 Marvell International Ltd.
5fe56b9e6SYuval Mintz */
6fe56b9e6SYuval Mintz
7fe56b9e6SYuval Mintz #include <linux/stddef.h>
8fe56b9e6SYuval Mintz #include <linux/pci.h>
9fe56b9e6SYuval Mintz #include <linux/kernel.h>
10fe56b9e6SYuval Mintz #include <linux/slab.h>
11fe56b9e6SYuval Mintz #include <linux/delay.h>
12fe56b9e6SYuval Mintz #include <asm/byteorder.h>
13fe56b9e6SYuval Mintz #include <linux/dma-mapping.h>
14fe56b9e6SYuval Mintz #include <linux/string.h>
15fe56b9e6SYuval Mintz #include <linux/module.h>
16fe56b9e6SYuval Mintz #include <linux/interrupt.h>
17fe56b9e6SYuval Mintz #include <linux/workqueue.h>
18fe56b9e6SYuval Mintz #include <linux/ethtool.h>
19fe56b9e6SYuval Mintz #include <linux/etherdevice.h>
20fe56b9e6SYuval Mintz #include <linux/vmalloc.h>
215d24bcf1STomer Tayar #include <linux/crash_dump.h>
223a69cae8SSudarsana Reddy Kalluru #include <linux/crc32.h>
23fe56b9e6SYuval Mintz #include <linux/qed/qed_if.h>
240a7fb11cSYuval Mintz #include <linux/qed/qed_ll2_if.h>
2524e04879SMichal Kalderon #include <net/devlink.h>
26bdb5d8ecSAlexander Lobakin #include <linux/phylink.h>
27fe56b9e6SYuval Mintz
28fe56b9e6SYuval Mintz #include "qed.h"
2937bff2b9SYuval Mintz #include "qed_sriov.h"
30fe56b9e6SYuval Mintz #include "qed_sp.h"
31fe56b9e6SYuval Mintz #include "qed_dev_api.h"
320a7fb11cSYuval Mintz #include "qed_ll2.h"
331e128c81SArun Easi #include "qed_fcoe.h"
342f2b2614SMintz, Yuval #include "qed_iscsi.h"
352f2b2614SMintz, Yuval
36fe56b9e6SYuval Mintz #include "qed_mcp.h"
37c56a8be7SRahul Verma #include "qed_reg_addr.h"
38fe56b9e6SYuval Mintz #include "qed_hw.h"
3903dc76caSSudarsana Reddy Kalluru #include "qed_selftest.h"
401e128c81SArun Easi #include "qed_debug.h"
4152306deeSIgor Russkikh #include "qed_devlink.h"
42fe56b9e6SYuval Mintz
4351ff1725SRam Amrani #define QED_ROCE_QPS (8192)
4451ff1725SRam Amrani #define QED_ROCE_DPIS (8)
4539dbc646SYuval Bason #define QED_RDMA_SRQS QED_ROCE_QPS
462d4c8495SSudarsana Reddy Kalluru #define QED_NVM_CFG_GET_FLAGS 0xA
472d4c8495SSudarsana Reddy Kalluru #define QED_NVM_CFG_GET_PF_FLAGS 0x1A
48c63b0968SSudarsana Reddy Kalluru #define QED_NVM_CFG_MAX_ATTRS 50
4951ff1725SRam Amrani
505abd7e92SYuval Mintz static char version[] =
517a3febedSShai Malin "QLogic FastLinQ 4xxxx Core Module qed\n";
52fe56b9e6SYuval Mintz
535abd7e92SYuval Mintz MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx Core Module");
54fe56b9e6SYuval Mintz MODULE_LICENSE("GPL");
55fe56b9e6SYuval Mintz
56fe56b9e6SYuval Mintz #define FW_FILE_VERSION \
57fe56b9e6SYuval Mintz __stringify(FW_MAJOR_VERSION) "." \
58fe56b9e6SYuval Mintz __stringify(FW_MINOR_VERSION) "." \
59fe56b9e6SYuval Mintz __stringify(FW_REVISION_VERSION) "." \
60fe56b9e6SYuval Mintz __stringify(FW_ENGINEERING_VERSION)
61fe56b9e6SYuval Mintz
62fe56b9e6SYuval Mintz #define QED_FW_FILE_NAME \
63fe56b9e6SYuval Mintz "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin"
64fe56b9e6SYuval Mintz
65d43d3f0fSYuval Mintz MODULE_FIRMWARE(QED_FW_FILE_NAME);
66d43d3f0fSYuval Mintz
67097818fcSAlexander Lobakin /* MFW speed capabilities maps */
68097818fcSAlexander Lobakin
69097818fcSAlexander Lobakin struct qed_mfw_speed_map {
70097818fcSAlexander Lobakin u32 mfw_val;
71097818fcSAlexander Lobakin __ETHTOOL_DECLARE_LINK_MODE_MASK(caps);
72097818fcSAlexander Lobakin
73097818fcSAlexander Lobakin const u32 *cap_arr;
74097818fcSAlexander Lobakin u32 arr_size;
75097818fcSAlexander Lobakin };
76097818fcSAlexander Lobakin
77097818fcSAlexander Lobakin #define QED_MFW_SPEED_MAP(type, arr) \
78097818fcSAlexander Lobakin { \
79097818fcSAlexander Lobakin .mfw_val = (type), \
80097818fcSAlexander Lobakin .cap_arr = (arr), \
81097818fcSAlexander Lobakin .arr_size = ARRAY_SIZE(arr), \
82097818fcSAlexander Lobakin }
83097818fcSAlexander Lobakin
8499785a87SAlexander Lobakin static const u32 qed_mfw_ext_1g[] __initconst = {
8599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
8699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
8799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
8899785a87SAlexander Lobakin };
8999785a87SAlexander Lobakin
9099785a87SAlexander Lobakin static const u32 qed_mfw_ext_10g[] __initconst = {
9199785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
9299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
9399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
9499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
9599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
9699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
9799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
9899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
9999785a87SAlexander Lobakin };
10099785a87SAlexander Lobakin
10199785a87SAlexander Lobakin static const u32 qed_mfw_ext_25g[] __initconst = {
10299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
10399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
10499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
10599785a87SAlexander Lobakin };
10699785a87SAlexander Lobakin
10799785a87SAlexander Lobakin static const u32 qed_mfw_ext_40g[] __initconst = {
10899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
10999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
11099785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
11199785a87SAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
11299785a87SAlexander Lobakin };
11399785a87SAlexander Lobakin
11499785a87SAlexander Lobakin static const u32 qed_mfw_ext_50g_base_r[] __initconst = {
11599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
11699785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
11799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
11899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
11999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
12099785a87SAlexander Lobakin };
12199785a87SAlexander Lobakin
12299785a87SAlexander Lobakin static const u32 qed_mfw_ext_50g_base_r2[] __initconst = {
12399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
12499785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
12599785a87SAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
12699785a87SAlexander Lobakin };
12799785a87SAlexander Lobakin
12899785a87SAlexander Lobakin static const u32 qed_mfw_ext_100g_base_r2[] __initconst = {
12999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
13099785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
13199785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
13299785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
13399785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
13499785a87SAlexander Lobakin };
13599785a87SAlexander Lobakin
13699785a87SAlexander Lobakin static const u32 qed_mfw_ext_100g_base_r4[] __initconst = {
13799785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
13899785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
13999785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
14099785a87SAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
14199785a87SAlexander Lobakin };
14299785a87SAlexander Lobakin
14399785a87SAlexander Lobakin static struct qed_mfw_speed_map qed_mfw_ext_maps[] __ro_after_init = {
14499785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_1G, qed_mfw_ext_1g),
14599785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_10G, qed_mfw_ext_10g),
14699785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_25G, qed_mfw_ext_25g),
14799785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_40G, qed_mfw_ext_40g),
14899785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R,
14999785a87SAlexander Lobakin qed_mfw_ext_50g_base_r),
15099785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R2,
15199785a87SAlexander Lobakin qed_mfw_ext_50g_base_r2),
15299785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R2,
15399785a87SAlexander Lobakin qed_mfw_ext_100g_base_r2),
15499785a87SAlexander Lobakin QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R4,
15599785a87SAlexander Lobakin qed_mfw_ext_100g_base_r4),
15699785a87SAlexander Lobakin };
15799785a87SAlexander Lobakin
158097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_1g[] __initconst = {
159097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
160097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
161097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
162097818fcSAlexander Lobakin };
163097818fcSAlexander Lobakin
164097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_10g[] __initconst = {
165097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
166097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
167097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
168097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
169097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
170097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
171097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
172097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
173097818fcSAlexander Lobakin };
174097818fcSAlexander Lobakin
175097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_20g[] __initconst = {
176097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
177097818fcSAlexander Lobakin };
178097818fcSAlexander Lobakin
179097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_25g[] __initconst = {
180097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
181097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
182097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
183097818fcSAlexander Lobakin };
184097818fcSAlexander Lobakin
185097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_40g[] __initconst = {
186097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
187097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
188097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
189097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
190097818fcSAlexander Lobakin };
191097818fcSAlexander Lobakin
192097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_50g[] __initconst = {
193097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
194097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
195097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
196097818fcSAlexander Lobakin };
197097818fcSAlexander Lobakin
198097818fcSAlexander Lobakin static const u32 qed_mfw_legacy_bb_100g[] __initconst = {
199097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
200097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
201097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
202097818fcSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
203097818fcSAlexander Lobakin };
204097818fcSAlexander Lobakin
205097818fcSAlexander Lobakin static struct qed_mfw_speed_map qed_mfw_legacy_maps[] __ro_after_init = {
206097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G,
207097818fcSAlexander Lobakin qed_mfw_legacy_1g),
208097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G,
209097818fcSAlexander Lobakin qed_mfw_legacy_10g),
210097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G,
211097818fcSAlexander Lobakin qed_mfw_legacy_20g),
212097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G,
213097818fcSAlexander Lobakin qed_mfw_legacy_25g),
214097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G,
215097818fcSAlexander Lobakin qed_mfw_legacy_40g),
216097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G,
217097818fcSAlexander Lobakin qed_mfw_legacy_50g),
218097818fcSAlexander Lobakin QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G,
219097818fcSAlexander Lobakin qed_mfw_legacy_bb_100g),
220097818fcSAlexander Lobakin };
221097818fcSAlexander Lobakin
qed_mfw_speed_map_populate(struct qed_mfw_speed_map * map)222097818fcSAlexander Lobakin static void __init qed_mfw_speed_map_populate(struct qed_mfw_speed_map *map)
223097818fcSAlexander Lobakin {
224097818fcSAlexander Lobakin linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps);
225097818fcSAlexander Lobakin
226097818fcSAlexander Lobakin map->cap_arr = NULL;
227097818fcSAlexander Lobakin map->arr_size = 0;
228097818fcSAlexander Lobakin }
229097818fcSAlexander Lobakin
qed_mfw_speed_maps_init(void)230097818fcSAlexander Lobakin static void __init qed_mfw_speed_maps_init(void)
231097818fcSAlexander Lobakin {
232097818fcSAlexander Lobakin u32 i;
233097818fcSAlexander Lobakin
23499785a87SAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++)
23599785a87SAlexander Lobakin qed_mfw_speed_map_populate(qed_mfw_ext_maps + i);
23699785a87SAlexander Lobakin
237097818fcSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++)
238097818fcSAlexander Lobakin qed_mfw_speed_map_populate(qed_mfw_legacy_maps + i);
239097818fcSAlexander Lobakin }
240097818fcSAlexander Lobakin
qed_init(void)241fe56b9e6SYuval Mintz static int __init qed_init(void)
242fe56b9e6SYuval Mintz {
243fe56b9e6SYuval Mintz pr_info("%s", version);
244fe56b9e6SYuval Mintz
245097818fcSAlexander Lobakin qed_mfw_speed_maps_init();
246097818fcSAlexander Lobakin
247fe56b9e6SYuval Mintz return 0;
248fe56b9e6SYuval Mintz }
249fe56b9e6SYuval Mintz module_init(qed_init);
250097818fcSAlexander Lobakin
qed_exit(void)251097818fcSAlexander Lobakin static void __exit qed_exit(void)
252097818fcSAlexander Lobakin {
253097818fcSAlexander Lobakin /* To prevent marking this module as "permanent" */
254097818fcSAlexander Lobakin }
255097818fcSAlexander Lobakin module_exit(qed_exit);
256fe56b9e6SYuval Mintz
qed_free_pci(struct qed_dev * cdev)257fe56b9e6SYuval Mintz static void qed_free_pci(struct qed_dev *cdev)
258fe56b9e6SYuval Mintz {
259fe56b9e6SYuval Mintz struct pci_dev *pdev = cdev->pdev;
260fe56b9e6SYuval Mintz
2611a850bfcSMintz, Yuval if (cdev->doorbells && cdev->db_size)
262fe56b9e6SYuval Mintz iounmap(cdev->doorbells);
263fe56b9e6SYuval Mintz if (cdev->regview)
264fe56b9e6SYuval Mintz iounmap(cdev->regview);
265fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1)
266fe56b9e6SYuval Mintz pci_release_regions(pdev);
267fe56b9e6SYuval Mintz
268fe56b9e6SYuval Mintz pci_disable_device(pdev);
269fe56b9e6SYuval Mintz }
270fe56b9e6SYuval Mintz
2710dfaba6dSYuval Mintz #define PCI_REVISION_ID_ERROR_VAL 0xff
2720dfaba6dSYuval Mintz
273fe56b9e6SYuval Mintz /* Performs PCI initializations as well as initializing PCI-related parameters
274fe56b9e6SYuval Mintz * in the device structrue. Returns 0 in case of success.
275fe56b9e6SYuval Mintz */
qed_init_pci(struct qed_dev * cdev,struct pci_dev * pdev)2761a635e48SYuval Mintz static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev)
277fe56b9e6SYuval Mintz {
2780dfaba6dSYuval Mintz u8 rev_id;
279fe56b9e6SYuval Mintz int rc;
280fe56b9e6SYuval Mintz
281fe56b9e6SYuval Mintz cdev->pdev = pdev;
282fe56b9e6SYuval Mintz
283fe56b9e6SYuval Mintz rc = pci_enable_device(pdev);
284fe56b9e6SYuval Mintz if (rc) {
285fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot enable PCI device\n");
286fe56b9e6SYuval Mintz goto err0;
287fe56b9e6SYuval Mintz }
288fe56b9e6SYuval Mintz
289fe56b9e6SYuval Mintz if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
290fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #0\n");
291fe56b9e6SYuval Mintz rc = -EIO;
292fe56b9e6SYuval Mintz goto err1;
293fe56b9e6SYuval Mintz }
294fe56b9e6SYuval Mintz
2951408cc1fSYuval Mintz if (IS_PF(cdev) && !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
296fe56b9e6SYuval Mintz DP_NOTICE(cdev, "No memory region found in bar #2\n");
297fe56b9e6SYuval Mintz rc = -EIO;
298fe56b9e6SYuval Mintz goto err1;
299fe56b9e6SYuval Mintz }
300fe56b9e6SYuval Mintz
301fe56b9e6SYuval Mintz if (atomic_read(&pdev->enable_cnt) == 1) {
302fe56b9e6SYuval Mintz rc = pci_request_regions(pdev, "qed");
303fe56b9e6SYuval Mintz if (rc) {
304fe56b9e6SYuval Mintz DP_NOTICE(cdev,
305fe56b9e6SYuval Mintz "Failed to request PCI memory resources\n");
306fe56b9e6SYuval Mintz goto err1;
307fe56b9e6SYuval Mintz }
308fe56b9e6SYuval Mintz pci_set_master(pdev);
309fe56b9e6SYuval Mintz pci_save_state(pdev);
310fe56b9e6SYuval Mintz }
311fe56b9e6SYuval Mintz
3120dfaba6dSYuval Mintz pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
3130dfaba6dSYuval Mintz if (rev_id == PCI_REVISION_ID_ERROR_VAL) {
3140dfaba6dSYuval Mintz DP_NOTICE(cdev,
3150dfaba6dSYuval Mintz "Detected PCI device error [rev_id 0x%x]. Probably due to prior indication. Aborting.\n",
3160dfaba6dSYuval Mintz rev_id);
3170dfaba6dSYuval Mintz rc = -ENODEV;
3180dfaba6dSYuval Mintz goto err2;
3190dfaba6dSYuval Mintz }
320fe56b9e6SYuval Mintz if (!pci_is_pcie(pdev)) {
321fe56b9e6SYuval Mintz DP_NOTICE(cdev, "The bus is not PCI Express\n");
322fe56b9e6SYuval Mintz rc = -EIO;
323fe56b9e6SYuval Mintz goto err2;
324fe56b9e6SYuval Mintz }
325fe56b9e6SYuval Mintz
326fe56b9e6SYuval Mintz cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
327416cdf06SYuval Mintz if (IS_PF(cdev) && !cdev->pci_params.pm_cap)
328fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot find power management capability\n");
329fe56b9e6SYuval Mintz
3304f9f531eSChristophe JAILLET rc = dma_set_mask_and_coherent(&cdev->pdev->dev, DMA_BIT_MASK(64));
3314f9f531eSChristophe JAILLET if (rc) {
3324f9f531eSChristophe JAILLET DP_NOTICE(cdev, "Can't request DMA addresses\n");
3334f9f531eSChristophe JAILLET rc = -EIO;
334fe56b9e6SYuval Mintz goto err2;
3354f9f531eSChristophe JAILLET }
336fe56b9e6SYuval Mintz
337fe56b9e6SYuval Mintz cdev->pci_params.mem_start = pci_resource_start(pdev, 0);
338fe56b9e6SYuval Mintz cdev->pci_params.mem_end = pci_resource_end(pdev, 0);
339fe56b9e6SYuval Mintz cdev->pci_params.irq = pdev->irq;
340fe56b9e6SYuval Mintz
341fe56b9e6SYuval Mintz cdev->regview = pci_ioremap_bar(pdev, 0);
342fe56b9e6SYuval Mintz if (!cdev->regview) {
343fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map register space, aborting\n");
344fe56b9e6SYuval Mintz rc = -ENOMEM;
345fe56b9e6SYuval Mintz goto err2;
346fe56b9e6SYuval Mintz }
347fe56b9e6SYuval Mintz
348fe56b9e6SYuval Mintz cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2);
349fe56b9e6SYuval Mintz cdev->db_size = pci_resource_len(cdev->pdev, 2);
3501a850bfcSMintz, Yuval if (!cdev->db_size) {
3511a850bfcSMintz, Yuval if (IS_PF(cdev)) {
3521a850bfcSMintz, Yuval DP_NOTICE(cdev, "No Doorbell bar available\n");
3531a850bfcSMintz, Yuval return -EINVAL;
3541a850bfcSMintz, Yuval } else {
3551a850bfcSMintz, Yuval return 0;
3561a850bfcSMintz, Yuval }
3571a850bfcSMintz, Yuval }
3581a850bfcSMintz, Yuval
359fe56b9e6SYuval Mintz cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size);
3601a850bfcSMintz, Yuval
361fe56b9e6SYuval Mintz if (!cdev->doorbells) {
362fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Cannot map doorbell space\n");
363fe56b9e6SYuval Mintz return -ENOMEM;
364fe56b9e6SYuval Mintz }
365fe56b9e6SYuval Mintz
366fe56b9e6SYuval Mintz return 0;
367fe56b9e6SYuval Mintz
368fe56b9e6SYuval Mintz err2:
369fe56b9e6SYuval Mintz pci_release_regions(pdev);
370fe56b9e6SYuval Mintz err1:
371fe56b9e6SYuval Mintz pci_disable_device(pdev);
372fe56b9e6SYuval Mintz err0:
373fe56b9e6SYuval Mintz return rc;
374fe56b9e6SYuval Mintz }
375fe56b9e6SYuval Mintz
qed_fill_dev_info(struct qed_dev * cdev,struct qed_dev_info * dev_info)376fe56b9e6SYuval Mintz int qed_fill_dev_info(struct qed_dev *cdev,
377fe56b9e6SYuval Mintz struct qed_dev_info *dev_info)
378fe56b9e6SYuval Mintz {
379c851a9dcSKalderon, Michal struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
380c851a9dcSKalderon, Michal struct qed_hw_info *hw_info = &p_hwfn->hw_info;
38119489c7fSChopra, Manish struct qed_tunnel_info *tun = &cdev->tunnel;
382cee4d264SManish Chopra struct qed_ptt *ptt;
383cee4d264SManish Chopra
384fe56b9e6SYuval Mintz memset(dev_info, 0, sizeof(struct qed_dev_info));
385fe56b9e6SYuval Mintz
38619489c7fSChopra, Manish if (tun->vxlan.tun_cls == QED_TUNN_CLSS_MAC_VLAN &&
38719489c7fSChopra, Manish tun->vxlan.b_mode_enabled)
38819489c7fSChopra, Manish dev_info->vxlan_enable = true;
38919489c7fSChopra, Manish
39019489c7fSChopra, Manish if (tun->l2_gre.b_mode_enabled && tun->ip_gre.b_mode_enabled &&
39119489c7fSChopra, Manish tun->l2_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN &&
39219489c7fSChopra, Manish tun->ip_gre.tun_cls == QED_TUNN_CLSS_MAC_VLAN)
39319489c7fSChopra, Manish dev_info->gre_enable = true;
39419489c7fSChopra, Manish
39519489c7fSChopra, Manish if (tun->l2_geneve.b_mode_enabled && tun->ip_geneve.b_mode_enabled &&
39619489c7fSChopra, Manish tun->l2_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN &&
39719489c7fSChopra, Manish tun->ip_geneve.tun_cls == QED_TUNN_CLSS_MAC_VLAN)
39819489c7fSChopra, Manish dev_info->geneve_enable = true;
39919489c7fSChopra, Manish
400fe56b9e6SYuval Mintz dev_info->num_hwfns = cdev->num_hwfns;
401fe56b9e6SYuval Mintz dev_info->pci_mem_start = cdev->pci_params.mem_start;
402fe56b9e6SYuval Mintz dev_info->pci_mem_end = cdev->pci_params.mem_end;
403fe56b9e6SYuval Mintz dev_info->pci_irq = cdev->pci_params.irq;
404c851a9dcSKalderon, Michal dev_info->rdma_supported = QED_IS_RDMA_PERSONALITY(p_hwfn);
4059c79ddaaSMintz, Yuval dev_info->dev_type = cdev->type;
406c851a9dcSKalderon, Michal ether_addr_copy(dev_info->hw_mac, hw_info->hw_mac_addr);
407fe56b9e6SYuval Mintz
4081408cc1fSYuval Mintz if (IS_PF(cdev)) {
409fe56b9e6SYuval Mintz dev_info->fw_major = FW_MAJOR_VERSION;
410fe56b9e6SYuval Mintz dev_info->fw_minor = FW_MINOR_VERSION;
411fe56b9e6SYuval Mintz dev_info->fw_rev = FW_REVISION_VERSION;
412fe56b9e6SYuval Mintz dev_info->fw_eng = FW_ENGINEERING_VERSION;
4130bc5fe85SSudarsana Reddy Kalluru dev_info->b_inter_pf_switch = test_bit(QED_MF_INTER_PF_SWITCH,
4140bc5fe85SSudarsana Reddy Kalluru &cdev->mf_bits);
4152d2fe843SDmitry Bogdanov if (!test_bit(QED_MF_DISABLE_ARFS, &cdev->mf_bits))
4162d2fe843SDmitry Bogdanov dev_info->b_arfs_capable = true;
417831bfb0eSYuval Mintz dev_info->tx_switching = true;
41814d39648SMintz, Yuval
419c851a9dcSKalderon, Michal if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME)
42014d39648SMintz, Yuval dev_info->wol_support = true;
4213c5da942SMintz, Yuval
422df9c716dSSudarsana Reddy Kalluru dev_info->smart_an = qed_mcp_is_smart_an_supported(p_hwfn);
423823163baSManish Chopra dev_info->esl = qed_mcp_is_esl_supported(p_hwfn);
4243c5da942SMintz, Yuval dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id;
4251408cc1fSYuval Mintz } else {
4261408cc1fSYuval Mintz qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
4271408cc1fSYuval Mintz &dev_info->fw_minor, &dev_info->fw_rev,
4281408cc1fSYuval Mintz &dev_info->fw_eng);
4291408cc1fSYuval Mintz }
430fe56b9e6SYuval Mintz
4311408cc1fSYuval Mintz if (IS_PF(cdev)) {
432cee4d264SManish Chopra ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
433cee4d264SManish Chopra if (ptt) {
4341408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), ptt,
4351408cc1fSYuval Mintz &dev_info->mfw_rev, NULL);
4361408cc1fSYuval Mintz
437ae33666aSTomer Tayar qed_mcp_get_mbi_ver(QED_LEADING_HWFN(cdev), ptt,
438ae33666aSTomer Tayar &dev_info->mbi_version);
439ae33666aSTomer Tayar
440cee4d264SManish Chopra qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt,
441cee4d264SManish Chopra &dev_info->flash_size);
442cee4d264SManish Chopra
443cee4d264SManish Chopra qed_ptt_release(QED_LEADING_HWFN(cdev), ptt);
444cee4d264SManish Chopra }
4451408cc1fSYuval Mintz } else {
4461408cc1fSYuval Mintz qed_mcp_get_mfw_ver(QED_LEADING_HWFN(cdev), NULL,
4471408cc1fSYuval Mintz &dev_info->mfw_rev, NULL);
4481408cc1fSYuval Mintz }
449cee4d264SManish Chopra
450c851a9dcSKalderon, Michal dev_info->mtu = hw_info->mtu;
45153916a67SIgor Russkikh cdev->common_dev_info = *dev_info;
4520fefbfbaSSudarsana Kalluru
453fe56b9e6SYuval Mintz return 0;
454fe56b9e6SYuval Mintz }
455fe56b9e6SYuval Mintz
qed_free_cdev(struct qed_dev * cdev)456fe56b9e6SYuval Mintz static void qed_free_cdev(struct qed_dev *cdev)
457fe56b9e6SYuval Mintz {
458fe56b9e6SYuval Mintz kfree((void *)cdev);
459fe56b9e6SYuval Mintz }
460fe56b9e6SYuval Mintz
qed_alloc_cdev(struct pci_dev * pdev)461fe56b9e6SYuval Mintz static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev)
462fe56b9e6SYuval Mintz {
463fe56b9e6SYuval Mintz struct qed_dev *cdev;
464fe56b9e6SYuval Mintz
465fe56b9e6SYuval Mintz cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
466fe56b9e6SYuval Mintz if (!cdev)
467fe56b9e6SYuval Mintz return cdev;
468fe56b9e6SYuval Mintz
469fe56b9e6SYuval Mintz qed_init_struct(cdev);
470fe56b9e6SYuval Mintz
471fe56b9e6SYuval Mintz return cdev;
472fe56b9e6SYuval Mintz }
473fe56b9e6SYuval Mintz
474fe56b9e6SYuval Mintz /* Sets the requested power state */
qed_set_power_state(struct qed_dev * cdev,pci_power_t state)4751a635e48SYuval Mintz static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state)
476fe56b9e6SYuval Mintz {
477fe56b9e6SYuval Mintz if (!cdev)
478fe56b9e6SYuval Mintz return -ENODEV;
479fe56b9e6SYuval Mintz
480fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n");
481fe56b9e6SYuval Mintz return 0;
482fe56b9e6SYuval Mintz }
483fe56b9e6SYuval Mintz
484fe56b9e6SYuval Mintz /* probing */
qed_probe(struct pci_dev * pdev,struct qed_probe_params * params)485fe56b9e6SYuval Mintz static struct qed_dev *qed_probe(struct pci_dev *pdev,
4861408cc1fSYuval Mintz struct qed_probe_params *params)
487fe56b9e6SYuval Mintz {
488fe56b9e6SYuval Mintz struct qed_dev *cdev;
489fe56b9e6SYuval Mintz int rc;
490fe56b9e6SYuval Mintz
491fe56b9e6SYuval Mintz cdev = qed_alloc_cdev(pdev);
492fe56b9e6SYuval Mintz if (!cdev)
493fe56b9e6SYuval Mintz goto err0;
494fe56b9e6SYuval Mintz
495712c3cbfSMintz, Yuval cdev->drv_type = DRV_ID_DRV_TYPE_LINUX;
4961408cc1fSYuval Mintz cdev->protocol = params->protocol;
497fe56b9e6SYuval Mintz
4981408cc1fSYuval Mintz if (params->is_vf)
4991408cc1fSYuval Mintz cdev->b_is_vf = true;
5001408cc1fSYuval Mintz
5011408cc1fSYuval Mintz qed_init_dp(cdev, params->dp_module, params->dp_level);
502fe56b9e6SYuval Mintz
50364515dc8STomer Tayar cdev->recov_in_prog = params->recov_in_prog;
50464515dc8STomer Tayar
505fe56b9e6SYuval Mintz rc = qed_init_pci(cdev, pdev);
506fe56b9e6SYuval Mintz if (rc) {
507fe56b9e6SYuval Mintz DP_ERR(cdev, "init pci failed\n");
508fe56b9e6SYuval Mintz goto err1;
509fe56b9e6SYuval Mintz }
510fe56b9e6SYuval Mintz DP_INFO(cdev, "PCI init completed successfully\n");
511fe56b9e6SYuval Mintz
512fe56b9e6SYuval Mintz rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT);
513fe56b9e6SYuval Mintz if (rc) {
514fe56b9e6SYuval Mintz DP_ERR(cdev, "hw prepare failed\n");
515fe56b9e6SYuval Mintz goto err2;
516fe56b9e6SYuval Mintz }
517fe56b9e6SYuval Mintz
518f2a74107SPrabhakar Kushwaha DP_INFO(cdev, "%s completed successfully\n", __func__);
519fe56b9e6SYuval Mintz
520fe56b9e6SYuval Mintz return cdev;
521fe56b9e6SYuval Mintz
522fe56b9e6SYuval Mintz err2:
523fe56b9e6SYuval Mintz qed_free_pci(cdev);
524fe56b9e6SYuval Mintz err1:
525fe56b9e6SYuval Mintz qed_free_cdev(cdev);
526fe56b9e6SYuval Mintz err0:
527fe56b9e6SYuval Mintz return NULL;
528fe56b9e6SYuval Mintz }
529fe56b9e6SYuval Mintz
qed_remove(struct qed_dev * cdev)530fe56b9e6SYuval Mintz static void qed_remove(struct qed_dev *cdev)
531fe56b9e6SYuval Mintz {
532fe56b9e6SYuval Mintz if (!cdev)
533fe56b9e6SYuval Mintz return;
534fe56b9e6SYuval Mintz
535fe56b9e6SYuval Mintz qed_hw_remove(cdev);
536fe56b9e6SYuval Mintz
537fe56b9e6SYuval Mintz qed_free_pci(cdev);
538fe56b9e6SYuval Mintz
539fe56b9e6SYuval Mintz qed_set_power_state(cdev, PCI_D3hot);
540fe56b9e6SYuval Mintz
541fe56b9e6SYuval Mintz qed_free_cdev(cdev);
542fe56b9e6SYuval Mintz }
543fe56b9e6SYuval Mintz
qed_disable_msix(struct qed_dev * cdev)544fe56b9e6SYuval Mintz static void qed_disable_msix(struct qed_dev *cdev)
545fe56b9e6SYuval Mintz {
546fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
547fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev);
548fe56b9e6SYuval Mintz kfree(cdev->int_params.msix_table);
549fe56b9e6SYuval Mintz } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) {
550fe56b9e6SYuval Mintz pci_disable_msi(cdev->pdev);
551fe56b9e6SYuval Mintz }
552fe56b9e6SYuval Mintz
553fe56b9e6SYuval Mintz memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param));
554fe56b9e6SYuval Mintz }
555fe56b9e6SYuval Mintz
qed_enable_msix(struct qed_dev * cdev,struct qed_int_params * int_params)556fe56b9e6SYuval Mintz static int qed_enable_msix(struct qed_dev *cdev,
557fe56b9e6SYuval Mintz struct qed_int_params *int_params)
558fe56b9e6SYuval Mintz {
559fe56b9e6SYuval Mintz int i, rc, cnt;
560fe56b9e6SYuval Mintz
561fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors;
562fe56b9e6SYuval Mintz
563fe56b9e6SYuval Mintz for (i = 0; i < cnt; i++)
564fe56b9e6SYuval Mintz int_params->msix_table[i].entry = i;
565fe56b9e6SYuval Mintz
566fe56b9e6SYuval Mintz rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table,
567fe56b9e6SYuval Mintz int_params->in.min_msix_cnt, cnt);
568fe56b9e6SYuval Mintz if (rc < cnt && rc >= int_params->in.min_msix_cnt &&
569fe56b9e6SYuval Mintz (rc % cdev->num_hwfns)) {
570fe56b9e6SYuval Mintz pci_disable_msix(cdev->pdev);
571fe56b9e6SYuval Mintz
572fe56b9e6SYuval Mintz /* If fastpath is initialized, we need at least one interrupt
573fe56b9e6SYuval Mintz * per hwfn [and the slow path interrupts]. New requested number
574fe56b9e6SYuval Mintz * should be a multiple of the number of hwfns.
575fe56b9e6SYuval Mintz */
576fe56b9e6SYuval Mintz cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns;
577fe56b9e6SYuval Mintz DP_NOTICE(cdev,
578fe56b9e6SYuval Mintz "Trying to enable MSI-X with less vectors (%d out of %d)\n",
579fe56b9e6SYuval Mintz cnt, int_params->in.num_vectors);
5801a635e48SYuval Mintz rc = pci_enable_msix_exact(cdev->pdev, int_params->msix_table,
5811a635e48SYuval Mintz cnt);
582fe56b9e6SYuval Mintz if (!rc)
583fe56b9e6SYuval Mintz rc = cnt;
584fe56b9e6SYuval Mintz }
585fe56b9e6SYuval Mintz
586b0cd0853SShai Malin /* For VFs, we should return with an error in case we didn't get the
587b0cd0853SShai Malin * exact number of msix vectors as we requested.
588b0cd0853SShai Malin * Not doing that will lead to a crash when starting queues for
589b0cd0853SShai Malin * this VF.
590b0cd0853SShai Malin */
591b0cd0853SShai Malin if ((IS_PF(cdev) && rc > 0) || (IS_VF(cdev) && rc == cnt)) {
592fe56b9e6SYuval Mintz /* MSI-x configuration was achieved */
593fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSIX;
594fe56b9e6SYuval Mintz int_params->out.num_vectors = rc;
595fe56b9e6SYuval Mintz rc = 0;
596fe56b9e6SYuval Mintz } else {
597fe56b9e6SYuval Mintz DP_NOTICE(cdev,
598fe56b9e6SYuval Mintz "Failed to enable MSI-X [Requested %d vectors][rc %d]\n",
599fe56b9e6SYuval Mintz cnt, rc);
600fe56b9e6SYuval Mintz }
601fe56b9e6SYuval Mintz
602fe56b9e6SYuval Mintz return rc;
603fe56b9e6SYuval Mintz }
604fe56b9e6SYuval Mintz
605fe56b9e6SYuval Mintz /* This function outputs the int mode and the number of enabled msix vector */
qed_set_int_mode(struct qed_dev * cdev,bool force_mode)606fe56b9e6SYuval Mintz static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode)
607fe56b9e6SYuval Mintz {
608fe56b9e6SYuval Mintz struct qed_int_params *int_params = &cdev->int_params;
609fe56b9e6SYuval Mintz struct msix_entry *tbl;
610fe56b9e6SYuval Mintz int rc = 0, cnt;
611fe56b9e6SYuval Mintz
612fe56b9e6SYuval Mintz switch (int_params->in.int_mode) {
613fe56b9e6SYuval Mintz case QED_INT_MODE_MSIX:
614fe56b9e6SYuval Mintz /* Allocate MSIX table */
615fe56b9e6SYuval Mintz cnt = int_params->in.num_vectors;
616fe56b9e6SYuval Mintz int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL);
617fe56b9e6SYuval Mintz if (!int_params->msix_table) {
618fe56b9e6SYuval Mintz rc = -ENOMEM;
619fe56b9e6SYuval Mintz goto out;
620fe56b9e6SYuval Mintz }
621fe56b9e6SYuval Mintz
622fe56b9e6SYuval Mintz /* Enable MSIX */
623fe56b9e6SYuval Mintz rc = qed_enable_msix(cdev, int_params);
624fe56b9e6SYuval Mintz if (!rc)
625fe56b9e6SYuval Mintz goto out;
626fe56b9e6SYuval Mintz
627fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI-X\n");
628fe56b9e6SYuval Mintz kfree(int_params->msix_table);
629fe56b9e6SYuval Mintz if (force_mode)
630fe56b9e6SYuval Mintz goto out;
631df561f66SGustavo A. R. Silva fallthrough;
632fe56b9e6SYuval Mintz
633fe56b9e6SYuval Mintz case QED_INT_MODE_MSI:
634bb13ace7SSudarsana Reddy Kalluru if (cdev->num_hwfns == 1) {
635fe56b9e6SYuval Mintz rc = pci_enable_msi(cdev->pdev);
636fe56b9e6SYuval Mintz if (!rc) {
637fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_MSI;
638fe56b9e6SYuval Mintz goto out;
639fe56b9e6SYuval Mintz }
640fe56b9e6SYuval Mintz
641fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed to enable MSI\n");
642fe56b9e6SYuval Mintz if (force_mode)
643fe56b9e6SYuval Mintz goto out;
644bb13ace7SSudarsana Reddy Kalluru }
645df561f66SGustavo A. R. Silva fallthrough;
646fe56b9e6SYuval Mintz
647fe56b9e6SYuval Mintz case QED_INT_MODE_INTA:
648fe56b9e6SYuval Mintz int_params->out.int_mode = QED_INT_MODE_INTA;
649fe56b9e6SYuval Mintz rc = 0;
650fe56b9e6SYuval Mintz goto out;
651fe56b9e6SYuval Mintz default:
652fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Unknown int_mode value %d\n",
653fe56b9e6SYuval Mintz int_params->in.int_mode);
654fe56b9e6SYuval Mintz rc = -EINVAL;
655fe56b9e6SYuval Mintz }
656fe56b9e6SYuval Mintz
657fe56b9e6SYuval Mintz out:
658525ef5c0SYuval Mintz if (!rc)
659525ef5c0SYuval Mintz DP_INFO(cdev, "Using %s interrupts\n",
660525ef5c0SYuval Mintz int_params->out.int_mode == QED_INT_MODE_INTA ?
661525ef5c0SYuval Mintz "INTa" : int_params->out.int_mode == QED_INT_MODE_MSI ?
662525ef5c0SYuval Mintz "MSI" : "MSIX");
663fe56b9e6SYuval Mintz cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE;
664fe56b9e6SYuval Mintz
665fe56b9e6SYuval Mintz return rc;
666fe56b9e6SYuval Mintz }
667fe56b9e6SYuval Mintz
qed_simd_handler_config(struct qed_dev * cdev,void * token,int index,void (* handler)(void *))668fe56b9e6SYuval Mintz static void qed_simd_handler_config(struct qed_dev *cdev, void *token,
669fe56b9e6SYuval Mintz int index, void(*handler)(void *))
670fe56b9e6SYuval Mintz {
671fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns];
672fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns;
673fe56b9e6SYuval Mintz
674fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].func = handler;
675fe56b9e6SYuval Mintz hwfn->simd_proto_handler[relative_idx].token = token;
676fe56b9e6SYuval Mintz }
677fe56b9e6SYuval Mintz
qed_simd_handler_clean(struct qed_dev * cdev,int index)678fe56b9e6SYuval Mintz static void qed_simd_handler_clean(struct qed_dev *cdev, int index)
679fe56b9e6SYuval Mintz {
680fe56b9e6SYuval Mintz struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns];
681fe56b9e6SYuval Mintz int relative_idx = index / cdev->num_hwfns;
682fe56b9e6SYuval Mintz
683fe56b9e6SYuval Mintz memset(&hwfn->simd_proto_handler[relative_idx], 0,
684fe56b9e6SYuval Mintz sizeof(struct qed_simd_fp_handler));
685fe56b9e6SYuval Mintz }
686fe56b9e6SYuval Mintz
qed_msix_sp_int(int irq,void * tasklet)687fe56b9e6SYuval Mintz static irqreturn_t qed_msix_sp_int(int irq, void *tasklet)
688fe56b9e6SYuval Mintz {
689fe56b9e6SYuval Mintz tasklet_schedule((struct tasklet_struct *)tasklet);
690fe56b9e6SYuval Mintz return IRQ_HANDLED;
691fe56b9e6SYuval Mintz }
692fe56b9e6SYuval Mintz
qed_single_int(int irq,void * dev_instance)693fe56b9e6SYuval Mintz static irqreturn_t qed_single_int(int irq, void *dev_instance)
694fe56b9e6SYuval Mintz {
695fe56b9e6SYuval Mintz struct qed_dev *cdev = (struct qed_dev *)dev_instance;
696fe56b9e6SYuval Mintz struct qed_hwfn *hwfn;
697fe56b9e6SYuval Mintz irqreturn_t rc = IRQ_NONE;
698fe56b9e6SYuval Mintz u64 status;
699fe56b9e6SYuval Mintz int i, j;
700fe56b9e6SYuval Mintz
701fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) {
702fe56b9e6SYuval Mintz status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]);
703fe56b9e6SYuval Mintz
704fe56b9e6SYuval Mintz if (!status)
705fe56b9e6SYuval Mintz continue;
706fe56b9e6SYuval Mintz
707fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i];
708fe56b9e6SYuval Mintz
709fe56b9e6SYuval Mintz /* Slowpath interrupt */
710fe56b9e6SYuval Mintz if (unlikely(status & 0x1)) {
711b5f0a3bfSAllen Pais tasklet_schedule(&hwfn->sp_dpc);
712fe56b9e6SYuval Mintz status &= ~0x1;
713fe56b9e6SYuval Mintz rc = IRQ_HANDLED;
714fe56b9e6SYuval Mintz }
715fe56b9e6SYuval Mintz
716fe56b9e6SYuval Mintz /* Fastpath interrupts */
717fe56b9e6SYuval Mintz for (j = 0; j < 64; j++) {
718fe56b9e6SYuval Mintz if ((0x2ULL << j) & status) {
7193935a709SSudarsana Reddy Kalluru struct qed_simd_fp_handler *p_handler =
7203935a709SSudarsana Reddy Kalluru &hwfn->simd_proto_handler[j];
7213935a709SSudarsana Reddy Kalluru
7223935a709SSudarsana Reddy Kalluru if (p_handler->func)
7233935a709SSudarsana Reddy Kalluru p_handler->func(p_handler->token);
7243935a709SSudarsana Reddy Kalluru else
7253935a709SSudarsana Reddy Kalluru DP_NOTICE(hwfn,
7263935a709SSudarsana Reddy Kalluru "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n",
7273935a709SSudarsana Reddy Kalluru j, status);
7283935a709SSudarsana Reddy Kalluru
729fe56b9e6SYuval Mintz status &= ~(0x2ULL << j);
730fe56b9e6SYuval Mintz rc = IRQ_HANDLED;
731fe56b9e6SYuval Mintz }
732fe56b9e6SYuval Mintz }
733fe56b9e6SYuval Mintz
734fe56b9e6SYuval Mintz if (unlikely(status))
735fe56b9e6SYuval Mintz DP_VERBOSE(hwfn, NETIF_MSG_INTR,
736fe56b9e6SYuval Mintz "got an unknown interrupt status 0x%llx\n",
737fe56b9e6SYuval Mintz status);
738fe56b9e6SYuval Mintz }
739fe56b9e6SYuval Mintz
740fe56b9e6SYuval Mintz return rc;
741fe56b9e6SYuval Mintz }
742fe56b9e6SYuval Mintz
qed_slowpath_irq_req(struct qed_hwfn * hwfn)7438f16bc97SSudarsana Kalluru int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
744fe56b9e6SYuval Mintz {
7458f16bc97SSudarsana Kalluru struct qed_dev *cdev = hwfn->cdev;
746525ef5c0SYuval Mintz u32 int_mode;
7478f16bc97SSudarsana Kalluru int rc = 0;
7488f16bc97SSudarsana Kalluru u8 id;
749fe56b9e6SYuval Mintz
750525ef5c0SYuval Mintz int_mode = cdev->int_params.out.int_mode;
751525ef5c0SYuval Mintz if (int_mode == QED_INT_MODE_MSIX) {
7528f16bc97SSudarsana Kalluru id = hwfn->my_id;
7538f16bc97SSudarsana Kalluru snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x",
7548f16bc97SSudarsana Kalluru id, cdev->pdev->bus->number,
7558f16bc97SSudarsana Kalluru PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
7568f16bc97SSudarsana Kalluru rc = request_irq(cdev->int_params.msix_table[id].vector,
757b5f0a3bfSAllen Pais qed_msix_sp_int, 0, hwfn->name, &hwfn->sp_dpc);
758fe56b9e6SYuval Mintz } else {
759fe56b9e6SYuval Mintz unsigned long flags = 0;
760fe56b9e6SYuval Mintz
761fe56b9e6SYuval Mintz snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x",
762fe56b9e6SYuval Mintz cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn),
763fe56b9e6SYuval Mintz PCI_FUNC(cdev->pdev->devfn));
764fe56b9e6SYuval Mintz
765fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA)
766fe56b9e6SYuval Mintz flags |= IRQF_SHARED;
767fe56b9e6SYuval Mintz
768fe56b9e6SYuval Mintz rc = request_irq(cdev->pdev->irq, qed_single_int,
769fe56b9e6SYuval Mintz flags, cdev->name, cdev);
770fe56b9e6SYuval Mintz }
771fe56b9e6SYuval Mintz
772525ef5c0SYuval Mintz if (rc)
773525ef5c0SYuval Mintz DP_NOTICE(cdev, "request_irq failed, rc = %d\n", rc);
774525ef5c0SYuval Mintz else
775525ef5c0SYuval Mintz DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
776525ef5c0SYuval Mintz "Requested slowpath %s\n",
777525ef5c0SYuval Mintz (int_mode == QED_INT_MODE_MSIX) ? "MSI-X" : "IRQ");
778525ef5c0SYuval Mintz
779fe56b9e6SYuval Mintz return rc;
780fe56b9e6SYuval Mintz }
781fe56b9e6SYuval Mintz
qed_slowpath_tasklet_flush(struct qed_hwfn * p_hwfn)78206892f2eSTomer Tayar static void qed_slowpath_tasklet_flush(struct qed_hwfn *p_hwfn)
78306892f2eSTomer Tayar {
78406892f2eSTomer Tayar /* Calling the disable function will make sure that any
78506892f2eSTomer Tayar * currently-running function is completed. The following call to the
78606892f2eSTomer Tayar * enable function makes this sequence a flush-like operation.
78706892f2eSTomer Tayar */
78806892f2eSTomer Tayar if (p_hwfn->b_sp_dpc_enabled) {
789b5f0a3bfSAllen Pais tasklet_disable(&p_hwfn->sp_dpc);
790b5f0a3bfSAllen Pais tasklet_enable(&p_hwfn->sp_dpc);
79106892f2eSTomer Tayar }
79206892f2eSTomer Tayar }
79306892f2eSTomer Tayar
qed_slowpath_irq_sync(struct qed_hwfn * p_hwfn)7941226337aSTomer Tayar void qed_slowpath_irq_sync(struct qed_hwfn *p_hwfn)
7951226337aSTomer Tayar {
7961226337aSTomer Tayar struct qed_dev *cdev = p_hwfn->cdev;
7971226337aSTomer Tayar u8 id = p_hwfn->my_id;
7981226337aSTomer Tayar u32 int_mode;
7991226337aSTomer Tayar
8001226337aSTomer Tayar int_mode = cdev->int_params.out.int_mode;
8011226337aSTomer Tayar if (int_mode == QED_INT_MODE_MSIX)
8021226337aSTomer Tayar synchronize_irq(cdev->int_params.msix_table[id].vector);
8031226337aSTomer Tayar else
8041226337aSTomer Tayar synchronize_irq(cdev->pdev->irq);
80506892f2eSTomer Tayar
80606892f2eSTomer Tayar qed_slowpath_tasklet_flush(p_hwfn);
8071226337aSTomer Tayar }
8081226337aSTomer Tayar
qed_slowpath_irq_free(struct qed_dev * cdev)809fe56b9e6SYuval Mintz static void qed_slowpath_irq_free(struct qed_dev *cdev)
810fe56b9e6SYuval Mintz {
811fe56b9e6SYuval Mintz int i;
812fe56b9e6SYuval Mintz
813fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
814fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) {
8158f16bc97SSudarsana Kalluru if (!cdev->hwfns[i].b_int_requested)
8168f16bc97SSudarsana Kalluru break;
817fe56b9e6SYuval Mintz free_irq(cdev->int_params.msix_table[i].vector,
818b5f0a3bfSAllen Pais &cdev->hwfns[i].sp_dpc);
819fe56b9e6SYuval Mintz }
820fe56b9e6SYuval Mintz } else {
8218f16bc97SSudarsana Kalluru if (QED_LEADING_HWFN(cdev)->b_int_requested)
822fe56b9e6SYuval Mintz free_irq(cdev->pdev->irq, cdev);
823fe56b9e6SYuval Mintz }
8248f16bc97SSudarsana Kalluru qed_int_disable_post_isr_release(cdev);
825fe56b9e6SYuval Mintz }
826fe56b9e6SYuval Mintz
qed_nic_stop(struct qed_dev * cdev)827fe56b9e6SYuval Mintz static int qed_nic_stop(struct qed_dev *cdev)
828fe56b9e6SYuval Mintz {
829fe56b9e6SYuval Mintz int i, rc;
830fe56b9e6SYuval Mintz
831fe56b9e6SYuval Mintz rc = qed_hw_stop(cdev);
832fe56b9e6SYuval Mintz
833fe56b9e6SYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) {
834fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
835fe56b9e6SYuval Mintz
836fe56b9e6SYuval Mintz if (p_hwfn->b_sp_dpc_enabled) {
837b5f0a3bfSAllen Pais tasklet_disable(&p_hwfn->sp_dpc);
838fe56b9e6SYuval Mintz p_hwfn->b_sp_dpc_enabled = false;
839fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_IFDOWN,
8402fdae034SColin Ian King "Disabled sp tasklet [hwfn %d] at %p\n",
841b5f0a3bfSAllen Pais i, &p_hwfn->sp_dpc);
842fe56b9e6SYuval Mintz }
843fe56b9e6SYuval Mintz }
844fe56b9e6SYuval Mintz
845c965db44STomer Tayar qed_dbg_pf_exit(cdev);
846c965db44STomer Tayar
847fe56b9e6SYuval Mintz return rc;
848fe56b9e6SYuval Mintz }
849fe56b9e6SYuval Mintz
qed_nic_setup(struct qed_dev * cdev)850fe56b9e6SYuval Mintz static int qed_nic_setup(struct qed_dev *cdev)
851fe56b9e6SYuval Mintz {
8520a7fb11cSYuval Mintz int rc, i;
8530a7fb11cSYuval Mintz
8540a7fb11cSYuval Mintz /* Determine if interface is going to require LL2 */
8550a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->hw_info.personality != QED_PCI_ETH) {
8560a7fb11cSYuval Mintz for (i = 0; i < cdev->num_hwfns; i++) {
8570a7fb11cSYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
8580a7fb11cSYuval Mintz
8590a7fb11cSYuval Mintz p_hwfn->using_ll2 = true;
8600a7fb11cSYuval Mintz }
8610a7fb11cSYuval Mintz }
862fe56b9e6SYuval Mintz
863fe56b9e6SYuval Mintz rc = qed_resc_alloc(cdev);
864fe56b9e6SYuval Mintz if (rc)
865fe56b9e6SYuval Mintz return rc;
866fe56b9e6SYuval Mintz
867fe56b9e6SYuval Mintz DP_INFO(cdev, "Allocated qed resources\n");
868fe56b9e6SYuval Mintz
869fe56b9e6SYuval Mintz qed_resc_setup(cdev);
870fe56b9e6SYuval Mintz
871fe56b9e6SYuval Mintz return rc;
872fe56b9e6SYuval Mintz }
873fe56b9e6SYuval Mintz
qed_set_int_fp(struct qed_dev * cdev,u16 cnt)874fe56b9e6SYuval Mintz static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt)
875fe56b9e6SYuval Mintz {
876fe56b9e6SYuval Mintz int limit = 0;
877fe56b9e6SYuval Mintz
878fe56b9e6SYuval Mintz /* Mark the fastpath as free/used */
879fe56b9e6SYuval Mintz cdev->int_params.fp_initialized = cnt ? true : false;
880fe56b9e6SYuval Mintz
881fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX)
882fe56b9e6SYuval Mintz limit = cdev->num_hwfns * 63;
883fe56b9e6SYuval Mintz else if (cdev->int_params.fp_msix_cnt)
884fe56b9e6SYuval Mintz limit = cdev->int_params.fp_msix_cnt;
885fe56b9e6SYuval Mintz
886fe56b9e6SYuval Mintz if (!limit)
887fe56b9e6SYuval Mintz return -ENOMEM;
888fe56b9e6SYuval Mintz
889fe56b9e6SYuval Mintz return min_t(int, cnt, limit);
890fe56b9e6SYuval Mintz }
891fe56b9e6SYuval Mintz
qed_get_int_fp(struct qed_dev * cdev,struct qed_int_info * info)892fe56b9e6SYuval Mintz static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info)
893fe56b9e6SYuval Mintz {
894fe56b9e6SYuval Mintz memset(info, 0, sizeof(struct qed_int_info));
895fe56b9e6SYuval Mintz
896fe56b9e6SYuval Mintz if (!cdev->int_params.fp_initialized) {
897fe56b9e6SYuval Mintz DP_INFO(cdev,
898fe56b9e6SYuval Mintz "Protocol driver requested interrupt information, but its support is not yet configured\n");
899fe56b9e6SYuval Mintz return -EINVAL;
900fe56b9e6SYuval Mintz }
901fe56b9e6SYuval Mintz
902fe56b9e6SYuval Mintz /* Need to expose only MSI-X information; Single IRQ is handled solely
903fe56b9e6SYuval Mintz * by qed.
904fe56b9e6SYuval Mintz */
905fe56b9e6SYuval Mintz if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
906fe56b9e6SYuval Mintz int msix_base = cdev->int_params.fp_msix_base;
907fe56b9e6SYuval Mintz
908fe56b9e6SYuval Mintz info->msix_cnt = cdev->int_params.fp_msix_cnt;
909fe56b9e6SYuval Mintz info->msix = &cdev->int_params.msix_table[msix_base];
910fe56b9e6SYuval Mintz }
911fe56b9e6SYuval Mintz
912fe56b9e6SYuval Mintz return 0;
913fe56b9e6SYuval Mintz }
914fe56b9e6SYuval Mintz
qed_slowpath_setup_int(struct qed_dev * cdev,enum qed_int_mode int_mode)915fe56b9e6SYuval Mintz static int qed_slowpath_setup_int(struct qed_dev *cdev,
916fe56b9e6SYuval Mintz enum qed_int_mode int_mode)
917fe56b9e6SYuval Mintz {
9184ac801b7SYuval Mintz struct qed_sb_cnt_info sb_cnt_info;
9190189efb8SYuval Mintz int num_l2_queues = 0;
9204ac801b7SYuval Mintz int rc;
9214ac801b7SYuval Mintz int i;
922fe56b9e6SYuval Mintz
9231d2c2024SSudarsana Reddy Kalluru if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
9241d2c2024SSudarsana Reddy Kalluru DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
9251d2c2024SSudarsana Reddy Kalluru return -EINVAL;
9261d2c2024SSudarsana Reddy Kalluru }
9271d2c2024SSudarsana Reddy Kalluru
9281d2c2024SSudarsana Reddy Kalluru memset(&cdev->int_params, 0, sizeof(struct qed_int_params));
929fe56b9e6SYuval Mintz cdev->int_params.in.int_mode = int_mode;
9304ac801b7SYuval Mintz for_each_hwfn(cdev, i) {
9314ac801b7SYuval Mintz memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
9324ac801b7SYuval Mintz qed_int_get_num_sbs(&cdev->hwfns[i], &sb_cnt_info);
933726fdbe9SMintz, Yuval cdev->int_params.in.num_vectors += sb_cnt_info.cnt;
9344ac801b7SYuval Mintz cdev->int_params.in.num_vectors++; /* slowpath */
9354ac801b7SYuval Mintz }
936fe56b9e6SYuval Mintz
937fe56b9e6SYuval Mintz /* We want a minimum of one slowpath and one fastpath vector per hwfn */
938fe56b9e6SYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2;
939fe56b9e6SYuval Mintz
940bb7858baSSudarsana Reddy Kalluru if (is_kdump_kernel()) {
941bb7858baSSudarsana Reddy Kalluru DP_INFO(cdev,
942bb7858baSSudarsana Reddy Kalluru "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n",
943bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt);
944bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.num_vectors =
945bb7858baSSudarsana Reddy Kalluru cdev->int_params.in.min_msix_cnt;
946bb7858baSSudarsana Reddy Kalluru }
947bb7858baSSudarsana Reddy Kalluru
948fe56b9e6SYuval Mintz rc = qed_set_int_mode(cdev, false);
949fe56b9e6SYuval Mintz if (rc) {
950f2a74107SPrabhakar Kushwaha DP_ERR(cdev, "%s ERR\n", __func__);
951fe56b9e6SYuval Mintz return rc;
952fe56b9e6SYuval Mintz }
953fe56b9e6SYuval Mintz
954fe56b9e6SYuval Mintz cdev->int_params.fp_msix_base = cdev->num_hwfns;
955fe56b9e6SYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors -
956fe56b9e6SYuval Mintz cdev->num_hwfns;
957fe56b9e6SYuval Mintz
9582f782278SMintz, Yuval if (!IS_ENABLED(CONFIG_QED_RDMA) ||
959c851a9dcSKalderon, Michal !QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev)))
9600189efb8SYuval Mintz return 0;
9610189efb8SYuval Mintz
96251ff1725SRam Amrani for_each_hwfn(cdev, i)
96351ff1725SRam Amrani num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE);
96451ff1725SRam Amrani
96551ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA,
96651ff1725SRam Amrani "cdev->int_params.fp_msix_cnt=%d num_l2_queues=%d\n",
96751ff1725SRam Amrani cdev->int_params.fp_msix_cnt, num_l2_queues);
96851ff1725SRam Amrani
96951ff1725SRam Amrani if (cdev->int_params.fp_msix_cnt > num_l2_queues) {
97051ff1725SRam Amrani cdev->int_params.rdma_msix_cnt =
97151ff1725SRam Amrani (cdev->int_params.fp_msix_cnt - num_l2_queues)
97251ff1725SRam Amrani / cdev->num_hwfns;
97351ff1725SRam Amrani cdev->int_params.rdma_msix_base =
97451ff1725SRam Amrani cdev->int_params.fp_msix_base + num_l2_queues;
97551ff1725SRam Amrani cdev->int_params.fp_msix_cnt = num_l2_queues;
97651ff1725SRam Amrani } else {
97751ff1725SRam Amrani cdev->int_params.rdma_msix_cnt = 0;
97851ff1725SRam Amrani }
97951ff1725SRam Amrani
98051ff1725SRam Amrani DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n",
98151ff1725SRam Amrani cdev->int_params.rdma_msix_cnt,
98251ff1725SRam Amrani cdev->int_params.rdma_msix_base);
98351ff1725SRam Amrani
984fe56b9e6SYuval Mintz return 0;
985fe56b9e6SYuval Mintz }
986fe56b9e6SYuval Mintz
qed_slowpath_vf_setup_int(struct qed_dev * cdev)9871408cc1fSYuval Mintz static int qed_slowpath_vf_setup_int(struct qed_dev *cdev)
9881408cc1fSYuval Mintz {
9891408cc1fSYuval Mintz int rc;
9901408cc1fSYuval Mintz
9911408cc1fSYuval Mintz memset(&cdev->int_params, 0, sizeof(struct qed_int_params));
9921408cc1fSYuval Mintz cdev->int_params.in.int_mode = QED_INT_MODE_MSIX;
9931408cc1fSYuval Mintz
9941408cc1fSYuval Mintz qed_vf_get_num_rxqs(QED_LEADING_HWFN(cdev),
9951408cc1fSYuval Mintz &cdev->int_params.in.num_vectors);
9961408cc1fSYuval Mintz if (cdev->num_hwfns > 1) {
9971408cc1fSYuval Mintz u8 vectors = 0;
9981408cc1fSYuval Mintz
9991408cc1fSYuval Mintz qed_vf_get_num_rxqs(&cdev->hwfns[1], &vectors);
10001408cc1fSYuval Mintz cdev->int_params.in.num_vectors += vectors;
10011408cc1fSYuval Mintz }
10021408cc1fSYuval Mintz
10031408cc1fSYuval Mintz /* We want a minimum of one fastpath vector per vf hwfn */
10041408cc1fSYuval Mintz cdev->int_params.in.min_msix_cnt = cdev->num_hwfns;
10051408cc1fSYuval Mintz
10061408cc1fSYuval Mintz rc = qed_set_int_mode(cdev, true);
10071408cc1fSYuval Mintz if (rc)
10081408cc1fSYuval Mintz return rc;
10091408cc1fSYuval Mintz
10101408cc1fSYuval Mintz cdev->int_params.fp_msix_base = 0;
10111408cc1fSYuval Mintz cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors;
10121408cc1fSYuval Mintz
10131408cc1fSYuval Mintz return 0;
10141408cc1fSYuval Mintz }
10151408cc1fSYuval Mintz
qed_unzip_data(struct qed_hwfn * p_hwfn,u32 input_len,u8 * input_buf,u32 max_size,u8 * unzip_buf)1016fe56b9e6SYuval Mintz u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len,
1017fe56b9e6SYuval Mintz u8 *input_buf, u32 max_size, u8 *unzip_buf)
1018fe56b9e6SYuval Mintz {
1019fe56b9e6SYuval Mintz int rc;
1020fe56b9e6SYuval Mintz
1021fe56b9e6SYuval Mintz p_hwfn->stream->next_in = input_buf;
1022fe56b9e6SYuval Mintz p_hwfn->stream->avail_in = input_len;
1023fe56b9e6SYuval Mintz p_hwfn->stream->next_out = unzip_buf;
1024fe56b9e6SYuval Mintz p_hwfn->stream->avail_out = max_size;
1025fe56b9e6SYuval Mintz
1026fe56b9e6SYuval Mintz rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS);
1027fe56b9e6SYuval Mintz
1028fe56b9e6SYuval Mintz if (rc != Z_OK) {
1029fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n",
1030fe56b9e6SYuval Mintz rc);
1031fe56b9e6SYuval Mintz return 0;
1032fe56b9e6SYuval Mintz }
1033fe56b9e6SYuval Mintz
1034fe56b9e6SYuval Mintz rc = zlib_inflate(p_hwfn->stream, Z_FINISH);
1035fe56b9e6SYuval Mintz zlib_inflateEnd(p_hwfn->stream);
1036fe56b9e6SYuval Mintz
1037fe56b9e6SYuval Mintz if (rc != Z_OK && rc != Z_STREAM_END) {
1038fe56b9e6SYuval Mintz DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n",
1039fe56b9e6SYuval Mintz p_hwfn->stream->msg, rc);
1040fe56b9e6SYuval Mintz return 0;
1041fe56b9e6SYuval Mintz }
1042fe56b9e6SYuval Mintz
1043fe56b9e6SYuval Mintz return p_hwfn->stream->total_out / 4;
1044fe56b9e6SYuval Mintz }
1045fe56b9e6SYuval Mintz
qed_alloc_stream_mem(struct qed_dev * cdev)1046fe56b9e6SYuval Mintz static int qed_alloc_stream_mem(struct qed_dev *cdev)
1047fe56b9e6SYuval Mintz {
1048fe56b9e6SYuval Mintz int i;
1049fe56b9e6SYuval Mintz void *workspace;
1050fe56b9e6SYuval Mintz
1051fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) {
1052fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
1053fe56b9e6SYuval Mintz
1054fe56b9e6SYuval Mintz p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL);
1055fe56b9e6SYuval Mintz if (!p_hwfn->stream)
1056fe56b9e6SYuval Mintz return -ENOMEM;
1057fe56b9e6SYuval Mintz
1058fe56b9e6SYuval Mintz workspace = vzalloc(zlib_inflate_workspacesize());
1059fe56b9e6SYuval Mintz if (!workspace)
1060fe56b9e6SYuval Mintz return -ENOMEM;
1061fe56b9e6SYuval Mintz p_hwfn->stream->workspace = workspace;
1062fe56b9e6SYuval Mintz }
1063fe56b9e6SYuval Mintz
1064fe56b9e6SYuval Mintz return 0;
1065fe56b9e6SYuval Mintz }
1066fe56b9e6SYuval Mintz
qed_free_stream_mem(struct qed_dev * cdev)1067fe56b9e6SYuval Mintz static void qed_free_stream_mem(struct qed_dev *cdev)
1068fe56b9e6SYuval Mintz {
1069fe56b9e6SYuval Mintz int i;
1070fe56b9e6SYuval Mintz
1071fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) {
1072fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
1073fe56b9e6SYuval Mintz
1074fe56b9e6SYuval Mintz if (!p_hwfn->stream)
1075fe56b9e6SYuval Mintz return;
1076fe56b9e6SYuval Mintz
1077fe56b9e6SYuval Mintz vfree(p_hwfn->stream->workspace);
1078fe56b9e6SYuval Mintz kfree(p_hwfn->stream);
1079fe56b9e6SYuval Mintz }
1080fe56b9e6SYuval Mintz }
1081fe56b9e6SYuval Mintz
qed_update_pf_params(struct qed_dev * cdev,struct qed_pf_params * params)1082fe56b9e6SYuval Mintz static void qed_update_pf_params(struct qed_dev *cdev,
1083fe56b9e6SYuval Mintz struct qed_pf_params *params)
1084fe56b9e6SYuval Mintz {
1085fe56b9e6SYuval Mintz int i;
1086fe56b9e6SYuval Mintz
10875c5f2609SRam Amrani if (IS_ENABLED(CONFIG_QED_RDMA)) {
10880189efb8SYuval Mintz params->rdma_pf_params.num_qps = QED_ROCE_QPS;
10890189efb8SYuval Mintz params->rdma_pf_params.min_dpis = QED_ROCE_DPIS;
109039dbc646SYuval Bason params->rdma_pf_params.num_srqs = QED_RDMA_SRQS;
10910189efb8SYuval Mintz /* divide by 3 the MRs to avoid MF ILT overflow */
10920189efb8SYuval Mintz params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX;
1093fe56b9e6SYuval Mintz }
1094fe56b9e6SYuval Mintz
1095d51e4af5SChopra, Manish if (cdev->num_hwfns > 1 || IS_VF(cdev))
1096d51e4af5SChopra, Manish params->eth_pf_params.num_arfs_filters = 0;
1097d51e4af5SChopra, Manish
1098e1d32acbSMintz, Yuval /* In case we might support RDMA, don't allow qede to be greedy
10995e7baf0fSManish Chopra * with the L2 contexts. Allow for 64 queues [rx, tx cos, xdp]
11005e7baf0fSManish Chopra * per hwfn.
1101e1d32acbSMintz, Yuval */
1102c851a9dcSKalderon, Michal if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) {
1103e1d32acbSMintz, Yuval u16 *num_cons;
1104e1d32acbSMintz, Yuval
1105e1d32acbSMintz, Yuval num_cons = ¶ms->eth_pf_params.num_cons;
11065e7baf0fSManish Chopra *num_cons = min_t(u16, *num_cons, QED_MAX_L2_CONS);
1107e1d32acbSMintz, Yuval }
1108e1d32acbSMintz, Yuval
11095c5f2609SRam Amrani for (i = 0; i < cdev->num_hwfns; i++) {
11105c5f2609SRam Amrani struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
11115c5f2609SRam Amrani
11125c5f2609SRam Amrani p_hwfn->pf_params = *params;
11135c5f2609SRam Amrani }
11145c5f2609SRam Amrani }
11155c5f2609SRam Amrani
1116d4476b8aSDenis Bolotin #define QED_PERIODIC_DB_REC_COUNT 10
1117a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL_MS 100
1118a1b469b8SAriel Elior #define QED_PERIODIC_DB_REC_INTERVAL \
1119a1b469b8SAriel Elior msecs_to_jiffies(QED_PERIODIC_DB_REC_INTERVAL_MS)
1120a1b469b8SAriel Elior
qed_slowpath_delayed_work(struct qed_hwfn * hwfn,enum qed_slowpath_wq_flag wq_flag,unsigned long delay)1121a1b469b8SAriel Elior static int qed_slowpath_delayed_work(struct qed_hwfn *hwfn,
1122a1b469b8SAriel Elior enum qed_slowpath_wq_flag wq_flag,
1123a1b469b8SAriel Elior unsigned long delay)
1124a1b469b8SAriel Elior {
1125a1b469b8SAriel Elior if (!hwfn->slowpath_wq_active)
1126a1b469b8SAriel Elior return -EINVAL;
1127a1b469b8SAriel Elior
1128a1b469b8SAriel Elior /* Memory barrier for setting atomic bit */
1129a1b469b8SAriel Elior smp_mb__before_atomic();
1130a1b469b8SAriel Elior set_bit(wq_flag, &hwfn->slowpath_task_flags);
1131f2a74107SPrabhakar Kushwaha /* Memory barrier after setting atomic bit */
1132a1b469b8SAriel Elior smp_mb__after_atomic();
1133a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, delay);
1134a1b469b8SAriel Elior
1135a1b469b8SAriel Elior return 0;
1136a1b469b8SAriel Elior }
1137a1b469b8SAriel Elior
qed_periodic_db_rec_start(struct qed_hwfn * p_hwfn)1138a1b469b8SAriel Elior void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn)
1139a1b469b8SAriel Elior {
1140a1b469b8SAriel Elior /* Reset periodic Doorbell Recovery counter */
1141a1b469b8SAriel Elior p_hwfn->periodic_db_rec_count = QED_PERIODIC_DB_REC_COUNT;
1142a1b469b8SAriel Elior
1143a1b469b8SAriel Elior /* Don't schedule periodic Doorbell Recovery if already scheduled */
1144a1b469b8SAriel Elior if (test_bit(QED_SLOWPATH_PERIODIC_DB_REC,
1145a1b469b8SAriel Elior &p_hwfn->slowpath_task_flags))
1146a1b469b8SAriel Elior return;
1147a1b469b8SAriel Elior
1148a1b469b8SAriel Elior qed_slowpath_delayed_work(p_hwfn, QED_SLOWPATH_PERIODIC_DB_REC,
1149a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL);
1150a1b469b8SAriel Elior }
1151a1b469b8SAriel Elior
qed_slowpath_wq_stop(struct qed_dev * cdev)115259ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_wq_stop(struct qed_dev *cdev)
115359ccf86fSSudarsana Reddy Kalluru {
11543b85720dSYuval Basson int i;
115559ccf86fSSudarsana Reddy Kalluru
115659ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev))
115759ccf86fSSudarsana Reddy Kalluru return;
115859ccf86fSSudarsana Reddy Kalluru
115959ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) {
116059ccf86fSSudarsana Reddy Kalluru if (!cdev->hwfns[i].slowpath_wq)
116159ccf86fSSudarsana Reddy Kalluru continue;
116259ccf86fSSudarsana Reddy Kalluru
1163a1b469b8SAriel Elior /* Stop queuing new delayed works */
1164a1b469b8SAriel Elior cdev->hwfns[i].slowpath_wq_active = false;
1165a1b469b8SAriel Elior
11663b85720dSYuval Basson cancel_delayed_work(&cdev->hwfns[i].slowpath_task);
116759ccf86fSSudarsana Reddy Kalluru destroy_workqueue(cdev->hwfns[i].slowpath_wq);
116859ccf86fSSudarsana Reddy Kalluru }
116959ccf86fSSudarsana Reddy Kalluru }
117059ccf86fSSudarsana Reddy Kalluru
qed_slowpath_task(struct work_struct * work)117159ccf86fSSudarsana Reddy Kalluru static void qed_slowpath_task(struct work_struct *work)
117259ccf86fSSudarsana Reddy Kalluru {
117359ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn,
117459ccf86fSSudarsana Reddy Kalluru slowpath_task.work);
117559ccf86fSSudarsana Reddy Kalluru struct qed_ptt *ptt = qed_ptt_acquire(hwfn);
117659ccf86fSSudarsana Reddy Kalluru
117759ccf86fSSudarsana Reddy Kalluru if (!ptt) {
1178a1b469b8SAriel Elior if (hwfn->slowpath_wq_active)
1179a1b469b8SAriel Elior queue_delayed_work(hwfn->slowpath_wq,
1180a1b469b8SAriel Elior &hwfn->slowpath_task, 0);
1181a1b469b8SAriel Elior
118259ccf86fSSudarsana Reddy Kalluru return;
118359ccf86fSSudarsana Reddy Kalluru }
118459ccf86fSSudarsana Reddy Kalluru
118559ccf86fSSudarsana Reddy Kalluru if (test_and_clear_bit(QED_SLOWPATH_MFW_TLV_REQ,
118659ccf86fSSudarsana Reddy Kalluru &hwfn->slowpath_task_flags))
118759ccf86fSSudarsana Reddy Kalluru qed_mfw_process_tlv_req(hwfn, ptt);
118859ccf86fSSudarsana Reddy Kalluru
1189a1b469b8SAriel Elior if (test_and_clear_bit(QED_SLOWPATH_PERIODIC_DB_REC,
1190a1b469b8SAriel Elior &hwfn->slowpath_task_flags)) {
1191995c3d49SShai Malin /* skip qed_db_rec_handler during recovery/unload */
1192995c3d49SShai Malin if (hwfn->cdev->recov_in_prog || !hwfn->slowpath_wq_active)
1193995c3d49SShai Malin goto out;
1194995c3d49SShai Malin
1195a1b469b8SAriel Elior qed_db_rec_handler(hwfn, ptt);
1196a1b469b8SAriel Elior if (hwfn->periodic_db_rec_count--)
1197a1b469b8SAriel Elior qed_slowpath_delayed_work(hwfn,
1198a1b469b8SAriel Elior QED_SLOWPATH_PERIODIC_DB_REC,
1199a1b469b8SAriel Elior QED_PERIODIC_DB_REC_INTERVAL);
1200a1b469b8SAriel Elior }
1201a1b469b8SAriel Elior
1202995c3d49SShai Malin out:
120359ccf86fSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
120459ccf86fSSudarsana Reddy Kalluru }
120559ccf86fSSudarsana Reddy Kalluru
qed_slowpath_wq_start(struct qed_dev * cdev)120659ccf86fSSudarsana Reddy Kalluru static int qed_slowpath_wq_start(struct qed_dev *cdev)
120759ccf86fSSudarsana Reddy Kalluru {
120859ccf86fSSudarsana Reddy Kalluru struct qed_hwfn *hwfn;
120959ccf86fSSudarsana Reddy Kalluru int i;
121059ccf86fSSudarsana Reddy Kalluru
121159ccf86fSSudarsana Reddy Kalluru if (IS_VF(cdev))
121259ccf86fSSudarsana Reddy Kalluru return 0;
121359ccf86fSSudarsana Reddy Kalluru
121459ccf86fSSudarsana Reddy Kalluru for_each_hwfn(cdev, i) {
121559ccf86fSSudarsana Reddy Kalluru hwfn = &cdev->hwfns[i];
121659ccf86fSSudarsana Reddy Kalluru
12176541f8eaSArnd Bergmann hwfn->slowpath_wq = alloc_workqueue("slowpath-%02x:%02x.%02x",
12186541f8eaSArnd Bergmann 0, 0, cdev->pdev->bus->number,
12196541f8eaSArnd Bergmann PCI_SLOT(cdev->pdev->devfn),
12206541f8eaSArnd Bergmann hwfn->abs_pf_id);
122159ccf86fSSudarsana Reddy Kalluru
122259ccf86fSSudarsana Reddy Kalluru if (!hwfn->slowpath_wq) {
122359ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n");
122459ccf86fSSudarsana Reddy Kalluru return -ENOMEM;
122559ccf86fSSudarsana Reddy Kalluru }
122659ccf86fSSudarsana Reddy Kalluru
122759ccf86fSSudarsana Reddy Kalluru INIT_DELAYED_WORK(&hwfn->slowpath_task, qed_slowpath_task);
1228a1b469b8SAriel Elior hwfn->slowpath_wq_active = true;
122959ccf86fSSudarsana Reddy Kalluru }
123059ccf86fSSudarsana Reddy Kalluru
123159ccf86fSSudarsana Reddy Kalluru return 0;
123259ccf86fSSudarsana Reddy Kalluru }
123359ccf86fSSudarsana Reddy Kalluru
qed_slowpath_start(struct qed_dev * cdev,struct qed_slowpath_params * params)1234fe56b9e6SYuval Mintz static int qed_slowpath_start(struct qed_dev *cdev,
1235fe56b9e6SYuval Mintz struct qed_slowpath_params *params)
1236fe56b9e6SYuval Mintz {
12375d24bcf1STomer Tayar struct qed_drv_load_params drv_load_params;
1238c0c2d0b4SMintz, Yuval struct qed_hw_init_params hw_init_params;
1239fe56b9e6SYuval Mintz struct qed_mcp_drv_version drv_version;
124019968430SChopra, Manish struct qed_tunnel_info tunn_info;
1241fe56b9e6SYuval Mintz const u8 *data = NULL;
1242fe56b9e6SYuval Mintz struct qed_hwfn *hwfn;
1243c78c70faSSudarsana Reddy Kalluru struct qed_ptt *p_ptt;
124437bff2b9SYuval Mintz int rc = -EINVAL;
124537bff2b9SYuval Mintz
124637bff2b9SYuval Mintz if (qed_iov_wq_start(cdev))
124737bff2b9SYuval Mintz goto err;
1248fe56b9e6SYuval Mintz
124959ccf86fSSudarsana Reddy Kalluru if (qed_slowpath_wq_start(cdev))
125059ccf86fSSudarsana Reddy Kalluru goto err;
125159ccf86fSSudarsana Reddy Kalluru
12521408cc1fSYuval Mintz if (IS_PF(cdev)) {
1253fe56b9e6SYuval Mintz rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME,
1254fe56b9e6SYuval Mintz &cdev->pdev->dev);
1255fe56b9e6SYuval Mintz if (rc) {
1256fe56b9e6SYuval Mintz DP_NOTICE(cdev,
1257fe56b9e6SYuval Mintz "Failed to find fw file - /lib/firmware/%s\n",
1258fe56b9e6SYuval Mintz QED_FW_FILE_NAME);
1259fe56b9e6SYuval Mintz goto err;
1260fe56b9e6SYuval Mintz }
1261c78c70faSSudarsana Reddy Kalluru
1262d51e4af5SChopra, Manish if (cdev->num_hwfns == 1) {
1263d51e4af5SChopra, Manish p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
1264d51e4af5SChopra, Manish if (p_ptt) {
1265d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt = p_ptt;
1266d51e4af5SChopra, Manish } else {
1267d51e4af5SChopra, Manish DP_NOTICE(cdev,
1268d51e4af5SChopra, Manish "Failed to acquire PTT for aRFS\n");
1269a5a14ea7Schongjiapeng rc = -EINVAL;
1270d51e4af5SChopra, Manish goto err;
1271d51e4af5SChopra, Manish }
1272d51e4af5SChopra, Manish }
12731408cc1fSYuval Mintz }
1274fe56b9e6SYuval Mintz
12750e191827SSudarsana Reddy Kalluru cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS;
1276fe56b9e6SYuval Mintz rc = qed_nic_setup(cdev);
1277fe56b9e6SYuval Mintz if (rc)
1278fe56b9e6SYuval Mintz goto err;
1279fe56b9e6SYuval Mintz
12801408cc1fSYuval Mintz if (IS_PF(cdev))
1281fe56b9e6SYuval Mintz rc = qed_slowpath_setup_int(cdev, params->int_mode);
12821408cc1fSYuval Mintz else
12831408cc1fSYuval Mintz rc = qed_slowpath_vf_setup_int(cdev);
1284fe56b9e6SYuval Mintz if (rc)
1285fe56b9e6SYuval Mintz goto err1;
1286fe56b9e6SYuval Mintz
12871408cc1fSYuval Mintz if (IS_PF(cdev)) {
1288fe56b9e6SYuval Mintz /* Allocate stream for unzipping */
1289fe56b9e6SYuval Mintz rc = qed_alloc_stream_mem(cdev);
12902591c280SJoe Perches if (rc)
12918f16bc97SSudarsana Kalluru goto err2;
1292fe56b9e6SYuval Mintz
12938ac1ed79SJoe Perches /* First Dword used to differentiate between various sources */
1294351a4dedSYuval Mintz data = cdev->firmware->data + sizeof(u32);
1295c965db44STomer Tayar
1296c965db44STomer Tayar qed_dbg_pf_init(cdev);
12971408cc1fSYuval Mintz }
1298fe56b9e6SYuval Mintz
12991408cc1fSYuval Mintz /* Start the slowpath */
1300c0c2d0b4SMintz, Yuval memset(&hw_init_params, 0, sizeof(hw_init_params));
130119968430SChopra, Manish memset(&tunn_info, 0, sizeof(tunn_info));
130219968430SChopra, Manish tunn_info.vxlan.b_mode_enabled = true;
130319968430SChopra, Manish tunn_info.l2_gre.b_mode_enabled = true;
130419968430SChopra, Manish tunn_info.ip_gre.b_mode_enabled = true;
130519968430SChopra, Manish tunn_info.l2_geneve.b_mode_enabled = true;
130619968430SChopra, Manish tunn_info.ip_geneve.b_mode_enabled = true;
130719968430SChopra, Manish tunn_info.vxlan.tun_cls = QED_TUNN_CLSS_MAC_VLAN;
130819968430SChopra, Manish tunn_info.l2_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN;
130919968430SChopra, Manish tunn_info.ip_gre.tun_cls = QED_TUNN_CLSS_MAC_VLAN;
131019968430SChopra, Manish tunn_info.l2_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN;
131119968430SChopra, Manish tunn_info.ip_geneve.tun_cls = QED_TUNN_CLSS_MAC_VLAN;
1312c0c2d0b4SMintz, Yuval hw_init_params.p_tunn = &tunn_info;
1313c0c2d0b4SMintz, Yuval hw_init_params.b_hw_start = true;
1314c0c2d0b4SMintz, Yuval hw_init_params.int_mode = cdev->int_params.out.int_mode;
1315c0c2d0b4SMintz, Yuval hw_init_params.allow_npar_tx_switch = true;
1316c0c2d0b4SMintz, Yuval hw_init_params.bin_fw_data = data;
1317c0c2d0b4SMintz, Yuval
13185d24bcf1STomer Tayar memset(&drv_load_params, 0, sizeof(drv_load_params));
13195d24bcf1STomer Tayar drv_load_params.is_crash_kernel = is_kdump_kernel();
13205d24bcf1STomer Tayar drv_load_params.mfw_timeout_val = QED_LOAD_REQ_LOCK_TO_DEFAULT;
13215d24bcf1STomer Tayar drv_load_params.avoid_eng_reset = false;
13225d24bcf1STomer Tayar drv_load_params.override_force_load = QED_OVERRIDE_FORCE_LOAD_NONE;
13235d24bcf1STomer Tayar hw_init_params.p_drv_load_params = &drv_load_params;
13245d24bcf1STomer Tayar
1325c0c2d0b4SMintz, Yuval rc = qed_hw_init(cdev, &hw_init_params);
1326fe56b9e6SYuval Mintz if (rc)
13278c925c44SYuval Mintz goto err2;
1328fe56b9e6SYuval Mintz
1329fe56b9e6SYuval Mintz DP_INFO(cdev,
1330fe56b9e6SYuval Mintz "HW initialization and function start completed successfully\n");
1331fe56b9e6SYuval Mintz
1332eaf3c0c6SChopra, Manish if (IS_PF(cdev)) {
1333eaf3c0c6SChopra, Manish cdev->tunn_feature_mask = (BIT(QED_MODE_VXLAN_TUNN) |
1334eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GENEVE_TUNN) |
1335eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGENEVE_TUNN) |
1336eaf3c0c6SChopra, Manish BIT(QED_MODE_L2GRE_TUNN) |
1337eaf3c0c6SChopra, Manish BIT(QED_MODE_IPGRE_TUNN));
1338eaf3c0c6SChopra, Manish }
1339eaf3c0c6SChopra, Manish
13400a7fb11cSYuval Mintz /* Allocate LL2 interface if needed */
13410a7fb11cSYuval Mintz if (QED_LEADING_HWFN(cdev)->using_ll2) {
13420a7fb11cSYuval Mintz rc = qed_ll2_alloc_if(cdev);
13430a7fb11cSYuval Mintz if (rc)
13440a7fb11cSYuval Mintz goto err3;
13450a7fb11cSYuval Mintz }
13461408cc1fSYuval Mintz if (IS_PF(cdev)) {
1347fe56b9e6SYuval Mintz hwfn = QED_LEADING_HWFN(cdev);
1348fe56b9e6SYuval Mintz drv_version.version = (params->drv_major << 24) |
1349fe56b9e6SYuval Mintz (params->drv_minor << 16) |
1350fe56b9e6SYuval Mintz (params->drv_rev << 8) |
1351fe56b9e6SYuval Mintz (params->drv_eng);
1352f2a74107SPrabhakar Kushwaha strscpy(drv_version.name, params->name,
1353fe56b9e6SYuval Mintz MCP_DRV_VER_STR_SIZE - 4);
1354fe56b9e6SYuval Mintz rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt,
1355fe56b9e6SYuval Mintz &drv_version);
1356fe56b9e6SYuval Mintz if (rc) {
1357fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Failed sending drv version command\n");
1358de0e4fd2SWenwen Wang goto err4;
1359fe56b9e6SYuval Mintz }
13601408cc1fSYuval Mintz }
1361fe56b9e6SYuval Mintz
13628c925c44SYuval Mintz qed_reset_vport_stats(cdev);
13638c925c44SYuval Mintz
1364fe56b9e6SYuval Mintz return 0;
1365fe56b9e6SYuval Mintz
1366de0e4fd2SWenwen Wang err4:
1367de0e4fd2SWenwen Wang qed_ll2_dealloc_if(cdev);
13680a7fb11cSYuval Mintz err3:
13690a7fb11cSYuval Mintz qed_hw_stop(cdev);
1370fe56b9e6SYuval Mintz err2:
13718c925c44SYuval Mintz qed_hw_timers_stop_all(cdev);
13721408cc1fSYuval Mintz if (IS_PF(cdev))
13738c925c44SYuval Mintz qed_slowpath_irq_free(cdev);
13748c925c44SYuval Mintz qed_free_stream_mem(cdev);
1375fe56b9e6SYuval Mintz qed_disable_msix(cdev);
1376fe56b9e6SYuval Mintz err1:
1377fe56b9e6SYuval Mintz qed_resc_free(cdev);
1378fe56b9e6SYuval Mintz err:
13791408cc1fSYuval Mintz if (IS_PF(cdev))
1380fe56b9e6SYuval Mintz release_firmware(cdev->firmware);
1381fe56b9e6SYuval Mintz
1382d51e4af5SChopra, Manish if (IS_PF(cdev) && (cdev->num_hwfns == 1) &&
1383d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt)
1384d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev),
1385d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt);
1386c78c70faSSudarsana Reddy Kalluru
138737bff2b9SYuval Mintz qed_iov_wq_stop(cdev, false);
138837bff2b9SYuval Mintz
138959ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev);
139059ccf86fSSudarsana Reddy Kalluru
1391fe56b9e6SYuval Mintz return rc;
1392fe56b9e6SYuval Mintz }
1393fe56b9e6SYuval Mintz
qed_slowpath_stop(struct qed_dev * cdev)1394fe56b9e6SYuval Mintz static int qed_slowpath_stop(struct qed_dev *cdev)
1395fe56b9e6SYuval Mintz {
1396fe56b9e6SYuval Mintz if (!cdev)
1397fe56b9e6SYuval Mintz return -ENODEV;
1398fe56b9e6SYuval Mintz
139959ccf86fSSudarsana Reddy Kalluru qed_slowpath_wq_stop(cdev);
140059ccf86fSSudarsana Reddy Kalluru
14010a7fb11cSYuval Mintz qed_ll2_dealloc_if(cdev);
14020a7fb11cSYuval Mintz
14031408cc1fSYuval Mintz if (IS_PF(cdev)) {
1404d51e4af5SChopra, Manish if (cdev->num_hwfns == 1)
1405d51e4af5SChopra, Manish qed_ptt_release(QED_LEADING_HWFN(cdev),
1406d51e4af5SChopra, Manish QED_LEADING_HWFN(cdev)->p_arfs_ptt);
1407fe56b9e6SYuval Mintz qed_free_stream_mem(cdev);
1408c5ac9319SYuval Mintz if (IS_QED_ETH_IF(cdev))
14090b55e27dSYuval Mintz qed_sriov_disable(cdev, true);
14105f027d7aSMintz, Yuval }
1411fe56b9e6SYuval Mintz
1412fe56b9e6SYuval Mintz qed_nic_stop(cdev);
14135f027d7aSMintz, Yuval
14145f027d7aSMintz, Yuval if (IS_PF(cdev))
1415fe56b9e6SYuval Mintz qed_slowpath_irq_free(cdev);
1416fe56b9e6SYuval Mintz
1417fe56b9e6SYuval Mintz qed_disable_msix(cdev);
14181226337aSTomer Tayar
14191226337aSTomer Tayar qed_resc_free(cdev);
1420fe56b9e6SYuval Mintz
142137bff2b9SYuval Mintz qed_iov_wq_stop(cdev, true);
142237bff2b9SYuval Mintz
14231408cc1fSYuval Mintz if (IS_PF(cdev))
1424fe56b9e6SYuval Mintz release_firmware(cdev->firmware);
1425fe56b9e6SYuval Mintz
1426fe56b9e6SYuval Mintz return 0;
1427fe56b9e6SYuval Mintz }
1428fe56b9e6SYuval Mintz
qed_set_name(struct qed_dev * cdev,char name[NAME_SIZE])1429712c3cbfSMintz, Yuval static void qed_set_name(struct qed_dev *cdev, char name[NAME_SIZE])
1430fe56b9e6SYuval Mintz {
1431fe56b9e6SYuval Mintz int i;
1432fe56b9e6SYuval Mintz
1433fe56b9e6SYuval Mintz memcpy(cdev->name, name, NAME_SIZE);
1434fe56b9e6SYuval Mintz for_each_hwfn(cdev, i)
1435fe56b9e6SYuval Mintz snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i);
1436fe56b9e6SYuval Mintz }
1437fe56b9e6SYuval Mintz
qed_sb_init(struct qed_dev * cdev,struct qed_sb_info * sb_info,void * sb_virt_addr,dma_addr_t sb_phy_addr,u16 sb_id,enum qed_sb_type type)1438fe56b9e6SYuval Mintz static u32 qed_sb_init(struct qed_dev *cdev,
1439fe56b9e6SYuval Mintz struct qed_sb_info *sb_info,
1440fe56b9e6SYuval Mintz void *sb_virt_addr,
1441fe56b9e6SYuval Mintz dma_addr_t sb_phy_addr, u16 sb_id,
1442fe56b9e6SYuval Mintz enum qed_sb_type type)
1443fe56b9e6SYuval Mintz {
1444fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn;
144585750d74SMintz, Yuval struct qed_ptt *p_ptt;
1446fe56b9e6SYuval Mintz u16 rel_sb_id;
1447fe56b9e6SYuval Mintz u32 rc;
1448fe56b9e6SYuval Mintz
144908eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */
145008eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) {
145108eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns];
145208eb1fb0SMichal Kalderon rel_sb_id = sb_id / cdev->num_hwfns;
145308eb1fb0SMichal Kalderon } else {
145408eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev);
145508eb1fb0SMichal Kalderon rel_sb_id = sb_id;
145608eb1fb0SMichal Kalderon }
1457fe56b9e6SYuval Mintz
1458fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR,
1459fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n",
146008eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id);
1461fe56b9e6SYuval Mintz
146285750d74SMintz, Yuval if (IS_PF(p_hwfn->cdev)) {
146385750d74SMintz, Yuval p_ptt = qed_ptt_acquire(p_hwfn);
146485750d74SMintz, Yuval if (!p_ptt)
146585750d74SMintz, Yuval return -EBUSY;
146685750d74SMintz, Yuval
146785750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, p_ptt, sb_info, sb_virt_addr,
146885750d74SMintz, Yuval sb_phy_addr, rel_sb_id);
146985750d74SMintz, Yuval qed_ptt_release(p_hwfn, p_ptt);
147085750d74SMintz, Yuval } else {
147185750d74SMintz, Yuval rc = qed_int_sb_init(p_hwfn, NULL, sb_info, sb_virt_addr,
147285750d74SMintz, Yuval sb_phy_addr, rel_sb_id);
147385750d74SMintz, Yuval }
1474fe56b9e6SYuval Mintz
1475fe56b9e6SYuval Mintz return rc;
1476fe56b9e6SYuval Mintz }
1477fe56b9e6SYuval Mintz
qed_sb_release(struct qed_dev * cdev,struct qed_sb_info * sb_info,u16 sb_id,enum qed_sb_type type)1478fe56b9e6SYuval Mintz static u32 qed_sb_release(struct qed_dev *cdev,
147908eb1fb0SMichal Kalderon struct qed_sb_info *sb_info,
148008eb1fb0SMichal Kalderon u16 sb_id,
148108eb1fb0SMichal Kalderon enum qed_sb_type type)
1482fe56b9e6SYuval Mintz {
1483fe56b9e6SYuval Mintz struct qed_hwfn *p_hwfn;
1484fe56b9e6SYuval Mintz u16 rel_sb_id;
1485fe56b9e6SYuval Mintz u32 rc;
1486fe56b9e6SYuval Mintz
148708eb1fb0SMichal Kalderon /* RoCE/Storage use a single engine in CMT mode while L2 uses both */
148808eb1fb0SMichal Kalderon if (type == QED_SB_TYPE_L2_QUEUE) {
148908eb1fb0SMichal Kalderon p_hwfn = &cdev->hwfns[sb_id % cdev->num_hwfns];
1490fe56b9e6SYuval Mintz rel_sb_id = sb_id / cdev->num_hwfns;
149108eb1fb0SMichal Kalderon } else {
149208eb1fb0SMichal Kalderon p_hwfn = QED_AFFIN_HWFN(cdev);
149308eb1fb0SMichal Kalderon rel_sb_id = sb_id;
149408eb1fb0SMichal Kalderon }
1495fe56b9e6SYuval Mintz
1496fe56b9e6SYuval Mintz DP_VERBOSE(cdev, NETIF_MSG_INTR,
1497fe56b9e6SYuval Mintz "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n",
149808eb1fb0SMichal Kalderon IS_LEAD_HWFN(p_hwfn) ? 0 : 1, rel_sb_id, sb_id);
1499fe56b9e6SYuval Mintz
1500fe56b9e6SYuval Mintz rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id);
1501fe56b9e6SYuval Mintz
1502fe56b9e6SYuval Mintz return rc;
1503fe56b9e6SYuval Mintz }
1504fe56b9e6SYuval Mintz
qed_can_link_change(struct qed_dev * cdev)1505fe7cd2bfSYuval Mintz static bool qed_can_link_change(struct qed_dev *cdev)
1506fe7cd2bfSYuval Mintz {
1507fe7cd2bfSYuval Mintz return true;
1508fe7cd2bfSYuval Mintz }
1509fe7cd2bfSYuval Mintz
qed_set_ext_speed_params(struct qed_mcp_link_params * link_params,const struct qed_link_params * params)151099785a87SAlexander Lobakin static void qed_set_ext_speed_params(struct qed_mcp_link_params *link_params,
151199785a87SAlexander Lobakin const struct qed_link_params *params)
151299785a87SAlexander Lobakin {
151399785a87SAlexander Lobakin struct qed_mcp_link_speed_params *ext_speed = &link_params->ext_speed;
151499785a87SAlexander Lobakin const struct qed_mfw_speed_map *map;
151599785a87SAlexander Lobakin u32 i;
151699785a87SAlexander Lobakin
151799785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG)
151899785a87SAlexander Lobakin ext_speed->autoneg = !!params->autoneg;
151999785a87SAlexander Lobakin
152099785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
152199785a87SAlexander Lobakin ext_speed->advertised_speeds = 0;
152299785a87SAlexander Lobakin
152399785a87SAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++) {
152499785a87SAlexander Lobakin map = qed_mfw_ext_maps + i;
152599785a87SAlexander Lobakin
152699785a87SAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps))
152799785a87SAlexander Lobakin ext_speed->advertised_speeds |= map->mfw_val;
152899785a87SAlexander Lobakin }
152999785a87SAlexander Lobakin }
153099785a87SAlexander Lobakin
153199785a87SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) {
153299785a87SAlexander Lobakin switch (params->forced_speed) {
153399785a87SAlexander Lobakin case SPEED_1000:
153499785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_1G;
153599785a87SAlexander Lobakin break;
153699785a87SAlexander Lobakin case SPEED_10000:
153799785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_10G;
153899785a87SAlexander Lobakin break;
153999785a87SAlexander Lobakin case SPEED_20000:
154099785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_20G;
154199785a87SAlexander Lobakin break;
154299785a87SAlexander Lobakin case SPEED_25000:
154399785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_25G;
154499785a87SAlexander Lobakin break;
154599785a87SAlexander Lobakin case SPEED_40000:
154699785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_40G;
154799785a87SAlexander Lobakin break;
154899785a87SAlexander Lobakin case SPEED_50000:
154999785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_50G_R |
155099785a87SAlexander Lobakin QED_EXT_SPEED_50G_R2;
155199785a87SAlexander Lobakin break;
155299785a87SAlexander Lobakin case SPEED_100000:
155399785a87SAlexander Lobakin ext_speed->forced_speed = QED_EXT_SPEED_100G_R2 |
155499785a87SAlexander Lobakin QED_EXT_SPEED_100G_R4 |
155599785a87SAlexander Lobakin QED_EXT_SPEED_100G_P4;
155699785a87SAlexander Lobakin break;
155799785a87SAlexander Lobakin default:
155899785a87SAlexander Lobakin break;
155999785a87SAlexander Lobakin }
156099785a87SAlexander Lobakin }
156199785a87SAlexander Lobakin
156299785a87SAlexander Lobakin if (!(params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG))
156399785a87SAlexander Lobakin return;
156499785a87SAlexander Lobakin
156599785a87SAlexander Lobakin switch (params->forced_speed) {
156699785a87SAlexander Lobakin case SPEED_25000:
156799785a87SAlexander Lobakin switch (params->fec) {
156899785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE:
156999785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_NONE;
157099785a87SAlexander Lobakin break;
157199785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE:
157299785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_BASE_R;
157399785a87SAlexander Lobakin break;
157499785a87SAlexander Lobakin case FEC_FORCE_MODE_RS:
157599785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528;
157699785a87SAlexander Lobakin break;
157799785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO:
157899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528 |
157999785a87SAlexander Lobakin ETH_EXT_FEC_25G_BASE_R |
158099785a87SAlexander Lobakin ETH_EXT_FEC_25G_NONE;
158199785a87SAlexander Lobakin break;
158299785a87SAlexander Lobakin default:
158399785a87SAlexander Lobakin break;
158499785a87SAlexander Lobakin }
158599785a87SAlexander Lobakin
158699785a87SAlexander Lobakin break;
158799785a87SAlexander Lobakin case SPEED_40000:
158899785a87SAlexander Lobakin switch (params->fec) {
158999785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE:
159099785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_NONE;
159199785a87SAlexander Lobakin break;
159299785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE:
159399785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R;
159499785a87SAlexander Lobakin break;
159599785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO:
159699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R |
159799785a87SAlexander Lobakin ETH_EXT_FEC_40G_NONE;
159899785a87SAlexander Lobakin break;
159999785a87SAlexander Lobakin default:
160099785a87SAlexander Lobakin break;
160199785a87SAlexander Lobakin }
160299785a87SAlexander Lobakin
160399785a87SAlexander Lobakin break;
160499785a87SAlexander Lobakin case SPEED_50000:
160599785a87SAlexander Lobakin switch (params->fec) {
160699785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE:
160799785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_NONE;
160899785a87SAlexander Lobakin break;
160999785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE:
161099785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_BASE_R;
161199785a87SAlexander Lobakin break;
161299785a87SAlexander Lobakin case FEC_FORCE_MODE_RS:
161399785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528;
161499785a87SAlexander Lobakin break;
161599785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO:
161699785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528 |
161799785a87SAlexander Lobakin ETH_EXT_FEC_50G_BASE_R |
161899785a87SAlexander Lobakin ETH_EXT_FEC_50G_NONE;
161999785a87SAlexander Lobakin break;
162099785a87SAlexander Lobakin default:
162199785a87SAlexander Lobakin break;
162299785a87SAlexander Lobakin }
162399785a87SAlexander Lobakin
162499785a87SAlexander Lobakin break;
162599785a87SAlexander Lobakin case SPEED_100000:
162699785a87SAlexander Lobakin switch (params->fec) {
162799785a87SAlexander Lobakin case FEC_FORCE_MODE_NONE:
162899785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_NONE;
162999785a87SAlexander Lobakin break;
163099785a87SAlexander Lobakin case FEC_FORCE_MODE_FIRECODE:
163199785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_BASE_R;
163299785a87SAlexander Lobakin break;
163399785a87SAlexander Lobakin case FEC_FORCE_MODE_RS:
163499785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528;
163599785a87SAlexander Lobakin break;
163699785a87SAlexander Lobakin case FEC_FORCE_MODE_AUTO:
163799785a87SAlexander Lobakin link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528 |
163899785a87SAlexander Lobakin ETH_EXT_FEC_100G_BASE_R |
163999785a87SAlexander Lobakin ETH_EXT_FEC_100G_NONE;
164099785a87SAlexander Lobakin break;
164199785a87SAlexander Lobakin default:
164299785a87SAlexander Lobakin break;
164399785a87SAlexander Lobakin }
164499785a87SAlexander Lobakin
164599785a87SAlexander Lobakin break;
164699785a87SAlexander Lobakin default:
164799785a87SAlexander Lobakin break;
164899785a87SAlexander Lobakin }
164999785a87SAlexander Lobakin }
165099785a87SAlexander Lobakin
qed_set_link(struct qed_dev * cdev,struct qed_link_params * params)1651351a4dedSYuval Mintz static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
1652cc875c2eSYuval Mintz {
1653cc875c2eSYuval Mintz struct qed_mcp_link_params *link_params;
1654097818fcSAlexander Lobakin struct qed_mcp_link_speed_params *speed;
1655097818fcSAlexander Lobakin const struct qed_mfw_speed_map *map;
1656bdb5d8ecSAlexander Lobakin struct qed_hwfn *hwfn;
1657cc875c2eSYuval Mintz struct qed_ptt *ptt;
1658cc875c2eSYuval Mintz int rc;
1659097818fcSAlexander Lobakin u32 i;
1660cc875c2eSYuval Mintz
1661cc875c2eSYuval Mintz if (!cdev)
1662cc875c2eSYuval Mintz return -ENODEV;
1663cc875c2eSYuval Mintz
1664cc875c2eSYuval Mintz /* The link should be set only once per PF */
1665cc875c2eSYuval Mintz hwfn = &cdev->hwfns[0];
1666cc875c2eSYuval Mintz
166765ed2ffdSMintz, Yuval /* When VF wants to set link, force it to read the bulletin instead.
166865ed2ffdSMintz, Yuval * This mimics the PF behavior, where a noitification [both immediate
166965ed2ffdSMintz, Yuval * and possible later] would be generated when changing properties.
167065ed2ffdSMintz, Yuval */
167165ed2ffdSMintz, Yuval if (IS_VF(cdev)) {
167265ed2ffdSMintz, Yuval qed_schedule_iov(hwfn, QED_IOV_WQ_VF_FORCE_LINK_QUERY_FLAG);
167365ed2ffdSMintz, Yuval return 0;
167465ed2ffdSMintz, Yuval }
167565ed2ffdSMintz, Yuval
1676cc875c2eSYuval Mintz ptt = qed_ptt_acquire(hwfn);
1677cc875c2eSYuval Mintz if (!ptt)
1678cc875c2eSYuval Mintz return -EBUSY;
1679cc875c2eSYuval Mintz
1680cc875c2eSYuval Mintz link_params = qed_mcp_get_link_params(hwfn);
1681bdb5d8ecSAlexander Lobakin if (!link_params)
1682bdb5d8ecSAlexander Lobakin return -ENODATA;
1683bdb5d8ecSAlexander Lobakin
1684097818fcSAlexander Lobakin speed = &link_params->speed;
1685097818fcSAlexander Lobakin
1686cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG)
1687097818fcSAlexander Lobakin speed->autoneg = !!params->autoneg;
1688bdb5d8ecSAlexander Lobakin
1689cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
1690097818fcSAlexander Lobakin speed->advertised_speeds = 0;
1691bdb5d8ecSAlexander Lobakin
1692097818fcSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++) {
1693097818fcSAlexander Lobakin map = qed_mfw_legacy_maps + i;
1694bdb5d8ecSAlexander Lobakin
1695097818fcSAlexander Lobakin if (linkmode_intersects(params->adv_speeds, map->caps))
1696097818fcSAlexander Lobakin speed->advertised_speeds |= map->mfw_val;
1697097818fcSAlexander Lobakin }
1698cc875c2eSYuval Mintz }
1699bdb5d8ecSAlexander Lobakin
1700cc875c2eSYuval Mintz if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED)
1701097818fcSAlexander Lobakin speed->forced_speed = params->forced_speed;
1702097818fcSAlexander Lobakin
170399785a87SAlexander Lobakin if (qed_mcp_is_ext_speed_supported(hwfn))
170499785a87SAlexander Lobakin qed_set_ext_speed_params(link_params, params);
170599785a87SAlexander Lobakin
1706a43f235fSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) {
1707a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
1708a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = true;
1709a43f235fSSudarsana Reddy Kalluru else
1710a43f235fSSudarsana Reddy Kalluru link_params->pause.autoneg = false;
1711a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_RX_ENABLE)
1712a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = true;
1713a43f235fSSudarsana Reddy Kalluru else
1714a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_rx = false;
1715a43f235fSSudarsana Reddy Kalluru if (params->pause_config & QED_LINK_PAUSE_TX_ENABLE)
1716a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = true;
1717a43f235fSSudarsana Reddy Kalluru else
1718a43f235fSSudarsana Reddy Kalluru link_params->pause.forced_tx = false;
1719a43f235fSSudarsana Reddy Kalluru }
1720097818fcSAlexander Lobakin
172103dc76caSSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) {
172203dc76caSSudarsana Reddy Kalluru switch (params->loopback_mode) {
172303dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_INT_PHY:
1724351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_INT_PHY;
172503dc76caSSudarsana Reddy Kalluru break;
172603dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT_PHY:
1727351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT_PHY;
172803dc76caSSudarsana Reddy Kalluru break;
172903dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_EXT:
1730351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_EXT;
173103dc76caSSudarsana Reddy Kalluru break;
173203dc76caSSudarsana Reddy Kalluru case QED_LINK_LOOPBACK_MAC:
1733351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_MAC;
173403dc76caSSudarsana Reddy Kalluru break;
173598e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_0123:
173698e675ecSAlexander Lobakin link_params->loopback_mode =
173798e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_0123;
173898e675ecSAlexander Lobakin break;
173998e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_CNIG_AH_ONLY_2301:
174098e675ecSAlexander Lobakin link_params->loopback_mode =
174198e675ecSAlexander Lobakin ETH_LOOPBACK_CNIG_AH_ONLY_2301;
174298e675ecSAlexander Lobakin break;
174398e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_PCS_AH_ONLY:
174498e675ecSAlexander Lobakin link_params->loopback_mode = ETH_LOOPBACK_PCS_AH_ONLY;
174598e675ecSAlexander Lobakin break;
174698e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_REVERSE_MAC_AH_ONLY:
174798e675ecSAlexander Lobakin link_params->loopback_mode =
174898e675ecSAlexander Lobakin ETH_LOOPBACK_REVERSE_MAC_AH_ONLY;
174998e675ecSAlexander Lobakin break;
175098e675ecSAlexander Lobakin case QED_LINK_LOOPBACK_INT_PHY_FEA_AH_ONLY:
175198e675ecSAlexander Lobakin link_params->loopback_mode =
175298e675ecSAlexander Lobakin ETH_LOOPBACK_INT_PHY_FEA_AH_ONLY;
175398e675ecSAlexander Lobakin break;
175403dc76caSSudarsana Reddy Kalluru default:
1755351a4dedSYuval Mintz link_params->loopback_mode = ETH_LOOPBACK_NONE;
175603dc76caSSudarsana Reddy Kalluru break;
175703dc76caSSudarsana Reddy Kalluru }
175803dc76caSSudarsana Reddy Kalluru }
1759cc875c2eSYuval Mintz
1760645874e5SSudarsana Reddy Kalluru if (params->override_flags & QED_LINK_OVERRIDE_EEE_CONFIG)
1761645874e5SSudarsana Reddy Kalluru memcpy(&link_params->eee, ¶ms->eee,
1762645874e5SSudarsana Reddy Kalluru sizeof(link_params->eee));
1763645874e5SSudarsana Reddy Kalluru
1764ae7e6937SAlexander Lobakin if (params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG)
1765ae7e6937SAlexander Lobakin link_params->fec = params->fec;
1766ae7e6937SAlexander Lobakin
1767cc875c2eSYuval Mintz rc = qed_mcp_set_link(hwfn, ptt, params->link_up);
1768cc875c2eSYuval Mintz
1769cc875c2eSYuval Mintz qed_ptt_release(hwfn, ptt);
1770cc875c2eSYuval Mintz
1771cc875c2eSYuval Mintz return rc;
1772cc875c2eSYuval Mintz }
1773cc875c2eSYuval Mintz
qed_get_port_type(u32 media_type)1774cc875c2eSYuval Mintz static int qed_get_port_type(u32 media_type)
1775cc875c2eSYuval Mintz {
1776cc875c2eSYuval Mintz int port_type;
1777cc875c2eSYuval Mintz
1778cc875c2eSYuval Mintz switch (media_type) {
1779cc875c2eSYuval Mintz case MEDIA_SFPP_10G_FIBER:
1780cc875c2eSYuval Mintz case MEDIA_SFP_1G_FIBER:
1781cc875c2eSYuval Mintz case MEDIA_XFP_FIBER:
1782b639f197SYuval Mintz case MEDIA_MODULE_FIBER:
1783cc875c2eSYuval Mintz port_type = PORT_FIBRE;
1784cc875c2eSYuval Mintz break;
1785cc875c2eSYuval Mintz case MEDIA_DA_TWINAX:
1786cc875c2eSYuval Mintz port_type = PORT_DA;
1787cc875c2eSYuval Mintz break;
1788cc875c2eSYuval Mintz case MEDIA_BASE_T:
1789cc875c2eSYuval Mintz port_type = PORT_TP;
1790cc875c2eSYuval Mintz break;
179199785a87SAlexander Lobakin case MEDIA_KR:
1792cc875c2eSYuval Mintz case MEDIA_NOT_PRESENT:
1793cc875c2eSYuval Mintz port_type = PORT_NONE;
1794cc875c2eSYuval Mintz break;
1795cc875c2eSYuval Mintz case MEDIA_UNSPECIFIED:
1796cc875c2eSYuval Mintz default:
1797cc875c2eSYuval Mintz port_type = PORT_OTHER;
1798cc875c2eSYuval Mintz break;
1799cc875c2eSYuval Mintz }
1800cc875c2eSYuval Mintz return port_type;
1801cc875c2eSYuval Mintz }
1802cc875c2eSYuval Mintz
qed_get_link_data(struct qed_hwfn * hwfn,struct qed_mcp_link_params * params,struct qed_mcp_link_state * link,struct qed_mcp_link_capabilities * link_caps)180314b84e86SArnd Bergmann static int qed_get_link_data(struct qed_hwfn *hwfn,
180414b84e86SArnd Bergmann struct qed_mcp_link_params *params,
180514b84e86SArnd Bergmann struct qed_mcp_link_state *link,
180614b84e86SArnd Bergmann struct qed_mcp_link_capabilities *link_caps)
180714b84e86SArnd Bergmann {
180814b84e86SArnd Bergmann void *p;
180914b84e86SArnd Bergmann
181014b84e86SArnd Bergmann if (!IS_PF(hwfn->cdev)) {
181114b84e86SArnd Bergmann qed_vf_get_link_params(hwfn, params);
181214b84e86SArnd Bergmann qed_vf_get_link_state(hwfn, link);
181314b84e86SArnd Bergmann qed_vf_get_link_caps(hwfn, link_caps);
181414b84e86SArnd Bergmann
181514b84e86SArnd Bergmann return 0;
181614b84e86SArnd Bergmann }
181714b84e86SArnd Bergmann
181814b84e86SArnd Bergmann p = qed_mcp_get_link_params(hwfn);
181914b84e86SArnd Bergmann if (!p)
182014b84e86SArnd Bergmann return -ENXIO;
182114b84e86SArnd Bergmann memcpy(params, p, sizeof(*params));
182214b84e86SArnd Bergmann
182314b84e86SArnd Bergmann p = qed_mcp_get_link_state(hwfn);
182414b84e86SArnd Bergmann if (!p)
182514b84e86SArnd Bergmann return -ENXIO;
182614b84e86SArnd Bergmann memcpy(link, p, sizeof(*link));
182714b84e86SArnd Bergmann
182814b84e86SArnd Bergmann p = qed_mcp_get_link_capabilities(hwfn);
182914b84e86SArnd Bergmann if (!p)
183014b84e86SArnd Bergmann return -ENXIO;
183114b84e86SArnd Bergmann memcpy(link_caps, p, sizeof(*link_caps));
183214b84e86SArnd Bergmann
183314b84e86SArnd Bergmann return 0;
183414b84e86SArnd Bergmann }
183514b84e86SArnd Bergmann
qed_fill_link_capability(struct qed_hwfn * hwfn,struct qed_ptt * ptt,u32 capability,unsigned long * if_caps)1836c56a8be7SRahul Verma static void qed_fill_link_capability(struct qed_hwfn *hwfn,
1837c56a8be7SRahul Verma struct qed_ptt *ptt, u32 capability,
1838bdb5d8ecSAlexander Lobakin unsigned long *if_caps)
1839c56a8be7SRahul Verma {
1840c56a8be7SRahul Verma u32 media_type, tcvr_state, tcvr_type;
1841c56a8be7SRahul Verma u32 speed_mask, board_cfg;
1842c56a8be7SRahul Verma
1843c56a8be7SRahul Verma if (qed_mcp_get_media_type(hwfn, ptt, &media_type))
1844c56a8be7SRahul Verma media_type = MEDIA_UNSPECIFIED;
1845c56a8be7SRahul Verma
1846c56a8be7SRahul Verma if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type))
1847c56a8be7SRahul Verma tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED;
1848c56a8be7SRahul Verma
1849c56a8be7SRahul Verma if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask))
1850c56a8be7SRahul Verma speed_mask = 0xFFFFFFFF;
1851c56a8be7SRahul Verma
1852c56a8be7SRahul Verma if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg))
1853c56a8be7SRahul Verma board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
1854c56a8be7SRahul Verma
1855c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV,
1856c56a8be7SRahul Verma "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x speed_mask = 0x%x board_cfg = 0x%x\n",
1857c56a8be7SRahul Verma media_type, tcvr_state, tcvr_type, speed_mask, board_cfg);
1858c56a8be7SRahul Verma
1859c56a8be7SRahul Verma switch (media_type) {
1860c56a8be7SRahul Verma case MEDIA_DA_TWINAX:
1861bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE);
1862bdb5d8ecSAlexander Lobakin
1863c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
1864bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full);
1865bdb5d8ecSAlexander Lobakin
1866c56a8be7SRahul Verma /* For DAC media multiple speed capabilities are supported */
18679228b7c1SAlexander Lobakin capability |= speed_mask;
18689228b7c1SAlexander Lobakin
1869c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
1870bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full);
1871c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
1872bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseCR_Full);
18739228b7c1SAlexander Lobakin
1874c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
18759228b7c1SAlexander Lobakin switch (tcvr_type) {
18769228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_CR4:
18779228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
18789228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
1879bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseCR4_Full);
18809228b7c1SAlexander Lobakin break;
18819228b7c1SAlexander Lobakin default:
18829228b7c1SAlexander Lobakin break;
18839228b7c1SAlexander Lobakin }
18849228b7c1SAlexander Lobakin
1885c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
1886bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseCR_Full);
1887c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
1888bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseCR2_Full);
18899228b7c1SAlexander Lobakin
1890c56a8be7SRahul Verma if (capability &
1891c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
18929228b7c1SAlexander Lobakin switch (tcvr_type) {
18939228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_CR4:
18949228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
1895bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseCR4_Full);
18969228b7c1SAlexander Lobakin break;
18979228b7c1SAlexander Lobakin default:
18989228b7c1SAlexander Lobakin break;
18999228b7c1SAlexander Lobakin }
1900bdb5d8ecSAlexander Lobakin
1901c56a8be7SRahul Verma break;
1902c56a8be7SRahul Verma case MEDIA_BASE_T:
1903bdb5d8ecSAlexander Lobakin phylink_set(if_caps, TP);
1904bdb5d8ecSAlexander Lobakin
1905c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) {
1906c56a8be7SRahul Verma if (capability &
1907bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
1908bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full);
1909c56a8be7SRahul Verma if (capability &
1910bdb5d8ecSAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
1911bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full);
1912c56a8be7SRahul Verma }
1913bdb5d8ecSAlexander Lobakin
1914c56a8be7SRahul Verma if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) {
1915bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE);
1916bdb5d8ecSAlexander Lobakin
19179228b7c1SAlexander Lobakin switch (tcvr_type) {
19189228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1000BASET:
1919bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseT_Full);
19209228b7c1SAlexander Lobakin break;
19219228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_BASET:
1922bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseT_Full);
19239228b7c1SAlexander Lobakin break;
19249228b7c1SAlexander Lobakin default:
19259228b7c1SAlexander Lobakin break;
19269228b7c1SAlexander Lobakin }
1927c56a8be7SRahul Verma }
1928bdb5d8ecSAlexander Lobakin
1929c56a8be7SRahul Verma break;
1930c56a8be7SRahul Verma case MEDIA_SFP_1G_FIBER:
1931c56a8be7SRahul Verma case MEDIA_SFPP_10G_FIBER:
1932c56a8be7SRahul Verma case MEDIA_XFP_FIBER:
1933c56a8be7SRahul Verma case MEDIA_MODULE_FIBER:
1934bdb5d8ecSAlexander Lobakin phylink_set(if_caps, FIBRE);
19359228b7c1SAlexander Lobakin capability |= speed_mask;
1936bdb5d8ecSAlexander Lobakin
19379228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
19389228b7c1SAlexander Lobakin switch (tcvr_type) {
19399228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_LX:
19409228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_1G_SX:
19419228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
19429228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
1943bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full);
19449228b7c1SAlexander Lobakin break;
19459228b7c1SAlexander Lobakin default:
19469228b7c1SAlexander Lobakin break;
1947c56a8be7SRahul Verma }
1948bdb5d8ecSAlexander Lobakin
19499228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
19509228b7c1SAlexander Lobakin switch (tcvr_type) {
19519228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_SR:
19529228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
19539228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
19549228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
1955bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseSR_Full);
19569228b7c1SAlexander Lobakin break;
19579228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LR:
19589228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
19599228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR:
19609228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
1961bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLR_Full);
19629228b7c1SAlexander Lobakin break;
19639228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_LRM:
1964bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseLRM_Full);
19659228b7c1SAlexander Lobakin break;
19669228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_10G_ER:
1967bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseR_FEC);
19689228b7c1SAlexander Lobakin break;
19699228b7c1SAlexander Lobakin default:
19709228b7c1SAlexander Lobakin break;
1971c56a8be7SRahul Verma }
1972bdb5d8ecSAlexander Lobakin
1973c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
1974bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full);
1975bdb5d8ecSAlexander Lobakin
19769228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
19779228b7c1SAlexander Lobakin switch (tcvr_type) {
19789228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_25G_SR:
19799228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
1980bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseSR_Full);
19819228b7c1SAlexander Lobakin break;
19829228b7c1SAlexander Lobakin default:
19839228b7c1SAlexander Lobakin break;
1984c56a8be7SRahul Verma }
1985bdb5d8ecSAlexander Lobakin
19869228b7c1SAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
19879228b7c1SAlexander Lobakin switch (tcvr_type) {
19889228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_LR4:
19899228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
19909228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
1991bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseLR4_Full);
19929228b7c1SAlexander Lobakin break;
19939228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_40G_SR4:
19949228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
19959228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
1996bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseSR4_Full);
19979228b7c1SAlexander Lobakin break;
19989228b7c1SAlexander Lobakin default:
19999228b7c1SAlexander Lobakin break;
2000c56a8be7SRahul Verma }
2001bdb5d8ecSAlexander Lobakin
2002bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
2003bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full);
2004bdb5d8ecSAlexander Lobakin
2005c56a8be7SRahul Verma if (capability &
20069228b7c1SAlexander Lobakin NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
20079228b7c1SAlexander Lobakin switch (tcvr_type) {
20089228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_100G_SR4:
20099228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
2010bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseSR4_Full);
20119228b7c1SAlexander Lobakin break;
20129228b7c1SAlexander Lobakin case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
20139228b7c1SAlexander Lobakin phylink_set(if_caps, 100000baseLR4_ER4_Full);
20149228b7c1SAlexander Lobakin break;
20159228b7c1SAlexander Lobakin default:
20169228b7c1SAlexander Lobakin break;
2017c56a8be7SRahul Verma }
2018c56a8be7SRahul Verma
2019c56a8be7SRahul Verma break;
2020c56a8be7SRahul Verma case MEDIA_KR:
2021bdb5d8ecSAlexander Lobakin phylink_set(if_caps, Backplane);
2022bdb5d8ecSAlexander Lobakin
2023c56a8be7SRahul Verma if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
2024bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 20000baseKR2_Full);
2025bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
2026bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 1000baseKX_Full);
2027bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
2028bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 10000baseKR_Full);
2029bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
2030bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 25000baseKR_Full);
2031bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
2032bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 40000baseKR4_Full);
2033bdb5d8ecSAlexander Lobakin if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
2034bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 50000baseKR2_Full);
2035c56a8be7SRahul Verma if (capability &
2036c56a8be7SRahul Verma NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
2037bdb5d8ecSAlexander Lobakin phylink_set(if_caps, 100000baseKR4_Full);
2038bdb5d8ecSAlexander Lobakin
2039c56a8be7SRahul Verma break;
2040c56a8be7SRahul Verma case MEDIA_UNSPECIFIED:
2041c56a8be7SRahul Verma case MEDIA_NOT_PRESENT:
20429228b7c1SAlexander Lobakin default:
2043c56a8be7SRahul Verma DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG,
2044c56a8be7SRahul Verma "Unknown media and transceiver type;\n");
2045c56a8be7SRahul Verma break;
2046c56a8be7SRahul Verma }
2047c56a8be7SRahul Verma }
2048c56a8be7SRahul Verma
qed_lp_caps_to_speed_mask(u32 caps,u32 * speed_mask)20493c41486eSAlexander Lobakin static void qed_lp_caps_to_speed_mask(u32 caps, u32 *speed_mask)
20503c41486eSAlexander Lobakin {
20513c41486eSAlexander Lobakin *speed_mask = 0;
20523c41486eSAlexander Lobakin
20533c41486eSAlexander Lobakin if (caps &
20543c41486eSAlexander Lobakin (QED_LINK_PARTNER_SPEED_1G_FD | QED_LINK_PARTNER_SPEED_1G_HD))
20553c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
20563c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_10G)
20573c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
20583c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_20G)
20593c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G;
20603c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_25G)
20613c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
20623c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_40G)
20633c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
20643c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_50G)
20653c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
20663c41486eSAlexander Lobakin if (caps & QED_LINK_PARTNER_SPEED_100G)
20673c41486eSAlexander Lobakin *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
20683c41486eSAlexander Lobakin }
20693c41486eSAlexander Lobakin
qed_fill_link(struct qed_hwfn * hwfn,struct qed_ptt * ptt,struct qed_link_output * if_link)2070cc875c2eSYuval Mintz static void qed_fill_link(struct qed_hwfn *hwfn,
2071706d0891SRahul Verma struct qed_ptt *ptt,
2072cc875c2eSYuval Mintz struct qed_link_output *if_link)
2073cc875c2eSYuval Mintz {
2074c56a8be7SRahul Verma struct qed_mcp_link_capabilities link_caps;
2075cc875c2eSYuval Mintz struct qed_mcp_link_params params;
2076cc875c2eSYuval Mintz struct qed_mcp_link_state link;
20773c41486eSAlexander Lobakin u32 media_type, speed_mask;
2078cc875c2eSYuval Mintz
2079cc875c2eSYuval Mintz memset(if_link, 0, sizeof(*if_link));
2080cc875c2eSYuval Mintz
2081cc875c2eSYuval Mintz /* Prepare source inputs */
208214b84e86SArnd Bergmann if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) {
208314b84e86SArnd Bergmann dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n");
208414b84e86SArnd Bergmann return;
20851408cc1fSYuval Mintz }
2086cc875c2eSYuval Mintz
2087cc875c2eSYuval Mintz /* Set the link parameters to pass to protocol driver */
2088cc875c2eSYuval Mintz if (link.link_up)
2089cc875c2eSYuval Mintz if_link->link_up = true;
2090cc875c2eSYuval Mintz
209199785a87SAlexander Lobakin if (IS_PF(hwfn->cdev) && qed_mcp_is_ext_speed_supported(hwfn)) {
209299785a87SAlexander Lobakin if (link_caps.default_ext_autoneg)
209399785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg);
209499785a87SAlexander Lobakin
209599785a87SAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps);
209699785a87SAlexander Lobakin
209799785a87SAlexander Lobakin if (params.ext_speed.autoneg)
209899785a87SAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg);
209999785a87SAlexander Lobakin else
210099785a87SAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg);
210199785a87SAlexander Lobakin
210299785a87SAlexander Lobakin qed_fill_link_capability(hwfn, ptt,
210399785a87SAlexander Lobakin params.ext_speed.advertised_speeds,
210499785a87SAlexander Lobakin if_link->advertised_caps);
210599785a87SAlexander Lobakin } else {
210634f9199cSsudarsana.kalluru@cavium.com if (link_caps.default_speed_autoneg)
2107bdb5d8ecSAlexander Lobakin phylink_set(if_link->supported_caps, Autoneg);
2108cc875c2eSYuval Mintz
2109bdb5d8ecSAlexander Lobakin linkmode_copy(if_link->advertised_caps, if_link->supported_caps);
2110bdb5d8ecSAlexander Lobakin
211134f9199cSsudarsana.kalluru@cavium.com if (params.speed.autoneg)
2112bdb5d8ecSAlexander Lobakin phylink_set(if_link->advertised_caps, Autoneg);
211334f9199cSsudarsana.kalluru@cavium.com else
2114bdb5d8ecSAlexander Lobakin phylink_clear(if_link->advertised_caps, Autoneg);
211599785a87SAlexander Lobakin }
211699785a87SAlexander Lobakin
211799785a87SAlexander Lobakin if (params.pause.autoneg ||
211899785a87SAlexander Lobakin (params.pause.forced_rx && params.pause.forced_tx))
211999785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Asym_Pause);
212099785a87SAlexander Lobakin if (params.pause.autoneg || params.pause.forced_rx ||
212199785a87SAlexander Lobakin params.pause.forced_tx)
212299785a87SAlexander Lobakin phylink_set(if_link->supported_caps, Pause);
2123cc875c2eSYuval Mintz
2124ae7e6937SAlexander Lobakin if_link->sup_fec = link_caps.fec_default;
2125ae7e6937SAlexander Lobakin if_link->active_fec = params.fec;
2126ae7e6937SAlexander Lobakin
2127c56a8be7SRahul Verma /* Fill link advertised capability */
2128c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds,
2129bdb5d8ecSAlexander Lobakin if_link->advertised_caps);
21303c41486eSAlexander Lobakin
2131c56a8be7SRahul Verma /* Fill link supported capability */
2132c56a8be7SRahul Verma qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities,
2133bdb5d8ecSAlexander Lobakin if_link->supported_caps);
2134cc875c2eSYuval Mintz
21353c41486eSAlexander Lobakin /* Fill partner advertised capability */
21363c41486eSAlexander Lobakin qed_lp_caps_to_speed_mask(link.partner_adv_speed, &speed_mask);
21373c41486eSAlexander Lobakin qed_fill_link_capability(hwfn, ptt, speed_mask, if_link->lp_caps);
21383c41486eSAlexander Lobakin
2139cc875c2eSYuval Mintz if (link.link_up)
2140cc875c2eSYuval Mintz if_link->speed = link.speed;
2141cc875c2eSYuval Mintz
2142cc875c2eSYuval Mintz /* TODO - fill duplex properly */
2143cc875c2eSYuval Mintz if_link->duplex = DUPLEX_FULL;
2144706d0891SRahul Verma qed_mcp_get_media_type(hwfn, ptt, &media_type);
2145cc875c2eSYuval Mintz if_link->port = qed_get_port_type(media_type);
2146cc875c2eSYuval Mintz
2147cc875c2eSYuval Mintz if_link->autoneg = params.speed.autoneg;
2148cc875c2eSYuval Mintz
2149cc875c2eSYuval Mintz if (params.pause.autoneg)
2150cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
2151cc875c2eSYuval Mintz if (params.pause.forced_rx)
2152cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE;
2153cc875c2eSYuval Mintz if (params.pause.forced_tx)
2154cc875c2eSYuval Mintz if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
2155cc875c2eSYuval Mintz
2156cc875c2eSYuval Mintz if (link.an_complete)
2157bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Autoneg);
2158cc875c2eSYuval Mintz if (link.partner_adv_pause)
2159bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Pause);
2160cc875c2eSYuval Mintz if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE ||
2161cc875c2eSYuval Mintz link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE)
2162bdb5d8ecSAlexander Lobakin phylink_set(if_link->lp_caps, Asym_Pause);
2163645874e5SSudarsana Reddy Kalluru
2164645874e5SSudarsana Reddy Kalluru if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) {
2165645874e5SSudarsana Reddy Kalluru if_link->eee_supported = false;
2166645874e5SSudarsana Reddy Kalluru } else {
2167645874e5SSudarsana Reddy Kalluru if_link->eee_supported = true;
2168645874e5SSudarsana Reddy Kalluru if_link->eee_active = link.eee_active;
2169645874e5SSudarsana Reddy Kalluru if_link->sup_caps = link_caps.eee_speed_caps;
2170645874e5SSudarsana Reddy Kalluru /* MFW clears adv_caps on eee disable; use configured value */
2171645874e5SSudarsana Reddy Kalluru if_link->eee.adv_caps = link.eee_adv_caps ? link.eee_adv_caps :
2172645874e5SSudarsana Reddy Kalluru params.eee.adv_caps;
2173645874e5SSudarsana Reddy Kalluru if_link->eee.lp_adv_caps = link.eee_lp_adv_caps;
2174645874e5SSudarsana Reddy Kalluru if_link->eee.enable = params.eee.enable;
2175645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_enable = params.eee.tx_lpi_enable;
2176645874e5SSudarsana Reddy Kalluru if_link->eee.tx_lpi_timer = params.eee.tx_lpi_timer;
2177645874e5SSudarsana Reddy Kalluru }
2178cc875c2eSYuval Mintz }
2179cc875c2eSYuval Mintz
qed_get_current_link(struct qed_dev * cdev,struct qed_link_output * if_link)2180cc875c2eSYuval Mintz static void qed_get_current_link(struct qed_dev *cdev,
2181cc875c2eSYuval Mintz struct qed_link_output *if_link)
2182cc875c2eSYuval Mintz {
2183706d0891SRahul Verma struct qed_hwfn *hwfn;
2184706d0891SRahul Verma struct qed_ptt *ptt;
218536558c3dSYuval Mintz int i;
218636558c3dSYuval Mintz
2187706d0891SRahul Verma hwfn = &cdev->hwfns[0];
2188706d0891SRahul Verma if (IS_PF(cdev)) {
2189706d0891SRahul Verma ptt = qed_ptt_acquire(hwfn);
2190706d0891SRahul Verma if (ptt) {
2191706d0891SRahul Verma qed_fill_link(hwfn, ptt, if_link);
2192706d0891SRahul Verma qed_ptt_release(hwfn, ptt);
2193706d0891SRahul Verma } else {
2194706d0891SRahul Verma DP_NOTICE(hwfn, "Failed to fill link; No PTT\n");
2195706d0891SRahul Verma }
2196706d0891SRahul Verma } else {
2197706d0891SRahul Verma qed_fill_link(hwfn, NULL, if_link);
2198706d0891SRahul Verma }
219936558c3dSYuval Mintz
220036558c3dSYuval Mintz for_each_hwfn(cdev, i)
220136558c3dSYuval Mintz qed_inform_vf_link_state(&cdev->hwfns[i]);
2202cc875c2eSYuval Mintz }
2203cc875c2eSYuval Mintz
qed_link_update(struct qed_hwfn * hwfn,struct qed_ptt * ptt)2204706d0891SRahul Verma void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt)
2205cc875c2eSYuval Mintz {
2206cc875c2eSYuval Mintz void *cookie = hwfn->cdev->ops_cookie;
2207cc875c2eSYuval Mintz struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
2208cc875c2eSYuval Mintz struct qed_link_output if_link;
2209cc875c2eSYuval Mintz
2210706d0891SRahul Verma qed_fill_link(hwfn, ptt, &if_link);
221136558c3dSYuval Mintz qed_inform_vf_link_state(hwfn);
2212cc875c2eSYuval Mintz
2213cc875c2eSYuval Mintz if (IS_LEAD_HWFN(hwfn) && cookie)
2214cc875c2eSYuval Mintz op->link_update(cookie, &if_link);
2215cc875c2eSYuval Mintz }
2216cc875c2eSYuval Mintz
qed_bw_update(struct qed_hwfn * hwfn,struct qed_ptt * ptt)2217699fed4aSSudarsana Reddy Kalluru void qed_bw_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt)
2218699fed4aSSudarsana Reddy Kalluru {
2219699fed4aSSudarsana Reddy Kalluru void *cookie = hwfn->cdev->ops_cookie;
2220699fed4aSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
2221699fed4aSSudarsana Reddy Kalluru
2222699fed4aSSudarsana Reddy Kalluru if (IS_LEAD_HWFN(hwfn) && cookie && op && op->bw_update)
2223699fed4aSSudarsana Reddy Kalluru op->bw_update(cookie);
2224699fed4aSSudarsana Reddy Kalluru }
2225699fed4aSSudarsana Reddy Kalluru
qed_drain(struct qed_dev * cdev)2226fe56b9e6SYuval Mintz static int qed_drain(struct qed_dev *cdev)
2227fe56b9e6SYuval Mintz {
2228fe56b9e6SYuval Mintz struct qed_hwfn *hwfn;
2229fe56b9e6SYuval Mintz struct qed_ptt *ptt;
2230fe56b9e6SYuval Mintz int i, rc;
2231fe56b9e6SYuval Mintz
22321408cc1fSYuval Mintz if (IS_VF(cdev))
22331408cc1fSYuval Mintz return 0;
22341408cc1fSYuval Mintz
2235fe56b9e6SYuval Mintz for_each_hwfn(cdev, i) {
2236fe56b9e6SYuval Mintz hwfn = &cdev->hwfns[i];
2237fe56b9e6SYuval Mintz ptt = qed_ptt_acquire(hwfn);
2238fe56b9e6SYuval Mintz if (!ptt) {
2239fe56b9e6SYuval Mintz DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n");
2240fe56b9e6SYuval Mintz return -EBUSY;
2241fe56b9e6SYuval Mintz }
2242fe56b9e6SYuval Mintz rc = qed_mcp_drain(hwfn, ptt);
22439aaa4e8bSDenis Bolotin qed_ptt_release(hwfn, ptt);
2244fe56b9e6SYuval Mintz if (rc)
2245fe56b9e6SYuval Mintz return rc;
2246fe56b9e6SYuval Mintz }
2247fe56b9e6SYuval Mintz
2248fe56b9e6SYuval Mintz return 0;
2249fe56b9e6SYuval Mintz }
2250fe56b9e6SYuval Mintz
qed_nvm_flash_image_access_crc(struct qed_dev * cdev,struct qed_nvm_image_att * nvm_image,u32 * crc)22513a69cae8SSudarsana Reddy Kalluru static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev,
22523a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att *nvm_image,
22533a69cae8SSudarsana Reddy Kalluru u32 *crc)
22543a69cae8SSudarsana Reddy Kalluru {
22553a69cae8SSudarsana Reddy Kalluru u8 *buf = NULL;
22565ab90341SAlexander Lobakin int rc;
22573a69cae8SSudarsana Reddy Kalluru
22583a69cae8SSudarsana Reddy Kalluru /* Allocate a buffer for holding the nvram image */
22593a69cae8SSudarsana Reddy Kalluru buf = kzalloc(nvm_image->length, GFP_KERNEL);
22603a69cae8SSudarsana Reddy Kalluru if (!buf)
22613a69cae8SSudarsana Reddy Kalluru return -ENOMEM;
22623a69cae8SSudarsana Reddy Kalluru
22633a69cae8SSudarsana Reddy Kalluru /* Read image into buffer */
22643a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr,
22653a69cae8SSudarsana Reddy Kalluru buf, nvm_image->length);
22663a69cae8SSudarsana Reddy Kalluru if (rc) {
22673a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading image from nvm\n");
22683a69cae8SSudarsana Reddy Kalluru goto out;
22693a69cae8SSudarsana Reddy Kalluru }
22703a69cae8SSudarsana Reddy Kalluru
22713a69cae8SSudarsana Reddy Kalluru /* Convert the buffer into big-endian format (excluding the
22723a69cae8SSudarsana Reddy Kalluru * closing 4 bytes of CRC).
22733a69cae8SSudarsana Reddy Kalluru */
22745ab90341SAlexander Lobakin cpu_to_be32_array((__force __be32 *)buf, (const u32 *)buf,
22755ab90341SAlexander Lobakin DIV_ROUND_UP(nvm_image->length - 4, 4));
22763a69cae8SSudarsana Reddy Kalluru
22773a69cae8SSudarsana Reddy Kalluru /* Calc CRC for the "actual" image buffer, i.e. not including
22783a69cae8SSudarsana Reddy Kalluru * the last 4 CRC bytes.
22793a69cae8SSudarsana Reddy Kalluru */
22805ab90341SAlexander Lobakin *crc = ~crc32(~0U, buf, nvm_image->length - 4);
22815ab90341SAlexander Lobakin *crc = (__force u32)cpu_to_be32p(crc);
22823a69cae8SSudarsana Reddy Kalluru
22833a69cae8SSudarsana Reddy Kalluru out:
22843a69cae8SSudarsana Reddy Kalluru kfree(buf);
22853a69cae8SSudarsana Reddy Kalluru
22863a69cae8SSudarsana Reddy Kalluru return rc;
22873a69cae8SSudarsana Reddy Kalluru }
22883a69cae8SSudarsana Reddy Kalluru
22893a69cae8SSudarsana Reddy Kalluru /* Binary file format -
22903a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\
22913a69cae8SSudarsana Reddy Kalluru * 0B | 0x4 [command index] |
22923a69cae8SSudarsana Reddy Kalluru * 4B | image_type | Options | Number of register settings |
22933a69cae8SSudarsana Reddy Kalluru * 8B | Value |
22943a69cae8SSudarsana Reddy Kalluru * 12B | Mask |
22953a69cae8SSudarsana Reddy Kalluru * 16B | Offset |
22963a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/
22973a69cae8SSudarsana Reddy Kalluru * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
22983a69cae8SSudarsana Reddy Kalluru * Options - 0'b - Calculate & Update CRC for image
22993a69cae8SSudarsana Reddy Kalluru */
qed_nvm_flash_image_access(struct qed_dev * cdev,const u8 ** data,bool * check_resp)23003a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
23013a69cae8SSudarsana Reddy Kalluru bool *check_resp)
23023a69cae8SSudarsana Reddy Kalluru {
23033a69cae8SSudarsana Reddy Kalluru struct qed_nvm_image_att nvm_image;
23043a69cae8SSudarsana Reddy Kalluru struct qed_hwfn *p_hwfn;
23053a69cae8SSudarsana Reddy Kalluru bool is_crc = false;
23063a69cae8SSudarsana Reddy Kalluru u32 image_type;
23073a69cae8SSudarsana Reddy Kalluru int rc = 0, i;
23083a69cae8SSudarsana Reddy Kalluru u16 len;
23093a69cae8SSudarsana Reddy Kalluru
23103a69cae8SSudarsana Reddy Kalluru *data += 4;
23113a69cae8SSudarsana Reddy Kalluru image_type = **data;
23123a69cae8SSudarsana Reddy Kalluru p_hwfn = QED_LEADING_HWFN(cdev);
23133a69cae8SSudarsana Reddy Kalluru for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
23143a69cae8SSudarsana Reddy Kalluru if (image_type == p_hwfn->nvm_info.image_att[i].image_type)
23153a69cae8SSudarsana Reddy Kalluru break;
23163a69cae8SSudarsana Reddy Kalluru if (i == p_hwfn->nvm_info.num_images) {
23173a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find nvram image of type %08x\n",
23183a69cae8SSudarsana Reddy Kalluru image_type);
23193a69cae8SSudarsana Reddy Kalluru return -ENOENT;
23203a69cae8SSudarsana Reddy Kalluru }
23213a69cae8SSudarsana Reddy Kalluru
23223a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
23233a69cae8SSudarsana Reddy Kalluru nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
23243a69cae8SSudarsana Reddy Kalluru
23253a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
23263a69cae8SSudarsana Reddy Kalluru "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
23273a69cae8SSudarsana Reddy Kalluru **data, image_type, nvm_image.start_addr,
23283a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 1);
23293a69cae8SSudarsana Reddy Kalluru (*data)++;
23303a69cae8SSudarsana Reddy Kalluru is_crc = !!(**data & BIT(0));
23313a69cae8SSudarsana Reddy Kalluru (*data)++;
23323a69cae8SSudarsana Reddy Kalluru len = *((u16 *)*data);
23333a69cae8SSudarsana Reddy Kalluru *data += 2;
23343a69cae8SSudarsana Reddy Kalluru if (is_crc) {
23353a69cae8SSudarsana Reddy Kalluru u32 crc = 0;
23363a69cae8SSudarsana Reddy Kalluru
23373a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc);
23383a69cae8SSudarsana Reddy Kalluru if (rc) {
23393a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc);
23403a69cae8SSudarsana Reddy Kalluru goto exit;
23413a69cae8SSudarsana Reddy Kalluru }
23423a69cae8SSudarsana Reddy Kalluru
23433a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
23443a69cae8SSudarsana Reddy Kalluru (nvm_image.start_addr +
23453a69cae8SSudarsana Reddy Kalluru nvm_image.length - 4), (u8 *)&crc, 4);
23463a69cae8SSudarsana Reddy Kalluru if (rc)
23473a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x, rc = %d\n",
23483a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + nvm_image.length - 4, rc);
23493a69cae8SSudarsana Reddy Kalluru goto exit;
23503a69cae8SSudarsana Reddy Kalluru }
23513a69cae8SSudarsana Reddy Kalluru
23523a69cae8SSudarsana Reddy Kalluru /* Iterate over the values for setting */
23533a69cae8SSudarsana Reddy Kalluru while (len) {
23543a69cae8SSudarsana Reddy Kalluru u32 offset, mask, value, cur_value;
23553a69cae8SSudarsana Reddy Kalluru u8 buf[4];
23563a69cae8SSudarsana Reddy Kalluru
23573a69cae8SSudarsana Reddy Kalluru value = *((u32 *)*data);
23583a69cae8SSudarsana Reddy Kalluru *data += 4;
23593a69cae8SSudarsana Reddy Kalluru mask = *((u32 *)*data);
23603a69cae8SSudarsana Reddy Kalluru *data += 4;
23613a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)*data);
23623a69cae8SSudarsana Reddy Kalluru *data += 4;
23633a69cae8SSudarsana Reddy Kalluru
23643a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf,
23653a69cae8SSudarsana Reddy Kalluru 4);
23663a69cae8SSudarsana Reddy Kalluru if (rc) {
23673a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed reading from %08x\n",
23683a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset);
23693a69cae8SSudarsana Reddy Kalluru goto exit;
23703a69cae8SSudarsana Reddy Kalluru }
23713a69cae8SSudarsana Reddy Kalluru
23723a69cae8SSudarsana Reddy Kalluru cur_value = le32_to_cpu(*((__le32 *)buf));
23733a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
23743a69cae8SSudarsana Reddy Kalluru "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n",
23753a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset, cur_value,
23763a69cae8SSudarsana Reddy Kalluru (cur_value & ~mask) | (value & mask), value, mask);
23773a69cae8SSudarsana Reddy Kalluru value = (value & mask) | (cur_value & ~mask);
23783a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
23793a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset,
23803a69cae8SSudarsana Reddy Kalluru (u8 *)&value, 4);
23813a69cae8SSudarsana Reddy Kalluru if (rc) {
23823a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed writing to %08x\n",
23833a69cae8SSudarsana Reddy Kalluru nvm_image.start_addr + offset);
23843a69cae8SSudarsana Reddy Kalluru goto exit;
23853a69cae8SSudarsana Reddy Kalluru }
23863a69cae8SSudarsana Reddy Kalluru
23873a69cae8SSudarsana Reddy Kalluru len--;
23883a69cae8SSudarsana Reddy Kalluru }
23893a69cae8SSudarsana Reddy Kalluru exit:
23903a69cae8SSudarsana Reddy Kalluru return rc;
23913a69cae8SSudarsana Reddy Kalluru }
23923a69cae8SSudarsana Reddy Kalluru
23933a69cae8SSudarsana Reddy Kalluru /* Binary file format -
23943a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\
23953a69cae8SSudarsana Reddy Kalluru * 0B | 0x3 [command index] |
23963a69cae8SSudarsana Reddy Kalluru * 4B | b'0: check_response? | b'1-31 reserved |
23973a69cae8SSudarsana Reddy Kalluru * 8B | File-type | reserved |
2398057d2b19SSudarsana Reddy Kalluru * 12B | Image length in bytes |
23993a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/
24003a69cae8SSudarsana Reddy Kalluru * Start a new file of the provided type
24013a69cae8SSudarsana Reddy Kalluru */
qed_nvm_flash_image_file_start(struct qed_dev * cdev,const u8 ** data,bool * check_resp)24023a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
24033a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp)
24043a69cae8SSudarsana Reddy Kalluru {
2405057d2b19SSudarsana Reddy Kalluru u32 file_type, file_size = 0;
24063a69cae8SSudarsana Reddy Kalluru int rc;
24073a69cae8SSudarsana Reddy Kalluru
24083a69cae8SSudarsana Reddy Kalluru *data += 4;
24093a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0));
24103a69cae8SSudarsana Reddy Kalluru *data += 4;
2411057d2b19SSudarsana Reddy Kalluru file_type = **data;
24123a69cae8SSudarsana Reddy Kalluru
24133a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
2414057d2b19SSudarsana Reddy Kalluru "About to start a new file of type %02x\n", file_type);
2415057d2b19SSudarsana Reddy Kalluru if (file_type == DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MBI) {
2416057d2b19SSudarsana Reddy Kalluru *data += 4;
2417057d2b19SSudarsana Reddy Kalluru file_size = *((u32 *)(*data));
2418057d2b19SSudarsana Reddy Kalluru }
2419057d2b19SSudarsana Reddy Kalluru
2420057d2b19SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_BEGIN, file_type,
2421057d2b19SSudarsana Reddy Kalluru (u8 *)(&file_size), 4);
24223a69cae8SSudarsana Reddy Kalluru *data += 4;
24233a69cae8SSudarsana Reddy Kalluru
24243a69cae8SSudarsana Reddy Kalluru return rc;
24253a69cae8SSudarsana Reddy Kalluru }
24263a69cae8SSudarsana Reddy Kalluru
24273a69cae8SSudarsana Reddy Kalluru /* Binary file format -
24283a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\
24293a69cae8SSudarsana Reddy Kalluru * 0B | 0x2 [command index] |
24303a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes |
24313a69cae8SSudarsana Reddy Kalluru * 8B | b'0: check_response? | b'1-31 reserved |
24323a69cae8SSudarsana Reddy Kalluru * 12B | Offset in bytes |
24333a69cae8SSudarsana Reddy Kalluru * 16B | Data ... |
24343a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/
24353a69cae8SSudarsana Reddy Kalluru * Write data as part of a file that was previously started. Data should be
24363a69cae8SSudarsana Reddy Kalluru * of length equal to that provided in the message
24373a69cae8SSudarsana Reddy Kalluru */
qed_nvm_flash_image_file_data(struct qed_dev * cdev,const u8 ** data,bool * check_resp)24383a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
24393a69cae8SSudarsana Reddy Kalluru const u8 **data, bool *check_resp)
24403a69cae8SSudarsana Reddy Kalluru {
24413a69cae8SSudarsana Reddy Kalluru u32 offset, len;
24423a69cae8SSudarsana Reddy Kalluru int rc;
24433a69cae8SSudarsana Reddy Kalluru
24443a69cae8SSudarsana Reddy Kalluru *data += 4;
24453a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data));
24463a69cae8SSudarsana Reddy Kalluru *data += 4;
24473a69cae8SSudarsana Reddy Kalluru *check_resp = !!(**data & BIT(0));
24483a69cae8SSudarsana Reddy Kalluru *data += 4;
24493a69cae8SSudarsana Reddy Kalluru offset = *((u32 *)(*data));
24503a69cae8SSudarsana Reddy Kalluru *data += 4;
24513a69cae8SSudarsana Reddy Kalluru
24523a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
24533a69cae8SSudarsana Reddy Kalluru "About to write File-data: %08x bytes to offset %08x\n",
24543a69cae8SSudarsana Reddy Kalluru len, offset);
24553a69cae8SSudarsana Reddy Kalluru
24563a69cae8SSudarsana Reddy Kalluru rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
24573a69cae8SSudarsana Reddy Kalluru (char *)(*data), len);
24583a69cae8SSudarsana Reddy Kalluru *data += len;
24593a69cae8SSudarsana Reddy Kalluru
24603a69cae8SSudarsana Reddy Kalluru return rc;
24613a69cae8SSudarsana Reddy Kalluru }
24623a69cae8SSudarsana Reddy Kalluru
24633a69cae8SSudarsana Reddy Kalluru /* Binary file format [General header] -
24643a69cae8SSudarsana Reddy Kalluru * /----------------------------------------------------------------------\
24653a69cae8SSudarsana Reddy Kalluru * 0B | QED_NVM_SIGNATURE |
24663a69cae8SSudarsana Reddy Kalluru * 4B | Length in bytes |
24673a69cae8SSudarsana Reddy Kalluru * 8B | Highest command in this batchfile | Reserved |
24683a69cae8SSudarsana Reddy Kalluru * \----------------------------------------------------------------------/
24693a69cae8SSudarsana Reddy Kalluru */
qed_nvm_flash_image_validate(struct qed_dev * cdev,const struct firmware * image,const u8 ** data)24703a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash_image_validate(struct qed_dev *cdev,
24713a69cae8SSudarsana Reddy Kalluru const struct firmware *image,
24723a69cae8SSudarsana Reddy Kalluru const u8 **data)
24733a69cae8SSudarsana Reddy Kalluru {
24743a69cae8SSudarsana Reddy Kalluru u32 signature, len;
24753a69cae8SSudarsana Reddy Kalluru
24763a69cae8SSudarsana Reddy Kalluru /* Check minimum size */
24773a69cae8SSudarsana Reddy Kalluru if (image->size < 12) {
24783a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size);
24793a69cae8SSudarsana Reddy Kalluru return -EINVAL;
24803a69cae8SSudarsana Reddy Kalluru }
24813a69cae8SSudarsana Reddy Kalluru
24823a69cae8SSudarsana Reddy Kalluru /* Check signature */
24833a69cae8SSudarsana Reddy Kalluru signature = *((u32 *)(*data));
24843a69cae8SSudarsana Reddy Kalluru if (signature != QED_NVM_SIGNATURE) {
24853a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Wrong signature '%08x'\n", signature);
24863a69cae8SSudarsana Reddy Kalluru return -EINVAL;
24873a69cae8SSudarsana Reddy Kalluru }
24883a69cae8SSudarsana Reddy Kalluru
24893a69cae8SSudarsana Reddy Kalluru *data += 4;
24903a69cae8SSudarsana Reddy Kalluru /* Validate internal size equals the image-size */
24913a69cae8SSudarsana Reddy Kalluru len = *((u32 *)(*data));
24923a69cae8SSudarsana Reddy Kalluru if (len != image->size) {
24933a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n",
24943a69cae8SSudarsana Reddy Kalluru len, (u32)image->size);
24953a69cae8SSudarsana Reddy Kalluru return -EINVAL;
24963a69cae8SSudarsana Reddy Kalluru }
24973a69cae8SSudarsana Reddy Kalluru
24983a69cae8SSudarsana Reddy Kalluru *data += 4;
24993a69cae8SSudarsana Reddy Kalluru /* Make sure driver familiar with all commands necessary for this */
25003a69cae8SSudarsana Reddy Kalluru if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) {
25013a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n",
25023a69cae8SSudarsana Reddy Kalluru *((u16 *)(*data)));
25033a69cae8SSudarsana Reddy Kalluru return -EINVAL;
25043a69cae8SSudarsana Reddy Kalluru }
25053a69cae8SSudarsana Reddy Kalluru
25063a69cae8SSudarsana Reddy Kalluru *data += 4;
25073a69cae8SSudarsana Reddy Kalluru
25083a69cae8SSudarsana Reddy Kalluru return 0;
25093a69cae8SSudarsana Reddy Kalluru }
25103a69cae8SSudarsana Reddy Kalluru
25110dabbe1bSSudarsana Reddy Kalluru /* Binary file format -
25120dabbe1bSSudarsana Reddy Kalluru * /----------------------------------------------------------------------\
25130dabbe1bSSudarsana Reddy Kalluru * 0B | 0x5 [command index] |
25142da244a5SSudarsana Reddy Kalluru * 4B | Number of config attributes | Reserved |
25152da244a5SSudarsana Reddy Kalluru * 4B | Config ID | Entity ID | Length |
25162da244a5SSudarsana Reddy Kalluru * 4B | Value |
25170dabbe1bSSudarsana Reddy Kalluru * | |
25180dabbe1bSSudarsana Reddy Kalluru * \----------------------------------------------------------------------/
25192da244a5SSudarsana Reddy Kalluru * There can be several cfg_id-entity_id-Length-Value sets as specified by
25202da244a5SSudarsana Reddy Kalluru * 'Number of config attributes'.
25210dabbe1bSSudarsana Reddy Kalluru *
25220dabbe1bSSudarsana Reddy Kalluru * The API parses config attributes from the user provided buffer and flashes
25230dabbe1bSSudarsana Reddy Kalluru * them to the respective NVM path using Management FW inerface.
25240dabbe1bSSudarsana Reddy Kalluru */
qed_nvm_flash_cfg_write(struct qed_dev * cdev,const u8 ** data)25250dabbe1bSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data)
25260dabbe1bSSudarsana Reddy Kalluru {
25270dabbe1bSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
25280dabbe1bSSudarsana Reddy Kalluru u8 entity_id, len, buf[32];
2529c63b0968SSudarsana Reddy Kalluru bool need_nvm_init = true;
25300dabbe1bSSudarsana Reddy Kalluru struct qed_ptt *ptt;
25310dabbe1bSSudarsana Reddy Kalluru u16 cfg_id, count;
25320dabbe1bSSudarsana Reddy Kalluru int rc = 0, i;
25330dabbe1bSSudarsana Reddy Kalluru u32 flags;
25340dabbe1bSSudarsana Reddy Kalluru
25350dabbe1bSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn);
25360dabbe1bSSudarsana Reddy Kalluru if (!ptt)
25370dabbe1bSSudarsana Reddy Kalluru return -EAGAIN;
25380dabbe1bSSudarsana Reddy Kalluru
25390dabbe1bSSudarsana Reddy Kalluru /* NVM CFG ID attribute header */
25400dabbe1bSSudarsana Reddy Kalluru *data += 4;
25410dabbe1bSSudarsana Reddy Kalluru count = *((u16 *)*data);
25422da244a5SSudarsana Reddy Kalluru *data += 4;
25430dabbe1bSSudarsana Reddy Kalluru
25440dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
25452da244a5SSudarsana Reddy Kalluru "Read config ids: num_attrs = %0d\n", count);
2546c63b0968SSudarsana Reddy Kalluru /* NVM CFG ID attributes. Start loop index from 1 to avoid additional
2547c63b0968SSudarsana Reddy Kalluru * arithmetic operations in the implementation.
2548c63b0968SSudarsana Reddy Kalluru */
2549c63b0968SSudarsana Reddy Kalluru for (i = 1; i <= count; i++) {
25500dabbe1bSSudarsana Reddy Kalluru cfg_id = *((u16 *)*data);
25510dabbe1bSSudarsana Reddy Kalluru *data += 2;
25522da244a5SSudarsana Reddy Kalluru entity_id = **data;
25532da244a5SSudarsana Reddy Kalluru (*data)++;
25540dabbe1bSSudarsana Reddy Kalluru len = **data;
25550dabbe1bSSudarsana Reddy Kalluru (*data)++;
25560dabbe1bSSudarsana Reddy Kalluru memcpy(buf, *data, len);
25570dabbe1bSSudarsana Reddy Kalluru *data += len;
25580dabbe1bSSudarsana Reddy Kalluru
2559c63b0968SSudarsana Reddy Kalluru flags = 0;
2560c63b0968SSudarsana Reddy Kalluru if (need_nvm_init) {
2561c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_INIT;
2562c63b0968SSudarsana Reddy Kalluru need_nvm_init = false;
2563c63b0968SSudarsana Reddy Kalluru }
2564c63b0968SSudarsana Reddy Kalluru
2565c63b0968SSudarsana Reddy Kalluru /* Commit to flash and free the resources */
2566c63b0968SSudarsana Reddy Kalluru if (!(i % QED_NVM_CFG_MAX_ATTRS) || i == count) {
2567c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_COMMIT |
2568c63b0968SSudarsana Reddy Kalluru QED_NVM_CFG_OPTION_FREE;
2569c63b0968SSudarsana Reddy Kalluru need_nvm_init = true;
2570c63b0968SSudarsana Reddy Kalluru }
2571c63b0968SSudarsana Reddy Kalluru
2572c63b0968SSudarsana Reddy Kalluru if (entity_id)
2573c63b0968SSudarsana Reddy Kalluru flags |= QED_NVM_CFG_OPTION_ENTITY_SEL;
25740dabbe1bSSudarsana Reddy Kalluru
25750dabbe1bSSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
25762da244a5SSudarsana Reddy Kalluru "cfg_id = %d entity = %d len = %d\n", cfg_id,
25772da244a5SSudarsana Reddy Kalluru entity_id, len);
25780dabbe1bSSudarsana Reddy Kalluru rc = qed_mcp_nvm_set_cfg(hwfn, ptt, cfg_id, entity_id, flags,
25790dabbe1bSSudarsana Reddy Kalluru buf, len);
25800dabbe1bSSudarsana Reddy Kalluru if (rc) {
25810dabbe1bSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d configuring %d\n", rc, cfg_id);
25820dabbe1bSSudarsana Reddy Kalluru break;
25830dabbe1bSSudarsana Reddy Kalluru }
25840dabbe1bSSudarsana Reddy Kalluru }
25850dabbe1bSSudarsana Reddy Kalluru
25860dabbe1bSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
25870dabbe1bSSudarsana Reddy Kalluru
25880dabbe1bSSudarsana Reddy Kalluru return rc;
25890dabbe1bSSudarsana Reddy Kalluru }
25900dabbe1bSSudarsana Reddy Kalluru
25919e54ba7cSSudarsana Reddy Kalluru #define QED_MAX_NVM_BUF_LEN 32
qed_nvm_flash_cfg_len(struct qed_dev * cdev,u32 cmd)25929e54ba7cSSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_len(struct qed_dev *cdev, u32 cmd)
25939e54ba7cSSudarsana Reddy Kalluru {
25949e54ba7cSSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
25959e54ba7cSSudarsana Reddy Kalluru u8 buf[QED_MAX_NVM_BUF_LEN];
25969e54ba7cSSudarsana Reddy Kalluru struct qed_ptt *ptt;
25979e54ba7cSSudarsana Reddy Kalluru u32 len;
25989e54ba7cSSudarsana Reddy Kalluru int rc;
25999e54ba7cSSudarsana Reddy Kalluru
26009e54ba7cSSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn);
26019e54ba7cSSudarsana Reddy Kalluru if (!ptt)
26029e54ba7cSSudarsana Reddy Kalluru return QED_MAX_NVM_BUF_LEN;
26039e54ba7cSSudarsana Reddy Kalluru
26049e54ba7cSSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, 0, QED_NVM_CFG_GET_FLAGS, buf,
26059e54ba7cSSudarsana Reddy Kalluru &len);
26069e54ba7cSSudarsana Reddy Kalluru if (rc || !len) {
26079e54ba7cSSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd);
26089e54ba7cSSudarsana Reddy Kalluru len = QED_MAX_NVM_BUF_LEN;
26099e54ba7cSSudarsana Reddy Kalluru }
26109e54ba7cSSudarsana Reddy Kalluru
26119e54ba7cSSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
26129e54ba7cSSudarsana Reddy Kalluru
26139e54ba7cSSudarsana Reddy Kalluru return len;
26149e54ba7cSSudarsana Reddy Kalluru }
26159e54ba7cSSudarsana Reddy Kalluru
qed_nvm_flash_cfg_read(struct qed_dev * cdev,u8 ** data,u32 cmd,u32 entity_id)26162d4c8495SSudarsana Reddy Kalluru static int qed_nvm_flash_cfg_read(struct qed_dev *cdev, u8 **data,
26172d4c8495SSudarsana Reddy Kalluru u32 cmd, u32 entity_id)
26182d4c8495SSudarsana Reddy Kalluru {
26192d4c8495SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
26202d4c8495SSudarsana Reddy Kalluru struct qed_ptt *ptt;
26212d4c8495SSudarsana Reddy Kalluru u32 flags, len;
26222d4c8495SSudarsana Reddy Kalluru int rc = 0;
26232d4c8495SSudarsana Reddy Kalluru
26242d4c8495SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn);
26252d4c8495SSudarsana Reddy Kalluru if (!ptt)
26262d4c8495SSudarsana Reddy Kalluru return -EAGAIN;
26272d4c8495SSudarsana Reddy Kalluru
26282d4c8495SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
26292d4c8495SSudarsana Reddy Kalluru "Read config cmd = %d entity id %d\n", cmd, entity_id);
26302d4c8495SSudarsana Reddy Kalluru flags = entity_id ? QED_NVM_CFG_GET_PF_FLAGS : QED_NVM_CFG_GET_FLAGS;
26312d4c8495SSudarsana Reddy Kalluru rc = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, entity_id, flags, *data, &len);
26322d4c8495SSudarsana Reddy Kalluru if (rc)
26332d4c8495SSudarsana Reddy Kalluru DP_ERR(cdev, "Error %d reading %d\n", rc, cmd);
26342d4c8495SSudarsana Reddy Kalluru
26352d4c8495SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
26362d4c8495SSudarsana Reddy Kalluru
26372d4c8495SSudarsana Reddy Kalluru return rc;
26382d4c8495SSudarsana Reddy Kalluru }
26392d4c8495SSudarsana Reddy Kalluru
qed_nvm_flash(struct qed_dev * cdev,const char * name)26403a69cae8SSudarsana Reddy Kalluru static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
26413a69cae8SSudarsana Reddy Kalluru {
26423a69cae8SSudarsana Reddy Kalluru const struct firmware *image;
26433a69cae8SSudarsana Reddy Kalluru const u8 *data, *data_end;
26443a69cae8SSudarsana Reddy Kalluru u32 cmd_type;
26453a69cae8SSudarsana Reddy Kalluru int rc;
26463a69cae8SSudarsana Reddy Kalluru
26473a69cae8SSudarsana Reddy Kalluru rc = request_firmware(&image, name, &cdev->pdev->dev);
26483a69cae8SSudarsana Reddy Kalluru if (rc) {
26493a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed to find '%s'\n", name);
26503a69cae8SSudarsana Reddy Kalluru return rc;
26513a69cae8SSudarsana Reddy Kalluru }
26523a69cae8SSudarsana Reddy Kalluru
26533a69cae8SSudarsana Reddy Kalluru DP_VERBOSE(cdev, NETIF_MSG_DRV,
26543a69cae8SSudarsana Reddy Kalluru "Flashing '%s' - firmware's data at %p, size is %08x\n",
26553a69cae8SSudarsana Reddy Kalluru name, image->data, (u32)image->size);
26563a69cae8SSudarsana Reddy Kalluru data = image->data;
26573a69cae8SSudarsana Reddy Kalluru data_end = data + image->size;
26583a69cae8SSudarsana Reddy Kalluru
26593a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_validate(cdev, image, &data);
26603a69cae8SSudarsana Reddy Kalluru if (rc)
26613a69cae8SSudarsana Reddy Kalluru goto exit;
26623a69cae8SSudarsana Reddy Kalluru
26633a69cae8SSudarsana Reddy Kalluru while (data < data_end) {
26643a69cae8SSudarsana Reddy Kalluru bool check_resp = false;
26653a69cae8SSudarsana Reddy Kalluru
26663a69cae8SSudarsana Reddy Kalluru /* Parse the actual command */
26673a69cae8SSudarsana Reddy Kalluru cmd_type = *((u32 *)data);
26683a69cae8SSudarsana Reddy Kalluru switch (cmd_type) {
26693a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_DATA:
26703a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_data(cdev, &data,
26713a69cae8SSudarsana Reddy Kalluru &check_resp);
26723a69cae8SSudarsana Reddy Kalluru break;
26733a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_FILE_START:
26743a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_file_start(cdev, &data,
26753a69cae8SSudarsana Reddy Kalluru &check_resp);
26763a69cae8SSudarsana Reddy Kalluru break;
26773a69cae8SSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CHANGE:
26783a69cae8SSudarsana Reddy Kalluru rc = qed_nvm_flash_image_access(cdev, &data,
26793a69cae8SSudarsana Reddy Kalluru &check_resp);
26803a69cae8SSudarsana Reddy Kalluru break;
26810dabbe1bSSudarsana Reddy Kalluru case QED_NVM_FLASH_CMD_NVM_CFG_ID:
26820dabbe1bSSudarsana Reddy Kalluru rc = qed_nvm_flash_cfg_write(cdev, &data);
26830dabbe1bSSudarsana Reddy Kalluru break;
26843a69cae8SSudarsana Reddy Kalluru default:
26853a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
26863a69cae8SSudarsana Reddy Kalluru rc = -EINVAL;
26873a69cae8SSudarsana Reddy Kalluru goto exit;
26883a69cae8SSudarsana Reddy Kalluru }
26893a69cae8SSudarsana Reddy Kalluru
26903a69cae8SSudarsana Reddy Kalluru if (rc) {
26913a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Command %08x failed\n", cmd_type);
26923a69cae8SSudarsana Reddy Kalluru goto exit;
26933a69cae8SSudarsana Reddy Kalluru }
26943a69cae8SSudarsana Reddy Kalluru
26953a69cae8SSudarsana Reddy Kalluru /* Check response if needed */
26963a69cae8SSudarsana Reddy Kalluru if (check_resp) {
26973a69cae8SSudarsana Reddy Kalluru u32 mcp_response = 0;
26983a69cae8SSudarsana Reddy Kalluru
26993a69cae8SSudarsana Reddy Kalluru if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
27003a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "Failed getting MCP response\n");
27013a69cae8SSudarsana Reddy Kalluru rc = -EINVAL;
27023a69cae8SSudarsana Reddy Kalluru goto exit;
27033a69cae8SSudarsana Reddy Kalluru }
27043a69cae8SSudarsana Reddy Kalluru
27053a69cae8SSudarsana Reddy Kalluru switch (mcp_response & FW_MSG_CODE_MASK) {
27063a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_OK:
27073a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_OK:
27083a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
27093a69cae8SSudarsana Reddy Kalluru case FW_MSG_CODE_PHY_OK:
27103a69cae8SSudarsana Reddy Kalluru break;
27113a69cae8SSudarsana Reddy Kalluru default:
27123a69cae8SSudarsana Reddy Kalluru DP_ERR(cdev, "MFW returns error: %08x\n",
27133a69cae8SSudarsana Reddy Kalluru mcp_response);
27143a69cae8SSudarsana Reddy Kalluru rc = -EINVAL;
27153a69cae8SSudarsana Reddy Kalluru goto exit;
27163a69cae8SSudarsana Reddy Kalluru }
27173a69cae8SSudarsana Reddy Kalluru }
27183a69cae8SSudarsana Reddy Kalluru }
27193a69cae8SSudarsana Reddy Kalluru
27203a69cae8SSudarsana Reddy Kalluru exit:
27213a69cae8SSudarsana Reddy Kalluru release_firmware(image);
27223a69cae8SSudarsana Reddy Kalluru
27233a69cae8SSudarsana Reddy Kalluru return rc;
27243a69cae8SSudarsana Reddy Kalluru }
27253a69cae8SSudarsana Reddy Kalluru
qed_nvm_get_image(struct qed_dev * cdev,enum qed_nvm_images type,u8 * buf,u16 len)272620675b37SMintz, Yuval static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
272720675b37SMintz, Yuval u8 *buf, u16 len)
272820675b37SMintz, Yuval {
272920675b37SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
273020675b37SMintz, Yuval
2731b60bfdfeSDenis Bolotin return qed_mcp_get_nvm_image(hwfn, type, buf, len);
273220675b37SMintz, Yuval }
273320675b37SMintz, Yuval
qed_schedule_recovery_handler(struct qed_hwfn * p_hwfn)273464515dc8STomer Tayar void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn)
273564515dc8STomer Tayar {
273664515dc8STomer Tayar struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common;
273764515dc8STomer Tayar void *cookie = p_hwfn->cdev->ops_cookie;
273864515dc8STomer Tayar
273964515dc8STomer Tayar if (ops && ops->schedule_recovery_handler)
274064515dc8STomer Tayar ops->schedule_recovery_handler(cookie);
274164515dc8STomer Tayar }
274264515dc8STomer Tayar
2743c6b7314dSAlexander Lobakin static const char * const qed_hw_err_type_descr[] = {
2744d639836aSIgor Russkikh [QED_HW_ERR_FAN_FAIL] = "Fan Failure",
2745d639836aSIgor Russkikh [QED_HW_ERR_MFW_RESP_FAIL] = "MFW Response Failure",
2746d639836aSIgor Russkikh [QED_HW_ERR_HW_ATTN] = "HW Attention",
2747d639836aSIgor Russkikh [QED_HW_ERR_DMAE_FAIL] = "DMAE Failure",
2748d639836aSIgor Russkikh [QED_HW_ERR_RAMROD_FAIL] = "Ramrod Failure",
2749d639836aSIgor Russkikh [QED_HW_ERR_FW_ASSERT] = "FW Assertion",
2750d639836aSIgor Russkikh [QED_HW_ERR_LAST] = "Unknown",
2751d639836aSIgor Russkikh };
2752d639836aSIgor Russkikh
qed_hw_error_occurred(struct qed_hwfn * p_hwfn,enum qed_hw_err_type err_type)2753d639836aSIgor Russkikh void qed_hw_error_occurred(struct qed_hwfn *p_hwfn,
2754d639836aSIgor Russkikh enum qed_hw_err_type err_type)
2755d639836aSIgor Russkikh {
2756d639836aSIgor Russkikh struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common;
2757d639836aSIgor Russkikh void *cookie = p_hwfn->cdev->ops_cookie;
2758c6b7314dSAlexander Lobakin const char *err_str;
2759d639836aSIgor Russkikh
2760d639836aSIgor Russkikh if (err_type > QED_HW_ERR_LAST)
2761d639836aSIgor Russkikh err_type = QED_HW_ERR_LAST;
2762d639836aSIgor Russkikh err_str = qed_hw_err_type_descr[err_type];
2763d639836aSIgor Russkikh
2764d639836aSIgor Russkikh DP_NOTICE(p_hwfn, "HW error occurred [%s]\n", err_str);
2765d639836aSIgor Russkikh
2766936c7ba4SIgor Russkikh /* Call the HW error handler of the protocol driver.
2767936c7ba4SIgor Russkikh * If it is not available - perform a minimal handling of preventing
2768936c7ba4SIgor Russkikh * HW attentions from being reasserted.
2769d639836aSIgor Russkikh */
2770d639836aSIgor Russkikh if (ops && ops->schedule_hw_err_handler)
2771d639836aSIgor Russkikh ops->schedule_hw_err_handler(cookie, err_type);
2772936c7ba4SIgor Russkikh else
2773936c7ba4SIgor Russkikh qed_int_attn_clr_enable(p_hwfn->cdev, true);
2774d639836aSIgor Russkikh }
2775d639836aSIgor Russkikh
qed_set_coalesce(struct qed_dev * cdev,u16 rx_coal,u16 tx_coal,void * handle)2776722003acSSudarsana Reddy Kalluru static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal,
2777477f2d14SRahul Verma void *handle)
2778722003acSSudarsana Reddy Kalluru {
2779477f2d14SRahul Verma return qed_set_queue_coalesce(rx_coal, tx_coal, handle);
2780722003acSSudarsana Reddy Kalluru }
2781722003acSSudarsana Reddy Kalluru
qed_set_led(struct qed_dev * cdev,enum qed_led_mode mode)278291420b83SSudarsana Kalluru static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
278391420b83SSudarsana Kalluru {
278491420b83SSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
278591420b83SSudarsana Kalluru struct qed_ptt *ptt;
278691420b83SSudarsana Kalluru int status = 0;
278791420b83SSudarsana Kalluru
278891420b83SSudarsana Kalluru ptt = qed_ptt_acquire(hwfn);
278991420b83SSudarsana Kalluru if (!ptt)
279091420b83SSudarsana Kalluru return -EAGAIN;
279191420b83SSudarsana Kalluru
279291420b83SSudarsana Kalluru status = qed_mcp_set_led(hwfn, ptt, mode);
279391420b83SSudarsana Kalluru
279491420b83SSudarsana Kalluru qed_ptt_release(hwfn, ptt);
279591420b83SSudarsana Kalluru
279691420b83SSudarsana Kalluru return status;
279791420b83SSudarsana Kalluru }
279891420b83SSudarsana Kalluru
qed_recovery_process(struct qed_dev * cdev)2799b228cb16SIgor Russkikh int qed_recovery_process(struct qed_dev *cdev)
280064515dc8STomer Tayar {
280164515dc8STomer Tayar struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
280264515dc8STomer Tayar struct qed_ptt *p_ptt;
280364515dc8STomer Tayar int rc = 0;
280464515dc8STomer Tayar
280564515dc8STomer Tayar p_ptt = qed_ptt_acquire(p_hwfn);
280664515dc8STomer Tayar if (!p_ptt)
280764515dc8STomer Tayar return -EAGAIN;
280864515dc8STomer Tayar
280964515dc8STomer Tayar rc = qed_start_recovery_process(p_hwfn, p_ptt);
281064515dc8STomer Tayar
281164515dc8STomer Tayar qed_ptt_release(p_hwfn, p_ptt);
281264515dc8STomer Tayar
281364515dc8STomer Tayar return rc;
281464515dc8STomer Tayar }
281564515dc8STomer Tayar
qed_update_wol(struct qed_dev * cdev,bool enabled)281614d39648SMintz, Yuval static int qed_update_wol(struct qed_dev *cdev, bool enabled)
281714d39648SMintz, Yuval {
281814d39648SMintz, Yuval struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
281914d39648SMintz, Yuval struct qed_ptt *ptt;
282014d39648SMintz, Yuval int rc = 0;
282114d39648SMintz, Yuval
282214d39648SMintz, Yuval if (IS_VF(cdev))
282314d39648SMintz, Yuval return 0;
282414d39648SMintz, Yuval
282514d39648SMintz, Yuval ptt = qed_ptt_acquire(hwfn);
282614d39648SMintz, Yuval if (!ptt)
282714d39648SMintz, Yuval return -EAGAIN;
282814d39648SMintz, Yuval
282914d39648SMintz, Yuval rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED
283014d39648SMintz, Yuval : QED_OV_WOL_DISABLED);
283114d39648SMintz, Yuval if (rc)
283214d39648SMintz, Yuval goto out;
283314d39648SMintz, Yuval rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
283414d39648SMintz, Yuval
283514d39648SMintz, Yuval out:
283614d39648SMintz, Yuval qed_ptt_release(hwfn, ptt);
283714d39648SMintz, Yuval return rc;
283814d39648SMintz, Yuval }
283914d39648SMintz, Yuval
qed_update_drv_state(struct qed_dev * cdev,bool active)28400fefbfbaSSudarsana Kalluru static int qed_update_drv_state(struct qed_dev *cdev, bool active)
28410fefbfbaSSudarsana Kalluru {
28420fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
28430fefbfbaSSudarsana Kalluru struct qed_ptt *ptt;
28440fefbfbaSSudarsana Kalluru int status = 0;
28450fefbfbaSSudarsana Kalluru
28460fefbfbaSSudarsana Kalluru if (IS_VF(cdev))
28470fefbfbaSSudarsana Kalluru return 0;
28480fefbfbaSSudarsana Kalluru
28490fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn);
28500fefbfbaSSudarsana Kalluru if (!ptt)
28510fefbfbaSSudarsana Kalluru return -EAGAIN;
28520fefbfbaSSudarsana Kalluru
28530fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_driver_state(hwfn, ptt, active ?
28540fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_ACTIVE :
28550fefbfbaSSudarsana Kalluru QED_OV_DRIVER_STATE_DISABLED);
28560fefbfbaSSudarsana Kalluru
28570fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt);
28580fefbfbaSSudarsana Kalluru
28590fefbfbaSSudarsana Kalluru return status;
28600fefbfbaSSudarsana Kalluru }
28610fefbfbaSSudarsana Kalluru
qed_update_mac(struct qed_dev * cdev,const u8 * mac)286276660757SJakub Kicinski static int qed_update_mac(struct qed_dev *cdev, const u8 *mac)
28630fefbfbaSSudarsana Kalluru {
28640fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
28650fefbfbaSSudarsana Kalluru struct qed_ptt *ptt;
28660fefbfbaSSudarsana Kalluru int status = 0;
28670fefbfbaSSudarsana Kalluru
28680fefbfbaSSudarsana Kalluru if (IS_VF(cdev))
28690fefbfbaSSudarsana Kalluru return 0;
28700fefbfbaSSudarsana Kalluru
28710fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn);
28720fefbfbaSSudarsana Kalluru if (!ptt)
28730fefbfbaSSudarsana Kalluru return -EAGAIN;
28740fefbfbaSSudarsana Kalluru
28750fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mac(hwfn, ptt, mac);
28760fefbfbaSSudarsana Kalluru if (status)
28770fefbfbaSSudarsana Kalluru goto out;
28780fefbfbaSSudarsana Kalluru
28790fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
28800fefbfbaSSudarsana Kalluru
28810fefbfbaSSudarsana Kalluru out:
28820fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt);
28830fefbfbaSSudarsana Kalluru return status;
28840fefbfbaSSudarsana Kalluru }
28850fefbfbaSSudarsana Kalluru
qed_update_mtu(struct qed_dev * cdev,u16 mtu)28860fefbfbaSSudarsana Kalluru static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
28870fefbfbaSSudarsana Kalluru {
28880fefbfbaSSudarsana Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
28890fefbfbaSSudarsana Kalluru struct qed_ptt *ptt;
28900fefbfbaSSudarsana Kalluru int status = 0;
28910fefbfbaSSudarsana Kalluru
28920fefbfbaSSudarsana Kalluru if (IS_VF(cdev))
28930fefbfbaSSudarsana Kalluru return 0;
28940fefbfbaSSudarsana Kalluru
28950fefbfbaSSudarsana Kalluru ptt = qed_ptt_acquire(hwfn);
28960fefbfbaSSudarsana Kalluru if (!ptt)
28970fefbfbaSSudarsana Kalluru return -EAGAIN;
28980fefbfbaSSudarsana Kalluru
28990fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_mtu(hwfn, ptt, mtu);
29000fefbfbaSSudarsana Kalluru if (status)
29010fefbfbaSSudarsana Kalluru goto out;
29020fefbfbaSSudarsana Kalluru
29030fefbfbaSSudarsana Kalluru status = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);
29040fefbfbaSSudarsana Kalluru
29050fefbfbaSSudarsana Kalluru out:
29060fefbfbaSSudarsana Kalluru qed_ptt_release(hwfn, ptt);
29070fefbfbaSSudarsana Kalluru return status;
29080fefbfbaSSudarsana Kalluru }
29090fefbfbaSSudarsana Kalluru
29100cc3a801SManish Chopra static int
qed_get_sb_info(struct qed_dev * cdev,struct qed_sb_info * sb,u16 qid,struct qed_sb_info_dbg * sb_dbg)29110cc3a801SManish Chopra qed_get_sb_info(struct qed_dev *cdev, struct qed_sb_info *sb,
29120cc3a801SManish Chopra u16 qid, struct qed_sb_info_dbg *sb_dbg)
29130cc3a801SManish Chopra {
29140cc3a801SManish Chopra struct qed_hwfn *hwfn = &cdev->hwfns[qid % cdev->num_hwfns];
29150cc3a801SManish Chopra struct qed_ptt *ptt;
29160cc3a801SManish Chopra int rc;
29170cc3a801SManish Chopra
29180cc3a801SManish Chopra if (IS_VF(cdev))
29190cc3a801SManish Chopra return -EINVAL;
29200cc3a801SManish Chopra
29210cc3a801SManish Chopra ptt = qed_ptt_acquire(hwfn);
29220cc3a801SManish Chopra if (!ptt) {
29230cc3a801SManish Chopra DP_NOTICE(hwfn, "Can't acquire PTT\n");
29240cc3a801SManish Chopra return -EAGAIN;
29250cc3a801SManish Chopra }
29260cc3a801SManish Chopra
29270cc3a801SManish Chopra memset(sb_dbg, 0, sizeof(*sb_dbg));
29280cc3a801SManish Chopra rc = qed_int_get_sb_dbg(hwfn, ptt, sb, sb_dbg);
29290cc3a801SManish Chopra
29300cc3a801SManish Chopra qed_ptt_release(hwfn, ptt);
29310cc3a801SManish Chopra return rc;
29320cc3a801SManish Chopra }
29330cc3a801SManish Chopra
qed_read_module_eeprom(struct qed_dev * cdev,char * buf,u8 dev_addr,u32 offset,u32 len)2934b51dab46SSudarsana Reddy Kalluru static int qed_read_module_eeprom(struct qed_dev *cdev, char *buf,
2935b51dab46SSudarsana Reddy Kalluru u8 dev_addr, u32 offset, u32 len)
2936b51dab46SSudarsana Reddy Kalluru {
2937b51dab46SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2938b51dab46SSudarsana Reddy Kalluru struct qed_ptt *ptt;
2939b51dab46SSudarsana Reddy Kalluru int rc = 0;
2940b51dab46SSudarsana Reddy Kalluru
2941b51dab46SSudarsana Reddy Kalluru if (IS_VF(cdev))
2942b51dab46SSudarsana Reddy Kalluru return 0;
2943b51dab46SSudarsana Reddy Kalluru
2944b51dab46SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn);
2945b51dab46SSudarsana Reddy Kalluru if (!ptt)
2946b51dab46SSudarsana Reddy Kalluru return -EAGAIN;
2947b51dab46SSudarsana Reddy Kalluru
2948b51dab46SSudarsana Reddy Kalluru rc = qed_mcp_phy_sfp_read(hwfn, ptt, MFW_PORT(hwfn), dev_addr,
2949b51dab46SSudarsana Reddy Kalluru offset, len, buf);
2950b51dab46SSudarsana Reddy Kalluru
2951b51dab46SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
2952b51dab46SSudarsana Reddy Kalluru
2953b51dab46SSudarsana Reddy Kalluru return rc;
2954b51dab46SSudarsana Reddy Kalluru }
2955b51dab46SSudarsana Reddy Kalluru
qed_set_grc_config(struct qed_dev * cdev,u32 cfg_id,u32 val)29563b86bd07SSudarsana Reddy Kalluru static int qed_set_grc_config(struct qed_dev *cdev, u32 cfg_id, u32 val)
29573b86bd07SSudarsana Reddy Kalluru {
29583b86bd07SSudarsana Reddy Kalluru struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
29593b86bd07SSudarsana Reddy Kalluru struct qed_ptt *ptt;
29603b86bd07SSudarsana Reddy Kalluru int rc = 0;
29613b86bd07SSudarsana Reddy Kalluru
29623b86bd07SSudarsana Reddy Kalluru if (IS_VF(cdev))
29633b86bd07SSudarsana Reddy Kalluru return 0;
29643b86bd07SSudarsana Reddy Kalluru
29653b86bd07SSudarsana Reddy Kalluru ptt = qed_ptt_acquire(hwfn);
29663b86bd07SSudarsana Reddy Kalluru if (!ptt)
29673b86bd07SSudarsana Reddy Kalluru return -EAGAIN;
29683b86bd07SSudarsana Reddy Kalluru
29692d22bc83SMichal Kalderon rc = qed_dbg_grc_config(hwfn, cfg_id, val);
29703b86bd07SSudarsana Reddy Kalluru
29713b86bd07SSudarsana Reddy Kalluru qed_ptt_release(hwfn, ptt);
29723b86bd07SSudarsana Reddy Kalluru
29733b86bd07SSudarsana Reddy Kalluru return rc;
29743b86bd07SSudarsana Reddy Kalluru }
29753b86bd07SSudarsana Reddy Kalluru
qed_mfw_report(struct qed_dev * cdev,char * fmt,...)29760cc3a801SManish Chopra static __printf(2, 3) void qed_mfw_report(struct qed_dev *cdev, char *fmt, ...)
29770cc3a801SManish Chopra {
29780cc3a801SManish Chopra char buf[QED_MFW_REPORT_STR_SIZE];
29790cc3a801SManish Chopra struct qed_hwfn *p_hwfn;
29800cc3a801SManish Chopra struct qed_ptt *p_ptt;
29810cc3a801SManish Chopra va_list vl;
29820cc3a801SManish Chopra
29830cc3a801SManish Chopra va_start(vl, fmt);
29840cc3a801SManish Chopra vsnprintf(buf, QED_MFW_REPORT_STR_SIZE, fmt, vl);
29850cc3a801SManish Chopra va_end(vl);
29860cc3a801SManish Chopra
29870cc3a801SManish Chopra if (IS_PF(cdev)) {
29880cc3a801SManish Chopra p_hwfn = QED_LEADING_HWFN(cdev);
29890cc3a801SManish Chopra p_ptt = qed_ptt_acquire(p_hwfn);
29900cc3a801SManish Chopra if (p_ptt) {
29910cc3a801SManish Chopra qed_mcp_send_raw_debug_data(p_hwfn, p_ptt, buf, strlen(buf));
29920cc3a801SManish Chopra qed_ptt_release(p_hwfn, p_ptt);
29930cc3a801SManish Chopra }
29940cc3a801SManish Chopra }
29950cc3a801SManish Chopra }
29960cc3a801SManish Chopra
qed_get_affin_hwfn_idx(struct qed_dev * cdev)299708eb1fb0SMichal Kalderon static u8 qed_get_affin_hwfn_idx(struct qed_dev *cdev)
299808eb1fb0SMichal Kalderon {
299908eb1fb0SMichal Kalderon return QED_AFFIN_HWFN_IDX(cdev);
300008eb1fb0SMichal Kalderon }
300108eb1fb0SMichal Kalderon
qed_get_esl_status(struct qed_dev * cdev,bool * esl_active)3002823163baSManish Chopra static int qed_get_esl_status(struct qed_dev *cdev, bool *esl_active)
3003823163baSManish Chopra {
3004823163baSManish Chopra struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
3005823163baSManish Chopra struct qed_ptt *ptt;
3006823163baSManish Chopra int rc = 0;
3007823163baSManish Chopra
3008823163baSManish Chopra *esl_active = false;
3009823163baSManish Chopra
3010823163baSManish Chopra if (IS_VF(cdev))
3011823163baSManish Chopra return 0;
3012823163baSManish Chopra
3013823163baSManish Chopra ptt = qed_ptt_acquire(hwfn);
3014823163baSManish Chopra if (!ptt)
3015823163baSManish Chopra return -EAGAIN;
3016823163baSManish Chopra
3017823163baSManish Chopra rc = qed_mcp_get_esl_status(hwfn, ptt, esl_active);
3018823163baSManish Chopra
3019823163baSManish Chopra qed_ptt_release(hwfn, ptt);
3020823163baSManish Chopra
3021823163baSManish Chopra return rc;
3022823163baSManish Chopra }
3023823163baSManish Chopra
30248c93beafSYuval Mintz static struct qed_selftest_ops qed_selftest_ops_pass = {
302503dc76caSSudarsana Reddy Kalluru .selftest_memory = &qed_selftest_memory,
302603dc76caSSudarsana Reddy Kalluru .selftest_interrupt = &qed_selftest_interrupt,
302703dc76caSSudarsana Reddy Kalluru .selftest_register = &qed_selftest_register,
302803dc76caSSudarsana Reddy Kalluru .selftest_clock = &qed_selftest_clock,
30297a4b21b7SMintz, Yuval .selftest_nvram = &qed_selftest_nvram,
303003dc76caSSudarsana Reddy Kalluru };
303103dc76caSSudarsana Reddy Kalluru
3032fe56b9e6SYuval Mintz const struct qed_common_ops qed_common_ops_pass = {
303303dc76caSSudarsana Reddy Kalluru .selftest = &qed_selftest_ops_pass,
3034fe56b9e6SYuval Mintz .probe = &qed_probe,
3035fe56b9e6SYuval Mintz .remove = &qed_remove,
3036fe56b9e6SYuval Mintz .set_power_state = &qed_set_power_state,
3037712c3cbfSMintz, Yuval .set_name = &qed_set_name,
3038fe56b9e6SYuval Mintz .update_pf_params = &qed_update_pf_params,
3039fe56b9e6SYuval Mintz .slowpath_start = &qed_slowpath_start,
3040fe56b9e6SYuval Mintz .slowpath_stop = &qed_slowpath_stop,
3041fe56b9e6SYuval Mintz .set_fp_int = &qed_set_int_fp,
3042fe56b9e6SYuval Mintz .get_fp_int = &qed_get_int_fp,
3043fe56b9e6SYuval Mintz .sb_init = &qed_sb_init,
3044fe56b9e6SYuval Mintz .sb_release = &qed_sb_release,
3045fe56b9e6SYuval Mintz .simd_handler_config = &qed_simd_handler_config,
3046fe56b9e6SYuval Mintz .simd_handler_clean = &qed_simd_handler_clean,
30471e128c81SArun Easi .dbg_grc = &qed_dbg_grc,
30481e128c81SArun Easi .dbg_grc_size = &qed_dbg_grc_size,
3049fe7cd2bfSYuval Mintz .can_link_change = &qed_can_link_change,
3050cc875c2eSYuval Mintz .set_link = &qed_set_link,
3051cc875c2eSYuval Mintz .get_link = &qed_get_current_link,
3052fe56b9e6SYuval Mintz .drain = &qed_drain,
3053fe56b9e6SYuval Mintz .update_msglvl = &qed_init_dp,
3054755f982bSIgor Russkikh .devlink_register = qed_devlink_register,
3055755f982bSIgor Russkikh .devlink_unregister = qed_devlink_unregister,
30564f5a8db2SIgor Russkikh .report_fatal_error = qed_report_fatal_error,
3057e0971c83STomer Tayar .dbg_all_data = &qed_dbg_all_data,
3058e0971c83STomer Tayar .dbg_all_data_size = &qed_dbg_all_data_size,
3059fe56b9e6SYuval Mintz .chain_alloc = &qed_chain_alloc,
3060fe56b9e6SYuval Mintz .chain_free = &qed_chain_free,
30613a69cae8SSudarsana Reddy Kalluru .nvm_flash = &qed_nvm_flash,
306220675b37SMintz, Yuval .nvm_get_image = &qed_nvm_get_image,
3063722003acSSudarsana Reddy Kalluru .set_coalesce = &qed_set_coalesce,
306491420b83SSudarsana Kalluru .set_led = &qed_set_led,
306564515dc8STomer Tayar .recovery_process = &qed_recovery_process,
306664515dc8STomer Tayar .recovery_prolog = &qed_recovery_prolog,
3067936c7ba4SIgor Russkikh .attn_clr_enable = &qed_int_attn_clr_enable,
30680fefbfbaSSudarsana Kalluru .update_drv_state = &qed_update_drv_state,
30690fefbfbaSSudarsana Kalluru .update_mac = &qed_update_mac,
30700fefbfbaSSudarsana Kalluru .update_mtu = &qed_update_mtu,
307114d39648SMintz, Yuval .update_wol = &qed_update_wol,
30720e1f1044SAriel Elior .db_recovery_add = &qed_db_recovery_add,
30730e1f1044SAriel Elior .db_recovery_del = &qed_db_recovery_del,
3074b51dab46SSudarsana Reddy Kalluru .read_module_eeprom = &qed_read_module_eeprom,
307508eb1fb0SMichal Kalderon .get_affin_hwfn_idx = &qed_get_affin_hwfn_idx,
30762d4c8495SSudarsana Reddy Kalluru .read_nvm_cfg = &qed_nvm_flash_cfg_read,
30779e54ba7cSSudarsana Reddy Kalluru .read_nvm_cfg_len = &qed_nvm_flash_cfg_len,
30783b86bd07SSudarsana Reddy Kalluru .set_grc_config = &qed_set_grc_config,
30790cc3a801SManish Chopra .mfw_report = &qed_mfw_report,
30800cc3a801SManish Chopra .get_sb_info = &qed_get_sb_info,
3081823163baSManish Chopra .get_esl_status = &qed_get_esl_status,
3082fe56b9e6SYuval Mintz };
30836c754246SSudarsana Reddy Kalluru
qed_get_protocol_stats(struct qed_dev * cdev,enum qed_mcp_protocol_type type,union qed_mcp_protocol_stats * stats)30846c754246SSudarsana Reddy Kalluru void qed_get_protocol_stats(struct qed_dev *cdev,
30856c754246SSudarsana Reddy Kalluru enum qed_mcp_protocol_type type,
30866c754246SSudarsana Reddy Kalluru union qed_mcp_protocol_stats *stats)
30876c754246SSudarsana Reddy Kalluru {
30886c754246SSudarsana Reddy Kalluru struct qed_eth_stats eth_stats;
30896c754246SSudarsana Reddy Kalluru
30906c754246SSudarsana Reddy Kalluru memset(stats, 0, sizeof(*stats));
30916c754246SSudarsana Reddy Kalluru
30926c754246SSudarsana Reddy Kalluru switch (type) {
30936c754246SSudarsana Reddy Kalluru case QED_MCP_LAN_STATS:
3094e346e231SKonstantin Khorenko qed_get_vport_stats_context(cdev, ð_stats, true);
30959c79ddaaSMintz, Yuval stats->lan_stats.ucast_rx_pkts =
30969c79ddaaSMintz, Yuval eth_stats.common.rx_ucast_pkts;
30979c79ddaaSMintz, Yuval stats->lan_stats.ucast_tx_pkts =
30989c79ddaaSMintz, Yuval eth_stats.common.tx_ucast_pkts;
30996c754246SSudarsana Reddy Kalluru stats->lan_stats.fcs_err = -1;
31006c754246SSudarsana Reddy Kalluru break;
31011e128c81SArun Easi case QED_MCP_FCOE_STATS:
3102e346e231SKonstantin Khorenko qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true);
31031e128c81SArun Easi break;
31042f2b2614SMintz, Yuval case QED_MCP_ISCSI_STATS:
3105e346e231SKonstantin Khorenko qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true);
31062f2b2614SMintz, Yuval break;
31076c754246SSudarsana Reddy Kalluru default:
3108512c7840SMintz, Yuval DP_VERBOSE(cdev, QED_MSG_SP,
3109512c7840SMintz, Yuval "Invalid protocol type = %d\n", type);
31106c754246SSudarsana Reddy Kalluru return;
31116c754246SSudarsana Reddy Kalluru }
31126c754246SSudarsana Reddy Kalluru }
31132528c389SSudarsana Reddy Kalluru
qed_mfw_tlv_req(struct qed_hwfn * hwfn)311459ccf86fSSudarsana Reddy Kalluru int qed_mfw_tlv_req(struct qed_hwfn *hwfn)
311559ccf86fSSudarsana Reddy Kalluru {
311659ccf86fSSudarsana Reddy Kalluru DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV,
311759ccf86fSSudarsana Reddy Kalluru "Scheduling slowpath task [Flag: %d]\n",
311859ccf86fSSudarsana Reddy Kalluru QED_SLOWPATH_MFW_TLV_REQ);
3119f2a74107SPrabhakar Kushwaha /* Memory barrier for setting atomic bit */
312059ccf86fSSudarsana Reddy Kalluru smp_mb__before_atomic();
312159ccf86fSSudarsana Reddy Kalluru set_bit(QED_SLOWPATH_MFW_TLV_REQ, &hwfn->slowpath_task_flags);
3122f2a74107SPrabhakar Kushwaha /* Memory barrier after setting atomic bit */
312359ccf86fSSudarsana Reddy Kalluru smp_mb__after_atomic();
312459ccf86fSSudarsana Reddy Kalluru queue_delayed_work(hwfn->slowpath_wq, &hwfn->slowpath_task, 0);
312559ccf86fSSudarsana Reddy Kalluru
312659ccf86fSSudarsana Reddy Kalluru return 0;
312759ccf86fSSudarsana Reddy Kalluru }
312859ccf86fSSudarsana Reddy Kalluru
312959ccf86fSSudarsana Reddy Kalluru static void
qed_fill_generic_tlv_data(struct qed_dev * cdev,struct qed_mfw_tlv_generic * tlv)313059ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(struct qed_dev *cdev, struct qed_mfw_tlv_generic *tlv)
313159ccf86fSSudarsana Reddy Kalluru {
313259ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *op = cdev->protocol_ops.common;
313359ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats_common *p_common;
313459ccf86fSSudarsana Reddy Kalluru struct qed_generic_tlvs gen_tlvs;
313559ccf86fSSudarsana Reddy Kalluru struct qed_eth_stats stats;
313659ccf86fSSudarsana Reddy Kalluru int i;
313759ccf86fSSudarsana Reddy Kalluru
313859ccf86fSSudarsana Reddy Kalluru memset(&gen_tlvs, 0, sizeof(gen_tlvs));
313959ccf86fSSudarsana Reddy Kalluru op->get_generic_tlv_data(cdev->ops_cookie, &gen_tlvs);
314059ccf86fSSudarsana Reddy Kalluru
314159ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_IP_CSUM)
314259ccf86fSSudarsana Reddy Kalluru tlv->flags.ipv4_csum_offload = true;
314359ccf86fSSudarsana Reddy Kalluru if (gen_tlvs.feat_flags & QED_TLV_LSO)
314459ccf86fSSudarsana Reddy Kalluru tlv->flags.lso_supported = true;
314559ccf86fSSudarsana Reddy Kalluru tlv->flags.b_set = true;
314659ccf86fSSudarsana Reddy Kalluru
314759ccf86fSSudarsana Reddy Kalluru for (i = 0; i < QED_TLV_MAC_COUNT; i++) {
314859ccf86fSSudarsana Reddy Kalluru if (is_valid_ether_addr(gen_tlvs.mac[i])) {
314959ccf86fSSudarsana Reddy Kalluru ether_addr_copy(tlv->mac[i], gen_tlvs.mac[i]);
315059ccf86fSSudarsana Reddy Kalluru tlv->mac_set[i] = true;
315159ccf86fSSudarsana Reddy Kalluru }
315259ccf86fSSudarsana Reddy Kalluru }
315359ccf86fSSudarsana Reddy Kalluru
315459ccf86fSSudarsana Reddy Kalluru qed_get_vport_stats(cdev, &stats);
315559ccf86fSSudarsana Reddy Kalluru p_common = &stats.common;
315659ccf86fSSudarsana Reddy Kalluru tlv->rx_frames = p_common->rx_ucast_pkts + p_common->rx_mcast_pkts +
315759ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_pkts;
315859ccf86fSSudarsana Reddy Kalluru tlv->rx_frames_set = true;
315959ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes = p_common->rx_ucast_bytes + p_common->rx_mcast_bytes +
316059ccf86fSSudarsana Reddy Kalluru p_common->rx_bcast_bytes;
316159ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true;
316259ccf86fSSudarsana Reddy Kalluru tlv->tx_frames = p_common->tx_ucast_pkts + p_common->tx_mcast_pkts +
316359ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_pkts;
316459ccf86fSSudarsana Reddy Kalluru tlv->tx_frames_set = true;
316559ccf86fSSudarsana Reddy Kalluru tlv->tx_bytes = p_common->tx_ucast_bytes + p_common->tx_mcast_bytes +
316659ccf86fSSudarsana Reddy Kalluru p_common->tx_bcast_bytes;
316759ccf86fSSudarsana Reddy Kalluru tlv->rx_bytes_set = true;
316859ccf86fSSudarsana Reddy Kalluru }
316959ccf86fSSudarsana Reddy Kalluru
qed_mfw_fill_tlv_data(struct qed_hwfn * hwfn,enum qed_mfw_tlv_type type,union qed_mfw_tlv_data * tlv_buf)31702528c389SSudarsana Reddy Kalluru int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn, enum qed_mfw_tlv_type type,
31712528c389SSudarsana Reddy Kalluru union qed_mfw_tlv_data *tlv_buf)
31722528c389SSudarsana Reddy Kalluru {
317359ccf86fSSudarsana Reddy Kalluru struct qed_dev *cdev = hwfn->cdev;
317459ccf86fSSudarsana Reddy Kalluru struct qed_common_cb_ops *ops;
317559ccf86fSSudarsana Reddy Kalluru
317659ccf86fSSudarsana Reddy Kalluru ops = cdev->protocol_ops.common;
317759ccf86fSSudarsana Reddy Kalluru if (!ops || !ops->get_protocol_tlv_data || !ops->get_generic_tlv_data) {
317859ccf86fSSudarsana Reddy Kalluru DP_NOTICE(hwfn, "Can't collect TLV management info\n");
31792528c389SSudarsana Reddy Kalluru return -EINVAL;
31802528c389SSudarsana Reddy Kalluru }
318159ccf86fSSudarsana Reddy Kalluru
318259ccf86fSSudarsana Reddy Kalluru switch (type) {
318359ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_GENERIC:
318459ccf86fSSudarsana Reddy Kalluru qed_fill_generic_tlv_data(hwfn->cdev, &tlv_buf->generic);
318559ccf86fSSudarsana Reddy Kalluru break;
318659ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ETH:
318759ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->eth);
318859ccf86fSSudarsana Reddy Kalluru break;
318959ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_FCOE:
319059ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->fcoe);
319159ccf86fSSudarsana Reddy Kalluru break;
319259ccf86fSSudarsana Reddy Kalluru case QED_MFW_TLV_ISCSI:
319359ccf86fSSudarsana Reddy Kalluru ops->get_protocol_tlv_data(cdev->ops_cookie, &tlv_buf->iscsi);
319459ccf86fSSudarsana Reddy Kalluru break;
319559ccf86fSSudarsana Reddy Kalluru default:
319659ccf86fSSudarsana Reddy Kalluru break;
319759ccf86fSSudarsana Reddy Kalluru }
319859ccf86fSSudarsana Reddy Kalluru
319959ccf86fSSudarsana Reddy Kalluru return 0;
320059ccf86fSSudarsana Reddy Kalluru }
32016c95dd8fSPrabhakar Kushwaha
qed_get_epoch_time(void)32026c95dd8fSPrabhakar Kushwaha unsigned long qed_get_epoch_time(void)
32036c95dd8fSPrabhakar Kushwaha {
32046c95dd8fSPrabhakar Kushwaha return ktime_get_real_seconds();
32056c95dd8fSPrabhakar Kushwaha }
3206