18c2ecf20Sopenharmony_ci/**********************************************************************
28c2ecf20Sopenharmony_ci * Author: Cavium, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Contact: support@cavium.com
58c2ecf20Sopenharmony_ci *          Please include "LiquidIO" in the subject.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
118c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
168c2ecf20Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
178c2ecf20Sopenharmony_ci ***********************************************************************/
188c2ecf20Sopenharmony_ci#include <linux/pci.h>
198c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
208c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
218c2ecf20Sopenharmony_ci#include "liquidio_common.h"
228c2ecf20Sopenharmony_ci#include "octeon_droq.h"
238c2ecf20Sopenharmony_ci#include "octeon_iq.h"
248c2ecf20Sopenharmony_ci#include "response_manager.h"
258c2ecf20Sopenharmony_ci#include "octeon_device.h"
268c2ecf20Sopenharmony_ci#include "octeon_main.h"
278c2ecf20Sopenharmony_ci#include "octeon_network.h"
288c2ecf20Sopenharmony_ci#include "cn66xx_regs.h"
298c2ecf20Sopenharmony_ci#include "cn66xx_device.h"
308c2ecf20Sopenharmony_ci#include "cn23xx_pf_device.h"
318c2ecf20Sopenharmony_ci#include "cn23xx_vf_device.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/** Default configuration
348c2ecf20Sopenharmony_ci *  for CN66XX OCTEON Models.
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_cistatic struct octeon_config default_cn66xx_conf = {
378c2ecf20Sopenharmony_ci	.card_type                              = LIO_210SV,
388c2ecf20Sopenharmony_ci	.card_name                              = LIO_210SV_NAME,
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	/** IQ attributes */
418c2ecf20Sopenharmony_ci	.iq					= {
428c2ecf20Sopenharmony_ci		.max_iqs			= CN6XXX_CFG_IO_QUEUES,
438c2ecf20Sopenharmony_ci		.pending_list_size		=
448c2ecf20Sopenharmony_ci			(CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES),
458c2ecf20Sopenharmony_ci		.instr_type			= OCTEON_64BYTE_INSTR,
468c2ecf20Sopenharmony_ci		.db_min				= CN6XXX_DB_MIN,
478c2ecf20Sopenharmony_ci		.db_timeout			= CN6XXX_DB_TIMEOUT,
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci	,
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	/** OQ attributes */
528c2ecf20Sopenharmony_ci	.oq					= {
538c2ecf20Sopenharmony_ci		.max_oqs			= CN6XXX_CFG_IO_QUEUES,
548c2ecf20Sopenharmony_ci		.refill_threshold		= CN6XXX_OQ_REFIL_THRESHOLD,
558c2ecf20Sopenharmony_ci		.oq_intr_pkt			= CN6XXX_OQ_INTR_PKT,
568c2ecf20Sopenharmony_ci		.oq_intr_time			= CN6XXX_OQ_INTR_TIME,
578c2ecf20Sopenharmony_ci		.pkts_per_intr			= CN6XXX_OQ_PKTSPER_INTR,
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci	,
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	.num_nic_ports				= DEFAULT_NUM_NIC_PORTS_66XX,
628c2ecf20Sopenharmony_ci	.num_def_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
638c2ecf20Sopenharmony_ci	.num_def_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
648c2ecf20Sopenharmony_ci	.def_rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* For ethernet interface 0:  Port cfg Attributes */
678c2ecf20Sopenharmony_ci	.nic_if_cfg[0] = {
688c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
698c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
728c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
758c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
788c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
818c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
848c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
878c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
888c2ecf20Sopenharmony_ci		 */
898c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		.gmx_port_id			= 0,
948c2ecf20Sopenharmony_ci	},
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	.nic_if_cfg[1] = {
978c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
988c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
1018c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
1048c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
1078c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
1108c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
1138c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
1168c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
1178c2ecf20Sopenharmony_ci		 */
1188c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci		.gmx_port_id			= 1,
1238c2ecf20Sopenharmony_ci	},
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/** Miscellaneous attributes */
1268c2ecf20Sopenharmony_ci	.misc					= {
1278c2ecf20Sopenharmony_ci		/* Host driver link query interval */
1288c2ecf20Sopenharmony_ci		.oct_link_query_interval	= 100,
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci		/* Octeon link query interval */
1318c2ecf20Sopenharmony_ci		.host_link_query_interval	= 500,
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci		.enable_sli_oq_bp		= 0,
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci		/* Control queue group */
1368c2ecf20Sopenharmony_ci		.ctrlq_grp			= 1,
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci	,
1398c2ecf20Sopenharmony_ci};
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/** Default configuration
1428c2ecf20Sopenharmony_ci *  for CN68XX OCTEON Model.
1438c2ecf20Sopenharmony_ci */
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic struct octeon_config default_cn68xx_conf = {
1468c2ecf20Sopenharmony_ci	.card_type                              = LIO_410NV,
1478c2ecf20Sopenharmony_ci	.card_name                              = LIO_410NV_NAME,
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/** IQ attributes */
1508c2ecf20Sopenharmony_ci	.iq					= {
1518c2ecf20Sopenharmony_ci		.max_iqs			= CN6XXX_CFG_IO_QUEUES,
1528c2ecf20Sopenharmony_ci		.pending_list_size		=
1538c2ecf20Sopenharmony_ci			(CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES),
1548c2ecf20Sopenharmony_ci		.instr_type			= OCTEON_64BYTE_INSTR,
1558c2ecf20Sopenharmony_ci		.db_min				= CN6XXX_DB_MIN,
1568c2ecf20Sopenharmony_ci		.db_timeout			= CN6XXX_DB_TIMEOUT,
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci	,
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	/** OQ attributes */
1618c2ecf20Sopenharmony_ci	.oq					= {
1628c2ecf20Sopenharmony_ci		.max_oqs			= CN6XXX_CFG_IO_QUEUES,
1638c2ecf20Sopenharmony_ci		.refill_threshold		= CN6XXX_OQ_REFIL_THRESHOLD,
1648c2ecf20Sopenharmony_ci		.oq_intr_pkt			= CN6XXX_OQ_INTR_PKT,
1658c2ecf20Sopenharmony_ci		.oq_intr_time			= CN6XXX_OQ_INTR_TIME,
1668c2ecf20Sopenharmony_ci		.pkts_per_intr			= CN6XXX_OQ_PKTSPER_INTR,
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci	,
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	.num_nic_ports				= DEFAULT_NUM_NIC_PORTS_68XX,
1718c2ecf20Sopenharmony_ci	.num_def_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
1728c2ecf20Sopenharmony_ci	.num_def_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
1738c2ecf20Sopenharmony_ci	.def_rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	.nic_if_cfg[0] = {
1768c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
1778c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
1808c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
1838c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
1868c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
1898c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
1928c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
1958c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
1968c2ecf20Sopenharmony_ci		 */
1978c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		.gmx_port_id			= 0,
2028c2ecf20Sopenharmony_ci	},
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	.nic_if_cfg[1] = {
2058c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
2068c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
2098c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
2128c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
2158c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
2188c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
2218c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
2248c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
2258c2ecf20Sopenharmony_ci		 */
2268c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci		.gmx_port_id			= 1,
2318c2ecf20Sopenharmony_ci	},
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	.nic_if_cfg[2] = {
2348c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
2358c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
2388c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
2418c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
2448c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
2478c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
2508c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
2538c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
2548c2ecf20Sopenharmony_ci		 */
2558c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci		.gmx_port_id			= 2,
2608c2ecf20Sopenharmony_ci	},
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	.nic_if_cfg[3] = {
2638c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
2648c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
2678c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
2708c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
2738c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
2768c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
2798c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
2828c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
2838c2ecf20Sopenharmony_ci		 */
2848c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		.gmx_port_id			= 3,
2898c2ecf20Sopenharmony_ci	},
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/** Miscellaneous attributes */
2928c2ecf20Sopenharmony_ci	.misc					= {
2938c2ecf20Sopenharmony_ci		/* Host driver link query interval */
2948c2ecf20Sopenharmony_ci		.oct_link_query_interval	= 100,
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci		/* Octeon link query interval */
2978c2ecf20Sopenharmony_ci		.host_link_query_interval	= 500,
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		.enable_sli_oq_bp		= 0,
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		/* Control queue group */
3028c2ecf20Sopenharmony_ci		.ctrlq_grp			= 1,
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci	,
3058c2ecf20Sopenharmony_ci};
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci/** Default configuration
3088c2ecf20Sopenharmony_ci *  for CN68XX OCTEON Model.
3098c2ecf20Sopenharmony_ci */
3108c2ecf20Sopenharmony_cistatic struct octeon_config default_cn68xx_210nv_conf = {
3118c2ecf20Sopenharmony_ci	.card_type                              = LIO_210NV,
3128c2ecf20Sopenharmony_ci	.card_name                              = LIO_210NV_NAME,
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/** IQ attributes */
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	.iq					= {
3178c2ecf20Sopenharmony_ci		.max_iqs			= CN6XXX_CFG_IO_QUEUES,
3188c2ecf20Sopenharmony_ci		.pending_list_size		=
3198c2ecf20Sopenharmony_ci			(CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES),
3208c2ecf20Sopenharmony_ci		.instr_type			= OCTEON_64BYTE_INSTR,
3218c2ecf20Sopenharmony_ci		.db_min				= CN6XXX_DB_MIN,
3228c2ecf20Sopenharmony_ci		.db_timeout			= CN6XXX_DB_TIMEOUT,
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci	,
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/** OQ attributes */
3278c2ecf20Sopenharmony_ci	.oq					= {
3288c2ecf20Sopenharmony_ci		.max_oqs			= CN6XXX_CFG_IO_QUEUES,
3298c2ecf20Sopenharmony_ci		.refill_threshold		= CN6XXX_OQ_REFIL_THRESHOLD,
3308c2ecf20Sopenharmony_ci		.oq_intr_pkt			= CN6XXX_OQ_INTR_PKT,
3318c2ecf20Sopenharmony_ci		.oq_intr_time			= CN6XXX_OQ_INTR_TIME,
3328c2ecf20Sopenharmony_ci		.pkts_per_intr			= CN6XXX_OQ_PKTSPER_INTR,
3338c2ecf20Sopenharmony_ci	}
3348c2ecf20Sopenharmony_ci	,
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	.num_nic_ports			= DEFAULT_NUM_NIC_PORTS_68XX_210NV,
3378c2ecf20Sopenharmony_ci	.num_def_rx_descs		= CN6XXX_MAX_OQ_DESCRIPTORS,
3388c2ecf20Sopenharmony_ci	.num_def_tx_descs		= CN6XXX_MAX_IQ_DESCRIPTORS,
3398c2ecf20Sopenharmony_ci	.def_rx_buf_size		= CN6XXX_OQ_BUF_SIZE,
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	.nic_if_cfg[0] = {
3428c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
3438c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
3468c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
3498c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
3528c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
3558c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
3588c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
3618c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
3628c2ecf20Sopenharmony_ci		 */
3638c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		.gmx_port_id			= 0,
3688c2ecf20Sopenharmony_ci	},
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	.nic_if_cfg[1] = {
3718c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
3728c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
3758c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
3788c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
3818c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
3848c2ecf20Sopenharmony_ci		.num_rx_descs			= CN6XXX_MAX_OQ_DESCRIPTORS,
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
3878c2ecf20Sopenharmony_ci		.num_tx_descs			= CN6XXX_MAX_IQ_DESCRIPTORS,
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
3908c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
3918c2ecf20Sopenharmony_ci		 */
3928c2ecf20Sopenharmony_ci		.rx_buf_size			= CN6XXX_OQ_BUF_SIZE,
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		.gmx_port_id			= 1,
3978c2ecf20Sopenharmony_ci	},
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/** Miscellaneous attributes */
4008c2ecf20Sopenharmony_ci	.misc					= {
4018c2ecf20Sopenharmony_ci		/* Host driver link query interval */
4028c2ecf20Sopenharmony_ci		.oct_link_query_interval	= 100,
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		/* Octeon link query interval */
4058c2ecf20Sopenharmony_ci		.host_link_query_interval	= 500,
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci		.enable_sli_oq_bp		= 0,
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci		/* Control queue group */
4108c2ecf20Sopenharmony_ci		.ctrlq_grp			= 1,
4118c2ecf20Sopenharmony_ci	}
4128c2ecf20Sopenharmony_ci	,
4138c2ecf20Sopenharmony_ci};
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic struct octeon_config default_cn23xx_conf = {
4168c2ecf20Sopenharmony_ci	.card_type                              = LIO_23XX,
4178c2ecf20Sopenharmony_ci	.card_name                              = LIO_23XX_NAME,
4188c2ecf20Sopenharmony_ci	/** IQ attributes */
4198c2ecf20Sopenharmony_ci	.iq = {
4208c2ecf20Sopenharmony_ci		.max_iqs		= CN23XX_CFG_IO_QUEUES,
4218c2ecf20Sopenharmony_ci		.pending_list_size	= (CN23XX_DEFAULT_IQ_DESCRIPTORS *
4228c2ecf20Sopenharmony_ci					   CN23XX_CFG_IO_QUEUES),
4238c2ecf20Sopenharmony_ci		.instr_type		= OCTEON_64BYTE_INSTR,
4248c2ecf20Sopenharmony_ci		.db_min			= CN23XX_DB_MIN,
4258c2ecf20Sopenharmony_ci		.db_timeout		= CN23XX_DB_TIMEOUT,
4268c2ecf20Sopenharmony_ci		.iq_intr_pkt		= CN23XX_DEF_IQ_INTR_THRESHOLD,
4278c2ecf20Sopenharmony_ci	},
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	/** OQ attributes */
4308c2ecf20Sopenharmony_ci	.oq = {
4318c2ecf20Sopenharmony_ci		.max_oqs		= CN23XX_CFG_IO_QUEUES,
4328c2ecf20Sopenharmony_ci		.pkts_per_intr	= CN23XX_OQ_PKTSPER_INTR,
4338c2ecf20Sopenharmony_ci		.refill_threshold	= CN23XX_OQ_REFIL_THRESHOLD,
4348c2ecf20Sopenharmony_ci		.oq_intr_pkt	= CN23XX_OQ_INTR_PKT,
4358c2ecf20Sopenharmony_ci		.oq_intr_time	= CN23XX_OQ_INTR_TIME,
4368c2ecf20Sopenharmony_ci	},
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	.num_nic_ports				= DEFAULT_NUM_NIC_PORTS_23XX,
4398c2ecf20Sopenharmony_ci	.num_def_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,
4408c2ecf20Sopenharmony_ci	.num_def_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,
4418c2ecf20Sopenharmony_ci	.def_rx_buf_size			= CN23XX_OQ_BUF_SIZE,
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/* For ethernet interface 0:  Port cfg Attributes */
4448c2ecf20Sopenharmony_ci	.nic_if_cfg[0] = {
4458c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
4468c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
4498c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
4528c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
4558c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
4588c2ecf20Sopenharmony_ci		.num_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
4618c2ecf20Sopenharmony_ci		.num_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
4648c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
4658c2ecf20Sopenharmony_ci		 */
4668c2ecf20Sopenharmony_ci		.rx_buf_size			= CN23XX_OQ_BUF_SIZE,
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		.gmx_port_id			= 0,
4718c2ecf20Sopenharmony_ci	},
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	.nic_if_cfg[1] = {
4748c2ecf20Sopenharmony_ci		/* Max Txqs: Half for each of the two ports :max_iq/2 */
4758c2ecf20Sopenharmony_ci		.max_txqs			= MAX_TXQS_PER_INTF,
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_txqs */
4788c2ecf20Sopenharmony_ci		.num_txqs			= DEF_TXQS_PER_INTF,
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci		/* Max Rxqs: Half for each of the two ports :max_oq/2  */
4818c2ecf20Sopenharmony_ci		.max_rxqs			= MAX_RXQS_PER_INTF,
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci		/* Actual configured value. Range could be: 1...max_rxqs */
4848c2ecf20Sopenharmony_ci		.num_rxqs			= DEF_RXQS_PER_INTF,
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci		/* Num of desc for rx rings */
4878c2ecf20Sopenharmony_ci		.num_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		/* Num of desc for tx rings */
4908c2ecf20Sopenharmony_ci		.num_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci		/* SKB size, We need not change buf size even for Jumbo frames.
4938c2ecf20Sopenharmony_ci		 * Octeon can send jumbo frames in 4 consecutive descriptors,
4948c2ecf20Sopenharmony_ci		 */
4958c2ecf20Sopenharmony_ci		.rx_buf_size			= CN23XX_OQ_BUF_SIZE,
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci		.base_queue			= BASE_QUEUE_NOT_REQUESTED,
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci		.gmx_port_id			= 1,
5008c2ecf20Sopenharmony_ci	},
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	.misc					= {
5038c2ecf20Sopenharmony_ci		/* Host driver link query interval */
5048c2ecf20Sopenharmony_ci		.oct_link_query_interval	= 100,
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci		/* Octeon link query interval */
5078c2ecf20Sopenharmony_ci		.host_link_query_interval	= 500,
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		.enable_sli_oq_bp		= 0,
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci		/* Control queue group */
5128c2ecf20Sopenharmony_ci		.ctrlq_grp			= 1,
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci};
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic struct octeon_config_ptr {
5178c2ecf20Sopenharmony_ci	u32 conf_type;
5188c2ecf20Sopenharmony_ci} oct_conf_info[MAX_OCTEON_DEVICES] = {
5198c2ecf20Sopenharmony_ci	{
5208c2ecf20Sopenharmony_ci		OCTEON_CONFIG_TYPE_DEFAULT,
5218c2ecf20Sopenharmony_ci	}, {
5228c2ecf20Sopenharmony_ci		OCTEON_CONFIG_TYPE_DEFAULT,
5238c2ecf20Sopenharmony_ci	}, {
5248c2ecf20Sopenharmony_ci		OCTEON_CONFIG_TYPE_DEFAULT,
5258c2ecf20Sopenharmony_ci	}, {
5268c2ecf20Sopenharmony_ci		OCTEON_CONFIG_TYPE_DEFAULT,
5278c2ecf20Sopenharmony_ci	},
5288c2ecf20Sopenharmony_ci};
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic char oct_dev_state_str[OCT_DEV_STATES + 1][32] = {
5318c2ecf20Sopenharmony_ci	"BEGIN", "PCI-ENABLE-DONE", "PCI-MAP-DONE", "DISPATCH-INIT-DONE",
5328c2ecf20Sopenharmony_ci	"IQ-INIT-DONE", "SCBUFF-POOL-INIT-DONE", "RESPLIST-INIT-DONE",
5338c2ecf20Sopenharmony_ci	"DROQ-INIT-DONE", "MBOX-SETUP-DONE", "MSIX-ALLOC-VECTOR-DONE",
5348c2ecf20Sopenharmony_ci	"INTR-SET-DONE", "IO-QUEUES-INIT-DONE", "CONSOLE-INIT-DONE",
5358c2ecf20Sopenharmony_ci	"HOST-READY", "CORE-READY", "RUNNING", "IN-RESET",
5368c2ecf20Sopenharmony_ci	"INVALID"
5378c2ecf20Sopenharmony_ci};
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_cistatic char oct_dev_app_str[CVM_DRV_APP_COUNT + 1][32] = {
5408c2ecf20Sopenharmony_ci	"BASE", "NIC", "UNKNOWN"};
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic struct octeon_device *octeon_device[MAX_OCTEON_DEVICES];
5438c2ecf20Sopenharmony_cistatic atomic_t adapter_refcounts[MAX_OCTEON_DEVICES];
5448c2ecf20Sopenharmony_cistatic atomic_t adapter_fw_states[MAX_OCTEON_DEVICES];
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_cistatic u32 octeon_device_count;
5478c2ecf20Sopenharmony_ci/* locks device array (i.e. octeon_device[]) */
5488c2ecf20Sopenharmony_cistatic spinlock_t octeon_devices_lock;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_cistatic struct octeon_core_setup core_setup[MAX_OCTEON_DEVICES];
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cistatic void oct_set_config_info(int oct_id, int conf_type)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	if (conf_type < 0 || conf_type > (NUM_OCTEON_CONFS - 1))
5558c2ecf20Sopenharmony_ci		conf_type = OCTEON_CONFIG_TYPE_DEFAULT;
5568c2ecf20Sopenharmony_ci	oct_conf_info[oct_id].conf_type = conf_type;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_civoid octeon_init_device_list(int conf_type)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	int i;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	memset(octeon_device, 0, (sizeof(void *) * MAX_OCTEON_DEVICES));
5648c2ecf20Sopenharmony_ci	for (i = 0; i <  MAX_OCTEON_DEVICES; i++)
5658c2ecf20Sopenharmony_ci		oct_set_config_info(i, conf_type);
5668c2ecf20Sopenharmony_ci	spin_lock_init(&octeon_devices_lock);
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_cistatic void *__retrieve_octeon_config_info(struct octeon_device *oct,
5708c2ecf20Sopenharmony_ci					   u16 card_type)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	u32 oct_id = oct->octeon_id;
5738c2ecf20Sopenharmony_ci	void *ret = NULL;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	switch (oct_conf_info[oct_id].conf_type) {
5768c2ecf20Sopenharmony_ci	case OCTEON_CONFIG_TYPE_DEFAULT:
5778c2ecf20Sopenharmony_ci		if (oct->chip_id == OCTEON_CN66XX) {
5788c2ecf20Sopenharmony_ci			ret = &default_cn66xx_conf;
5798c2ecf20Sopenharmony_ci		} else if ((oct->chip_id == OCTEON_CN68XX) &&
5808c2ecf20Sopenharmony_ci			   (card_type == LIO_210NV)) {
5818c2ecf20Sopenharmony_ci			ret = &default_cn68xx_210nv_conf;
5828c2ecf20Sopenharmony_ci		} else if ((oct->chip_id == OCTEON_CN68XX) &&
5838c2ecf20Sopenharmony_ci			   (card_type == LIO_410NV)) {
5848c2ecf20Sopenharmony_ci			ret = &default_cn68xx_conf;
5858c2ecf20Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
5868c2ecf20Sopenharmony_ci			ret = &default_cn23xx_conf;
5878c2ecf20Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
5888c2ecf20Sopenharmony_ci			ret = &default_cn23xx_conf;
5898c2ecf20Sopenharmony_ci		}
5908c2ecf20Sopenharmony_ci		break;
5918c2ecf20Sopenharmony_ci	default:
5928c2ecf20Sopenharmony_ci		break;
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci	return ret;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic int __verify_octeon_config_info(struct octeon_device *oct, void *conf)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	switch (oct->chip_id) {
6008c2ecf20Sopenharmony_ci	case OCTEON_CN66XX:
6018c2ecf20Sopenharmony_ci	case OCTEON_CN68XX:
6028c2ecf20Sopenharmony_ci		return lio_validate_cn6xxx_config_info(oct, conf);
6038c2ecf20Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
6048c2ecf20Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
6058c2ecf20Sopenharmony_ci		return 0;
6068c2ecf20Sopenharmony_ci	default:
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	return 1;
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_civoid *oct_get_config_info(struct octeon_device *oct, u16 card_type)
6148c2ecf20Sopenharmony_ci{
6158c2ecf20Sopenharmony_ci	void *conf = NULL;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	conf = __retrieve_octeon_config_info(oct, card_type);
6188c2ecf20Sopenharmony_ci	if (!conf)
6198c2ecf20Sopenharmony_ci		return NULL;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (__verify_octeon_config_info(oct, conf)) {
6228c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Configuration verification failed\n");
6238c2ecf20Sopenharmony_ci		return NULL;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	return conf;
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_cichar *lio_get_state_string(atomic_t *state_ptr)
6308c2ecf20Sopenharmony_ci{
6318c2ecf20Sopenharmony_ci	s32 istate = (s32)atomic_read(state_ptr);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (istate > OCT_DEV_STATES || istate < 0)
6348c2ecf20Sopenharmony_ci		return oct_dev_state_str[OCT_DEV_STATE_INVALID];
6358c2ecf20Sopenharmony_ci	return oct_dev_state_str[istate];
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic char *get_oct_app_string(u32 app_mode)
6398c2ecf20Sopenharmony_ci{
6408c2ecf20Sopenharmony_ci	if (app_mode <= CVM_DRV_APP_END)
6418c2ecf20Sopenharmony_ci		return oct_dev_app_str[app_mode - CVM_DRV_APP_START];
6428c2ecf20Sopenharmony_ci	return oct_dev_app_str[CVM_DRV_INVALID_APP - CVM_DRV_APP_START];
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_civoid octeon_free_device_mem(struct octeon_device *oct)
6468c2ecf20Sopenharmony_ci{
6478c2ecf20Sopenharmony_ci	int i;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
6508c2ecf20Sopenharmony_ci		if (oct->io_qmask.oq & BIT_ULL(i))
6518c2ecf20Sopenharmony_ci			vfree(oct->droq[i]);
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
6558c2ecf20Sopenharmony_ci		if (oct->io_qmask.iq & BIT_ULL(i))
6568c2ecf20Sopenharmony_ci			vfree(oct->instr_queue[i]);
6578c2ecf20Sopenharmony_ci	}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	i = oct->octeon_id;
6608c2ecf20Sopenharmony_ci	vfree(oct);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	octeon_device[i] = NULL;
6638c2ecf20Sopenharmony_ci	octeon_device_count--;
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_cistatic struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
6678c2ecf20Sopenharmony_ci							u32 priv_size)
6688c2ecf20Sopenharmony_ci{
6698c2ecf20Sopenharmony_ci	struct octeon_device *oct;
6708c2ecf20Sopenharmony_ci	u8 *buf = NULL;
6718c2ecf20Sopenharmony_ci	u32 octdevsize = 0, configsize = 0, size;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	switch (pci_id) {
6748c2ecf20Sopenharmony_ci	case OCTEON_CN68XX:
6758c2ecf20Sopenharmony_ci	case OCTEON_CN66XX:
6768c2ecf20Sopenharmony_ci		configsize = sizeof(struct octeon_cn6xxx);
6778c2ecf20Sopenharmony_ci		break;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
6808c2ecf20Sopenharmony_ci		configsize = sizeof(struct octeon_cn23xx_pf);
6818c2ecf20Sopenharmony_ci		break;
6828c2ecf20Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
6838c2ecf20Sopenharmony_ci		configsize = sizeof(struct octeon_cn23xx_vf);
6848c2ecf20Sopenharmony_ci		break;
6858c2ecf20Sopenharmony_ci	default:
6868c2ecf20Sopenharmony_ci		pr_err("%s: Unknown PCI Device: 0x%x\n",
6878c2ecf20Sopenharmony_ci		       __func__,
6888c2ecf20Sopenharmony_ci		       pci_id);
6898c2ecf20Sopenharmony_ci		return NULL;
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	if (configsize & 0x7)
6938c2ecf20Sopenharmony_ci		configsize += (8 - (configsize & 0x7));
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	octdevsize = sizeof(struct octeon_device);
6968c2ecf20Sopenharmony_ci	if (octdevsize & 0x7)
6978c2ecf20Sopenharmony_ci		octdevsize += (8 - (octdevsize & 0x7));
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	if (priv_size & 0x7)
7008c2ecf20Sopenharmony_ci		priv_size += (8 - (priv_size & 0x7));
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	size = octdevsize + priv_size + configsize +
7038c2ecf20Sopenharmony_ci		(sizeof(struct octeon_dispatch) * DISPATCH_LIST_SIZE);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	buf = vzalloc(size);
7068c2ecf20Sopenharmony_ci	if (!buf)
7078c2ecf20Sopenharmony_ci		return NULL;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	oct = (struct octeon_device *)buf;
7108c2ecf20Sopenharmony_ci	oct->priv = (void *)(buf + octdevsize);
7118c2ecf20Sopenharmony_ci	oct->chip = (void *)(buf + octdevsize + priv_size);
7128c2ecf20Sopenharmony_ci	oct->dispatch.dlist = (struct octeon_dispatch *)
7138c2ecf20Sopenharmony_ci		(buf + octdevsize + priv_size + configsize);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	return oct;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_cistruct octeon_device *octeon_allocate_device(u32 pci_id,
7198c2ecf20Sopenharmony_ci					     u32 priv_size)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	u32 oct_idx = 0;
7228c2ecf20Sopenharmony_ci	struct octeon_device *oct = NULL;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	spin_lock(&octeon_devices_lock);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	for (oct_idx = 0; oct_idx < MAX_OCTEON_DEVICES; oct_idx++)
7278c2ecf20Sopenharmony_ci		if (!octeon_device[oct_idx])
7288c2ecf20Sopenharmony_ci			break;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (oct_idx < MAX_OCTEON_DEVICES) {
7318c2ecf20Sopenharmony_ci		oct = octeon_allocate_device_mem(pci_id, priv_size);
7328c2ecf20Sopenharmony_ci		if (oct) {
7338c2ecf20Sopenharmony_ci			octeon_device_count++;
7348c2ecf20Sopenharmony_ci			octeon_device[oct_idx] = oct;
7358c2ecf20Sopenharmony_ci		}
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	spin_unlock(&octeon_devices_lock);
7398c2ecf20Sopenharmony_ci	if (!oct)
7408c2ecf20Sopenharmony_ci		return NULL;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	spin_lock_init(&oct->pci_win_lock);
7438c2ecf20Sopenharmony_ci	spin_lock_init(&oct->mem_access_lock);
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	oct->octeon_id = oct_idx;
7468c2ecf20Sopenharmony_ci	snprintf(oct->device_name, sizeof(oct->device_name),
7478c2ecf20Sopenharmony_ci		 "LiquidIO%d", (oct->octeon_id));
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	return oct;
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci/** Register a device's bus location at initialization time.
7538c2ecf20Sopenharmony_ci *  @param octeon_dev - pointer to the octeon device structure.
7548c2ecf20Sopenharmony_ci *  @param bus        - PCIe bus #
7558c2ecf20Sopenharmony_ci *  @param dev        - PCIe device #
7568c2ecf20Sopenharmony_ci *  @param func       - PCIe function #
7578c2ecf20Sopenharmony_ci *  @param is_pf      - TRUE for PF, FALSE for VF
7588c2ecf20Sopenharmony_ci *  @return reference count of device's adapter
7598c2ecf20Sopenharmony_ci */
7608c2ecf20Sopenharmony_ciint octeon_register_device(struct octeon_device *oct,
7618c2ecf20Sopenharmony_ci			   int bus, int dev, int func, int is_pf)
7628c2ecf20Sopenharmony_ci{
7638c2ecf20Sopenharmony_ci	int idx, refcount;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	oct->loc.bus = bus;
7668c2ecf20Sopenharmony_ci	oct->loc.dev = dev;
7678c2ecf20Sopenharmony_ci	oct->loc.func = func;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	oct->adapter_refcount = &adapter_refcounts[oct->octeon_id];
7708c2ecf20Sopenharmony_ci	atomic_set(oct->adapter_refcount, 0);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	/* Like the reference count, the f/w state is shared 'per-adapter' */
7738c2ecf20Sopenharmony_ci	oct->adapter_fw_state = &adapter_fw_states[oct->octeon_id];
7748c2ecf20Sopenharmony_ci	atomic_set(oct->adapter_fw_state, FW_NEEDS_TO_BE_LOADED);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	spin_lock(&octeon_devices_lock);
7778c2ecf20Sopenharmony_ci	for (idx = (int)oct->octeon_id - 1; idx >= 0; idx--) {
7788c2ecf20Sopenharmony_ci		if (!octeon_device[idx]) {
7798c2ecf20Sopenharmony_ci			dev_err(&oct->pci_dev->dev,
7808c2ecf20Sopenharmony_ci				"%s: Internal driver error, missing dev",
7818c2ecf20Sopenharmony_ci				__func__);
7828c2ecf20Sopenharmony_ci			spin_unlock(&octeon_devices_lock);
7838c2ecf20Sopenharmony_ci			atomic_inc(oct->adapter_refcount);
7848c2ecf20Sopenharmony_ci			return 1; /* here, refcount is guaranteed to be 1 */
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci		/* If another device is at same bus/dev, use its refcounter
7878c2ecf20Sopenharmony_ci		 * (and f/w state variable).
7888c2ecf20Sopenharmony_ci		 */
7898c2ecf20Sopenharmony_ci		if ((octeon_device[idx]->loc.bus == bus) &&
7908c2ecf20Sopenharmony_ci		    (octeon_device[idx]->loc.dev == dev)) {
7918c2ecf20Sopenharmony_ci			oct->adapter_refcount =
7928c2ecf20Sopenharmony_ci				octeon_device[idx]->adapter_refcount;
7938c2ecf20Sopenharmony_ci			oct->adapter_fw_state =
7948c2ecf20Sopenharmony_ci				octeon_device[idx]->adapter_fw_state;
7958c2ecf20Sopenharmony_ci			break;
7968c2ecf20Sopenharmony_ci		}
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci	spin_unlock(&octeon_devices_lock);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	atomic_inc(oct->adapter_refcount);
8018c2ecf20Sopenharmony_ci	refcount = atomic_read(oct->adapter_refcount);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "%s: %02x:%02x:%d refcount %u", __func__,
8048c2ecf20Sopenharmony_ci		oct->loc.bus, oct->loc.dev, oct->loc.func, refcount);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	return refcount;
8078c2ecf20Sopenharmony_ci}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci/** Deregister a device at de-initialization time.
8108c2ecf20Sopenharmony_ci *  @param octeon_dev - pointer to the octeon device structure.
8118c2ecf20Sopenharmony_ci *  @return reference count of device's adapter
8128c2ecf20Sopenharmony_ci */
8138c2ecf20Sopenharmony_ciint octeon_deregister_device(struct octeon_device *oct)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	int refcount;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	atomic_dec(oct->adapter_refcount);
8188c2ecf20Sopenharmony_ci	refcount = atomic_read(oct->adapter_refcount);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "%s: %04d:%02d:%d refcount %u", __func__,
8218c2ecf20Sopenharmony_ci		oct->loc.bus, oct->loc.dev, oct->loc.func, refcount);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	return refcount;
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ciint
8278c2ecf20Sopenharmony_ciocteon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs)
8288c2ecf20Sopenharmony_ci{
8298c2ecf20Sopenharmony_ci	struct octeon_ioq_vector *ioq_vector;
8308c2ecf20Sopenharmony_ci	int cpu_num;
8318c2ecf20Sopenharmony_ci	int size;
8328c2ecf20Sopenharmony_ci	int i;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	size = sizeof(struct octeon_ioq_vector) * num_ioqs;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	oct->ioq_vector = vzalloc(size);
8378c2ecf20Sopenharmony_ci	if (!oct->ioq_vector)
8388c2ecf20Sopenharmony_ci		return -1;
8398c2ecf20Sopenharmony_ci	for (i = 0; i < num_ioqs; i++) {
8408c2ecf20Sopenharmony_ci		ioq_vector		= &oct->ioq_vector[i];
8418c2ecf20Sopenharmony_ci		ioq_vector->oct_dev	= oct;
8428c2ecf20Sopenharmony_ci		ioq_vector->iq_index	= i;
8438c2ecf20Sopenharmony_ci		ioq_vector->droq_index	= i;
8448c2ecf20Sopenharmony_ci		ioq_vector->mbox	= oct->mbox[i];
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci		cpu_num = i % num_online_cpus();
8478c2ecf20Sopenharmony_ci		cpumask_set_cpu(cpu_num, &ioq_vector->affinity_mask);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci		if (oct->chip_id == OCTEON_CN23XX_PF_VID)
8508c2ecf20Sopenharmony_ci			ioq_vector->ioq_num	= i + oct->sriov_info.pf_srn;
8518c2ecf20Sopenharmony_ci		else
8528c2ecf20Sopenharmony_ci			ioq_vector->ioq_num	= i;
8538c2ecf20Sopenharmony_ci	}
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	return 0;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_civoid
8598c2ecf20Sopenharmony_ciocteon_free_ioq_vector(struct octeon_device *oct)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	vfree(oct->ioq_vector);
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci/* this function is only for setting up the first queue */
8658c2ecf20Sopenharmony_ciint octeon_setup_instr_queues(struct octeon_device *oct)
8668c2ecf20Sopenharmony_ci{
8678c2ecf20Sopenharmony_ci	u32 num_descs = 0;
8688c2ecf20Sopenharmony_ci	u32 iq_no = 0;
8698c2ecf20Sopenharmony_ci	union oct_txpciq txpciq;
8708c2ecf20Sopenharmony_ci	int numa_node = dev_to_node(&oct->pci_dev->dev);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct))
8738c2ecf20Sopenharmony_ci		num_descs =
8748c2ecf20Sopenharmony_ci			CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx));
8758c2ecf20Sopenharmony_ci	else if (OCTEON_CN23XX_PF(oct))
8768c2ecf20Sopenharmony_ci		num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf));
8778c2ecf20Sopenharmony_ci	else if (OCTEON_CN23XX_VF(oct))
8788c2ecf20Sopenharmony_ci		num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_vf));
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	oct->num_iqs = 0;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	oct->instr_queue[0] = vzalloc_node(sizeof(*oct->instr_queue[0]),
8838c2ecf20Sopenharmony_ci				numa_node);
8848c2ecf20Sopenharmony_ci	if (!oct->instr_queue[0])
8858c2ecf20Sopenharmony_ci		oct->instr_queue[0] =
8868c2ecf20Sopenharmony_ci			vzalloc(sizeof(struct octeon_instr_queue));
8878c2ecf20Sopenharmony_ci	if (!oct->instr_queue[0])
8888c2ecf20Sopenharmony_ci		return 1;
8898c2ecf20Sopenharmony_ci	memset(oct->instr_queue[0], 0, sizeof(struct octeon_instr_queue));
8908c2ecf20Sopenharmony_ci	oct->instr_queue[0]->q_index = 0;
8918c2ecf20Sopenharmony_ci	oct->instr_queue[0]->app_ctx = (void *)(size_t)0;
8928c2ecf20Sopenharmony_ci	oct->instr_queue[0]->ifidx = 0;
8938c2ecf20Sopenharmony_ci	txpciq.u64 = 0;
8948c2ecf20Sopenharmony_ci	txpciq.s.q_no = iq_no;
8958c2ecf20Sopenharmony_ci	txpciq.s.pkind = oct->pfvf_hsword.pkind;
8968c2ecf20Sopenharmony_ci	txpciq.s.use_qpg = 0;
8978c2ecf20Sopenharmony_ci	txpciq.s.qpg = 0;
8988c2ecf20Sopenharmony_ci	if (octeon_init_instr_queue(oct, txpciq, num_descs)) {
8998c2ecf20Sopenharmony_ci		/* prevent memory leak */
9008c2ecf20Sopenharmony_ci		vfree(oct->instr_queue[0]);
9018c2ecf20Sopenharmony_ci		oct->instr_queue[0] = NULL;
9028c2ecf20Sopenharmony_ci		return 1;
9038c2ecf20Sopenharmony_ci	}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	oct->num_iqs++;
9068c2ecf20Sopenharmony_ci	return 0;
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ciint octeon_setup_output_queues(struct octeon_device *oct)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	u32 num_descs = 0;
9128c2ecf20Sopenharmony_ci	u32 desc_size = 0;
9138c2ecf20Sopenharmony_ci	u32 oq_no = 0;
9148c2ecf20Sopenharmony_ci	int numa_node = dev_to_node(&oct->pci_dev->dev);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
9178c2ecf20Sopenharmony_ci		num_descs =
9188c2ecf20Sopenharmony_ci			CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn6xxx));
9198c2ecf20Sopenharmony_ci		desc_size =
9208c2ecf20Sopenharmony_ci			CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn6xxx));
9218c2ecf20Sopenharmony_ci	} else if (OCTEON_CN23XX_PF(oct)) {
9228c2ecf20Sopenharmony_ci		num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf));
9238c2ecf20Sopenharmony_ci		desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf));
9248c2ecf20Sopenharmony_ci	} else if (OCTEON_CN23XX_VF(oct)) {
9258c2ecf20Sopenharmony_ci		num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_vf));
9268c2ecf20Sopenharmony_ci		desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_vf));
9278c2ecf20Sopenharmony_ci	}
9288c2ecf20Sopenharmony_ci	oct->num_oqs = 0;
9298c2ecf20Sopenharmony_ci	oct->droq[0] = vzalloc_node(sizeof(*oct->droq[0]), numa_node);
9308c2ecf20Sopenharmony_ci	if (!oct->droq[0])
9318c2ecf20Sopenharmony_ci		oct->droq[0] = vzalloc(sizeof(*oct->droq[0]));
9328c2ecf20Sopenharmony_ci	if (!oct->droq[0])
9338c2ecf20Sopenharmony_ci		return 1;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL)) {
9368c2ecf20Sopenharmony_ci		vfree(oct->droq[oq_no]);
9378c2ecf20Sopenharmony_ci		oct->droq[oq_no] = NULL;
9388c2ecf20Sopenharmony_ci		return 1;
9398c2ecf20Sopenharmony_ci	}
9408c2ecf20Sopenharmony_ci	oct->num_oqs++;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	return 0;
9438c2ecf20Sopenharmony_ci}
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ciint octeon_set_io_queues_off(struct octeon_device *oct)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	int loop = BUSY_READING_REG_VF_LOOP_COUNT;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
9508c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
9518c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
9528c2ecf20Sopenharmony_ci	} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
9538c2ecf20Sopenharmony_ci		u32 q_no;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci		/* IOQs will already be in reset.
9568c2ecf20Sopenharmony_ci		 * If RST bit is set, wait for quiet bit to be set.
9578c2ecf20Sopenharmony_ci		 * Once quiet bit is set, clear the RST bit.
9588c2ecf20Sopenharmony_ci		 */
9598c2ecf20Sopenharmony_ci		for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
9608c2ecf20Sopenharmony_ci			u64 reg_val = octeon_read_csr64(
9618c2ecf20Sopenharmony_ci				oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci			while ((reg_val & CN23XX_PKT_INPUT_CTL_RST) &&
9648c2ecf20Sopenharmony_ci			       !(reg_val &  CN23XX_PKT_INPUT_CTL_QUIET) &&
9658c2ecf20Sopenharmony_ci			       loop) {
9668c2ecf20Sopenharmony_ci				reg_val = octeon_read_csr64(
9678c2ecf20Sopenharmony_ci					oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
9688c2ecf20Sopenharmony_ci				loop--;
9698c2ecf20Sopenharmony_ci			}
9708c2ecf20Sopenharmony_ci			if (!loop) {
9718c2ecf20Sopenharmony_ci				dev_err(&oct->pci_dev->dev,
9728c2ecf20Sopenharmony_ci					"clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
9738c2ecf20Sopenharmony_ci					q_no);
9748c2ecf20Sopenharmony_ci				return -1;
9758c2ecf20Sopenharmony_ci			}
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci			reg_val = reg_val & ~CN23XX_PKT_INPUT_CTL_RST;
9788c2ecf20Sopenharmony_ci			octeon_write_csr64(oct,
9798c2ecf20Sopenharmony_ci					   CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
9808c2ecf20Sopenharmony_ci					   reg_val);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci			reg_val = octeon_read_csr64(
9838c2ecf20Sopenharmony_ci					oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
9848c2ecf20Sopenharmony_ci			if (reg_val & CN23XX_PKT_INPUT_CTL_RST) {
9858c2ecf20Sopenharmony_ci				dev_err(&oct->pci_dev->dev,
9868c2ecf20Sopenharmony_ci					"unable to reset qno %u\n", q_no);
9878c2ecf20Sopenharmony_ci				return -1;
9888c2ecf20Sopenharmony_ci			}
9898c2ecf20Sopenharmony_ci		}
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci	return 0;
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_civoid octeon_set_droq_pkt_op(struct octeon_device *oct,
9958c2ecf20Sopenharmony_ci			    u32 q_no,
9968c2ecf20Sopenharmony_ci			    u32 enable)
9978c2ecf20Sopenharmony_ci{
9988c2ecf20Sopenharmony_ci	u32 reg_val = 0;
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	/* Disable the i/p and o/p queues for this Octeon. */
10018c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
10028c2ecf20Sopenharmony_ci		reg_val = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		if (enable)
10058c2ecf20Sopenharmony_ci			reg_val = reg_val | (1 << q_no);
10068c2ecf20Sopenharmony_ci		else
10078c2ecf20Sopenharmony_ci			reg_val = reg_val & (~(1 << q_no));
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, reg_val);
10108c2ecf20Sopenharmony_ci	}
10118c2ecf20Sopenharmony_ci}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ciint octeon_init_dispatch_list(struct octeon_device *oct)
10148c2ecf20Sopenharmony_ci{
10158c2ecf20Sopenharmony_ci	u32 i;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	oct->dispatch.count = 0;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	for (i = 0; i < DISPATCH_LIST_SIZE; i++) {
10208c2ecf20Sopenharmony_ci		oct->dispatch.dlist[i].opcode = 0;
10218c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&oct->dispatch.dlist[i].list);
10228c2ecf20Sopenharmony_ci	}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	for (i = 0; i <= REQTYPE_LAST; i++)
10258c2ecf20Sopenharmony_ci		octeon_register_reqtype_free_fn(oct, i, NULL);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	spin_lock_init(&oct->dispatch.lock);
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	return 0;
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_civoid octeon_delete_dispatch_list(struct octeon_device *oct)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	u32 i;
10358c2ecf20Sopenharmony_ci	struct list_head freelist, *temp, *tmp2;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&freelist);
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	spin_lock_bh(&oct->dispatch.lock);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	for (i = 0; i < DISPATCH_LIST_SIZE; i++) {
10428c2ecf20Sopenharmony_ci		struct list_head *dispatch;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci		dispatch = &oct->dispatch.dlist[i].list;
10458c2ecf20Sopenharmony_ci		while (dispatch->next != dispatch) {
10468c2ecf20Sopenharmony_ci			temp = dispatch->next;
10478c2ecf20Sopenharmony_ci			list_move_tail(temp, &freelist);
10488c2ecf20Sopenharmony_ci		}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		oct->dispatch.dlist[i].opcode = 0;
10518c2ecf20Sopenharmony_ci	}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	oct->dispatch.count = 0;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	spin_unlock_bh(&oct->dispatch.lock);
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	list_for_each_safe(temp, tmp2, &freelist) {
10588c2ecf20Sopenharmony_ci		list_del(temp);
10598c2ecf20Sopenharmony_ci		kfree(temp);
10608c2ecf20Sopenharmony_ci	}
10618c2ecf20Sopenharmony_ci}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ciocteon_dispatch_fn_t
10648c2ecf20Sopenharmony_ciocteon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode,
10658c2ecf20Sopenharmony_ci		    u16 subcode)
10668c2ecf20Sopenharmony_ci{
10678c2ecf20Sopenharmony_ci	u32 idx;
10688c2ecf20Sopenharmony_ci	struct list_head *dispatch;
10698c2ecf20Sopenharmony_ci	octeon_dispatch_fn_t fn = NULL;
10708c2ecf20Sopenharmony_ci	u16 combined_opcode = OPCODE_SUBCODE(opcode, subcode);
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	idx = combined_opcode & OCTEON_OPCODE_MASK;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	spin_lock_bh(&octeon_dev->dispatch.lock);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	if (octeon_dev->dispatch.count == 0) {
10778c2ecf20Sopenharmony_ci		spin_unlock_bh(&octeon_dev->dispatch.lock);
10788c2ecf20Sopenharmony_ci		return NULL;
10798c2ecf20Sopenharmony_ci	}
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	if (!(octeon_dev->dispatch.dlist[idx].opcode)) {
10828c2ecf20Sopenharmony_ci		spin_unlock_bh(&octeon_dev->dispatch.lock);
10838c2ecf20Sopenharmony_ci		return NULL;
10848c2ecf20Sopenharmony_ci	}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	if (octeon_dev->dispatch.dlist[idx].opcode == combined_opcode) {
10878c2ecf20Sopenharmony_ci		fn = octeon_dev->dispatch.dlist[idx].dispatch_fn;
10888c2ecf20Sopenharmony_ci	} else {
10898c2ecf20Sopenharmony_ci		list_for_each(dispatch,
10908c2ecf20Sopenharmony_ci			      &octeon_dev->dispatch.dlist[idx].list) {
10918c2ecf20Sopenharmony_ci			if (((struct octeon_dispatch *)dispatch)->opcode ==
10928c2ecf20Sopenharmony_ci			    combined_opcode) {
10938c2ecf20Sopenharmony_ci				fn = ((struct octeon_dispatch *)
10948c2ecf20Sopenharmony_ci				      dispatch)->dispatch_fn;
10958c2ecf20Sopenharmony_ci				break;
10968c2ecf20Sopenharmony_ci			}
10978c2ecf20Sopenharmony_ci		}
10988c2ecf20Sopenharmony_ci	}
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	spin_unlock_bh(&octeon_dev->dispatch.lock);
11018c2ecf20Sopenharmony_ci	return fn;
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci/* octeon_register_dispatch_fn
11058c2ecf20Sopenharmony_ci * Parameters:
11068c2ecf20Sopenharmony_ci *   octeon_id - id of the octeon device.
11078c2ecf20Sopenharmony_ci *   opcode    - opcode for which driver should call the registered function
11088c2ecf20Sopenharmony_ci *   subcode   - subcode for which driver should call the registered function
11098c2ecf20Sopenharmony_ci *   fn        - The function to call when a packet with "opcode" arrives in
11108c2ecf20Sopenharmony_ci *		  octeon output queues.
11118c2ecf20Sopenharmony_ci *   fn_arg    - The argument to be passed when calling function "fn".
11128c2ecf20Sopenharmony_ci * Description:
11138c2ecf20Sopenharmony_ci *   Registers a function and its argument to be called when a packet
11148c2ecf20Sopenharmony_ci *   arrives in Octeon output queues with "opcode".
11158c2ecf20Sopenharmony_ci * Returns:
11168c2ecf20Sopenharmony_ci *   Success: 0
11178c2ecf20Sopenharmony_ci *   Failure: 1
11188c2ecf20Sopenharmony_ci * Locks:
11198c2ecf20Sopenharmony_ci *   No locks are held.
11208c2ecf20Sopenharmony_ci */
11218c2ecf20Sopenharmony_ciint
11228c2ecf20Sopenharmony_ciocteon_register_dispatch_fn(struct octeon_device *oct,
11238c2ecf20Sopenharmony_ci			    u16 opcode,
11248c2ecf20Sopenharmony_ci			    u16 subcode,
11258c2ecf20Sopenharmony_ci			    octeon_dispatch_fn_t fn, void *fn_arg)
11268c2ecf20Sopenharmony_ci{
11278c2ecf20Sopenharmony_ci	u32 idx;
11288c2ecf20Sopenharmony_ci	octeon_dispatch_fn_t pfn;
11298c2ecf20Sopenharmony_ci	u16 combined_opcode = OPCODE_SUBCODE(opcode, subcode);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	idx = combined_opcode & OCTEON_OPCODE_MASK;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	spin_lock_bh(&oct->dispatch.lock);
11348c2ecf20Sopenharmony_ci	/* Add dispatch function to first level of lookup table */
11358c2ecf20Sopenharmony_ci	if (oct->dispatch.dlist[idx].opcode == 0) {
11368c2ecf20Sopenharmony_ci		oct->dispatch.dlist[idx].opcode = combined_opcode;
11378c2ecf20Sopenharmony_ci		oct->dispatch.dlist[idx].dispatch_fn = fn;
11388c2ecf20Sopenharmony_ci		oct->dispatch.dlist[idx].arg = fn_arg;
11398c2ecf20Sopenharmony_ci		oct->dispatch.count++;
11408c2ecf20Sopenharmony_ci		spin_unlock_bh(&oct->dispatch.lock);
11418c2ecf20Sopenharmony_ci		return 0;
11428c2ecf20Sopenharmony_ci	}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	spin_unlock_bh(&oct->dispatch.lock);
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	/* Check if there was a function already registered for this
11478c2ecf20Sopenharmony_ci	 * opcode/subcode.
11488c2ecf20Sopenharmony_ci	 */
11498c2ecf20Sopenharmony_ci	pfn = octeon_get_dispatch(oct, opcode, subcode);
11508c2ecf20Sopenharmony_ci	if (!pfn) {
11518c2ecf20Sopenharmony_ci		struct octeon_dispatch *dispatch;
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev,
11548c2ecf20Sopenharmony_ci			"Adding opcode to dispatch list linked list\n");
11558c2ecf20Sopenharmony_ci		dispatch = kmalloc(sizeof(*dispatch), GFP_KERNEL);
11568c2ecf20Sopenharmony_ci		if (!dispatch)
11578c2ecf20Sopenharmony_ci			return 1;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci		dispatch->opcode = combined_opcode;
11608c2ecf20Sopenharmony_ci		dispatch->dispatch_fn = fn;
11618c2ecf20Sopenharmony_ci		dispatch->arg = fn_arg;
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci		/* Add dispatch function to linked list of fn ptrs
11648c2ecf20Sopenharmony_ci		 * at the hashed index.
11658c2ecf20Sopenharmony_ci		 */
11668c2ecf20Sopenharmony_ci		spin_lock_bh(&oct->dispatch.lock);
11678c2ecf20Sopenharmony_ci		list_add(&dispatch->list, &oct->dispatch.dlist[idx].list);
11688c2ecf20Sopenharmony_ci		oct->dispatch.count++;
11698c2ecf20Sopenharmony_ci		spin_unlock_bh(&oct->dispatch.lock);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	} else {
11728c2ecf20Sopenharmony_ci		if (pfn == fn &&
11738c2ecf20Sopenharmony_ci		    octeon_get_dispatch_arg(oct, opcode, subcode) == fn_arg)
11748c2ecf20Sopenharmony_ci			return 0;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
11778c2ecf20Sopenharmony_ci			"Found previously registered dispatch fn for opcode/subcode: %x/%x\n",
11788c2ecf20Sopenharmony_ci			opcode, subcode);
11798c2ecf20Sopenharmony_ci		return 1;
11808c2ecf20Sopenharmony_ci	}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	return 0;
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ciint octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	u32 i;
11888c2ecf20Sopenharmony_ci	char app_name[16];
11898c2ecf20Sopenharmony_ci	struct octeon_device *oct = (struct octeon_device *)buf;
11908c2ecf20Sopenharmony_ci	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
11918c2ecf20Sopenharmony_ci	struct octeon_core_setup *cs = NULL;
11928c2ecf20Sopenharmony_ci	u32 num_nic_ports = 0;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct))
11958c2ecf20Sopenharmony_ci		num_nic_ports =
11968c2ecf20Sopenharmony_ci			CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn6xxx));
11978c2ecf20Sopenharmony_ci	else if (OCTEON_CN23XX_PF(oct))
11988c2ecf20Sopenharmony_ci		num_nic_ports =
11998c2ecf20Sopenharmony_ci			CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn23xx_pf));
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	if (atomic_read(&oct->status) >= OCT_DEV_RUNNING) {
12028c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Received CORE OK when device state is 0x%x\n",
12038c2ecf20Sopenharmony_ci			atomic_read(&oct->status));
12048c2ecf20Sopenharmony_ci		goto core_drv_init_err;
12058c2ecf20Sopenharmony_ci	}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	strncpy(app_name,
12088c2ecf20Sopenharmony_ci		get_oct_app_string(
12098c2ecf20Sopenharmony_ci		(u32)recv_pkt->rh.r_core_drv_init.app_mode),
12108c2ecf20Sopenharmony_ci		sizeof(app_name) - 1);
12118c2ecf20Sopenharmony_ci	oct->app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode;
12128c2ecf20Sopenharmony_ci	if (recv_pkt->rh.r_core_drv_init.app_mode == CVM_DRV_NIC_APP) {
12138c2ecf20Sopenharmony_ci		oct->fw_info.max_nic_ports =
12148c2ecf20Sopenharmony_ci			(u32)recv_pkt->rh.r_core_drv_init.max_nic_ports;
12158c2ecf20Sopenharmony_ci		oct->fw_info.num_gmx_ports =
12168c2ecf20Sopenharmony_ci			(u32)recv_pkt->rh.r_core_drv_init.num_gmx_ports;
12178c2ecf20Sopenharmony_ci	}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (oct->fw_info.max_nic_ports < num_nic_ports) {
12208c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
12218c2ecf20Sopenharmony_ci			"Config has more ports than firmware allows (%d > %d).\n",
12228c2ecf20Sopenharmony_ci			num_nic_ports, oct->fw_info.max_nic_ports);
12238c2ecf20Sopenharmony_ci		goto core_drv_init_err;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci	oct->fw_info.app_cap_flags = recv_pkt->rh.r_core_drv_init.app_cap_flags;
12268c2ecf20Sopenharmony_ci	oct->fw_info.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode;
12278c2ecf20Sopenharmony_ci	oct->pfvf_hsword.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode;
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	oct->pfvf_hsword.pkind = recv_pkt->rh.r_core_drv_init.pkind;
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	for (i = 0; i < oct->num_iqs; i++)
12328c2ecf20Sopenharmony_ci		oct->instr_queue[i]->txpciq.s.pkind = oct->pfvf_hsword.pkind;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	atomic_set(&oct->status, OCT_DEV_CORE_OK);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	cs = &core_setup[oct->octeon_id];
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	if (recv_pkt->buffer_size[0] != (sizeof(*cs) + OCT_DROQ_INFO_SIZE)) {
12398c2ecf20Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "Core setup bytes expected %u found %d\n",
12408c2ecf20Sopenharmony_ci			(u32)sizeof(*cs),
12418c2ecf20Sopenharmony_ci			recv_pkt->buffer_size[0]);
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	memcpy(cs, get_rbd(
12458c2ecf20Sopenharmony_ci	       recv_pkt->buffer_ptr[0]) + OCT_DROQ_INFO_SIZE, sizeof(*cs));
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	strncpy(oct->boardinfo.name, cs->boardname, OCT_BOARD_NAME);
12488c2ecf20Sopenharmony_ci	strncpy(oct->boardinfo.serial_number, cs->board_serial_number,
12498c2ecf20Sopenharmony_ci		OCT_SERIAL_LEN);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	octeon_swap_8B_data((u64 *)cs, (sizeof(*cs) >> 3));
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	oct->boardinfo.major = cs->board_rev_major;
12548c2ecf20Sopenharmony_ci	oct->boardinfo.minor = cs->board_rev_minor;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	dev_info(&oct->pci_dev->dev,
12578c2ecf20Sopenharmony_ci		 "Running %s (%llu Hz)\n",
12588c2ecf20Sopenharmony_ci		 app_name, CVM_CAST64(cs->corefreq));
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_cicore_drv_init_err:
12618c2ecf20Sopenharmony_ci	for (i = 0; i < recv_pkt->buffer_count; i++)
12628c2ecf20Sopenharmony_ci		recv_buffer_free(recv_pkt->buffer_ptr[i]);
12638c2ecf20Sopenharmony_ci	octeon_free_recv_info(recv_info);
12648c2ecf20Sopenharmony_ci	return 0;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ciint octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci{
12708c2ecf20Sopenharmony_ci	if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES(oct)) &&
12718c2ecf20Sopenharmony_ci	    (oct->io_qmask.iq & BIT_ULL(q_no)))
12728c2ecf20Sopenharmony_ci		return oct->instr_queue[q_no]->max_count;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	return -1;
12758c2ecf20Sopenharmony_ci}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ciint octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
12788c2ecf20Sopenharmony_ci{
12798c2ecf20Sopenharmony_ci	if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES(oct)) &&
12808c2ecf20Sopenharmony_ci	    (oct->io_qmask.oq & BIT_ULL(q_no)))
12818c2ecf20Sopenharmony_ci		return oct->droq[q_no]->max_count;
12828c2ecf20Sopenharmony_ci	return -1;
12838c2ecf20Sopenharmony_ci}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci/* Retruns the host firmware handshake OCTEON specific configuration */
12868c2ecf20Sopenharmony_cistruct octeon_config *octeon_get_conf(struct octeon_device *oct)
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	struct octeon_config *default_oct_conf = NULL;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	/* check the OCTEON Device model & return the corresponding octeon
12918c2ecf20Sopenharmony_ci	 * configuration
12928c2ecf20Sopenharmony_ci	 */
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
12958c2ecf20Sopenharmony_ci		default_oct_conf =
12968c2ecf20Sopenharmony_ci			(struct octeon_config *)(CHIP_CONF(oct, cn6xxx));
12978c2ecf20Sopenharmony_ci	} else if (OCTEON_CN23XX_PF(oct)) {
12988c2ecf20Sopenharmony_ci		default_oct_conf = (struct octeon_config *)
12998c2ecf20Sopenharmony_ci			(CHIP_CONF(oct, cn23xx_pf));
13008c2ecf20Sopenharmony_ci	} else if (OCTEON_CN23XX_VF(oct)) {
13018c2ecf20Sopenharmony_ci		default_oct_conf = (struct octeon_config *)
13028c2ecf20Sopenharmony_ci			(CHIP_CONF(oct, cn23xx_vf));
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci	return default_oct_conf;
13058c2ecf20Sopenharmony_ci}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci/* scratch register address is same in all the OCT-II and CN70XX models */
13088c2ecf20Sopenharmony_ci#define CNXX_SLI_SCRATCH1   0x3C0
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci/* Get the octeon device pointer.
13118c2ecf20Sopenharmony_ci *  @param octeon_id  - The id for which the octeon device pointer is required.
13128c2ecf20Sopenharmony_ci *  @return Success: Octeon device pointer.
13138c2ecf20Sopenharmony_ci *  @return Failure: NULL.
13148c2ecf20Sopenharmony_ci */
13158c2ecf20Sopenharmony_cistruct octeon_device *lio_get_device(u32 octeon_id)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	if (octeon_id >= MAX_OCTEON_DEVICES)
13188c2ecf20Sopenharmony_ci		return NULL;
13198c2ecf20Sopenharmony_ci	else
13208c2ecf20Sopenharmony_ci		return octeon_device[octeon_id];
13218c2ecf20Sopenharmony_ci}
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ciu64 lio_pci_readq(struct octeon_device *oct, u64 addr)
13248c2ecf20Sopenharmony_ci{
13258c2ecf20Sopenharmony_ci	u64 val64;
13268c2ecf20Sopenharmony_ci	unsigned long flags;
13278c2ecf20Sopenharmony_ci	u32 addrhi;
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	spin_lock_irqsave(&oct->pci_win_lock, flags);
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	/* The windowed read happens when the LSB of the addr is written.
13328c2ecf20Sopenharmony_ci	 * So write MSB first
13338c2ecf20Sopenharmony_ci	 */
13348c2ecf20Sopenharmony_ci	addrhi = (addr >> 32);
13358c2ecf20Sopenharmony_ci	if ((oct->chip_id == OCTEON_CN66XX) ||
13368c2ecf20Sopenharmony_ci	    (oct->chip_id == OCTEON_CN68XX) ||
13378c2ecf20Sopenharmony_ci	    (oct->chip_id == OCTEON_CN23XX_PF_VID))
13388c2ecf20Sopenharmony_ci		addrhi |= 0x00060000;
13398c2ecf20Sopenharmony_ci	writel(addrhi, oct->reg_list.pci_win_rd_addr_hi);
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	/* Read back to preserve ordering of writes */
13428c2ecf20Sopenharmony_ci	readl(oct->reg_list.pci_win_rd_addr_hi);
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	writel(addr & 0xffffffff, oct->reg_list.pci_win_rd_addr_lo);
13458c2ecf20Sopenharmony_ci	readl(oct->reg_list.pci_win_rd_addr_lo);
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	val64 = readq(oct->reg_list.pci_win_rd_data);
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&oct->pci_win_lock, flags);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	return val64;
13528c2ecf20Sopenharmony_ci}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_civoid lio_pci_writeq(struct octeon_device *oct,
13558c2ecf20Sopenharmony_ci		    u64 val,
13568c2ecf20Sopenharmony_ci		    u64 addr)
13578c2ecf20Sopenharmony_ci{
13588c2ecf20Sopenharmony_ci	unsigned long flags;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	spin_lock_irqsave(&oct->pci_win_lock, flags);
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	writeq(addr, oct->reg_list.pci_win_wr_addr);
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	/* The write happens when the LSB is written. So write MSB first. */
13658c2ecf20Sopenharmony_ci	writel(val >> 32, oct->reg_list.pci_win_wr_data_hi);
13668c2ecf20Sopenharmony_ci	/* Read the MSB to ensure ordering of writes. */
13678c2ecf20Sopenharmony_ci	readl(oct->reg_list.pci_win_wr_data_hi);
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	writel(val & 0xffffffff, oct->reg_list.pci_win_wr_data_lo);
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&oct->pci_win_lock, flags);
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ciint octeon_mem_access_ok(struct octeon_device *oct)
13758c2ecf20Sopenharmony_ci{
13768c2ecf20Sopenharmony_ci	u64 access_okay = 0;
13778c2ecf20Sopenharmony_ci	u64 lmc0_reset_ctl;
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	/* Check to make sure a DDR interface is enabled */
13808c2ecf20Sopenharmony_ci	if (OCTEON_CN23XX_PF(oct)) {
13818c2ecf20Sopenharmony_ci		lmc0_reset_ctl = lio_pci_readq(oct, CN23XX_LMC0_RESET_CTL);
13828c2ecf20Sopenharmony_ci		access_okay =
13838c2ecf20Sopenharmony_ci			(lmc0_reset_ctl & CN23XX_LMC0_RESET_CTL_DDR3RST_MASK);
13848c2ecf20Sopenharmony_ci	} else {
13858c2ecf20Sopenharmony_ci		lmc0_reset_ctl = lio_pci_readq(oct, CN6XXX_LMC0_RESET_CTL);
13868c2ecf20Sopenharmony_ci		access_okay =
13878c2ecf20Sopenharmony_ci			(lmc0_reset_ctl & CN6XXX_LMC0_RESET_CTL_DDR3RST_MASK);
13888c2ecf20Sopenharmony_ci	}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	return access_okay ? 0 : 1;
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ciint octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
13948c2ecf20Sopenharmony_ci{
13958c2ecf20Sopenharmony_ci	int ret = 1;
13968c2ecf20Sopenharmony_ci	u32 ms;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	if (!timeout)
13998c2ecf20Sopenharmony_ci		return ret;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	for (ms = 0; (ret != 0) && ((*timeout == 0) || (ms <= *timeout));
14028c2ecf20Sopenharmony_ci	     ms += HZ / 10) {
14038c2ecf20Sopenharmony_ci		ret = octeon_mem_access_ok(oct);
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci		/* wait 100 ms */
14068c2ecf20Sopenharmony_ci		if (ret)
14078c2ecf20Sopenharmony_ci			schedule_timeout_uninterruptible(HZ / 10);
14088c2ecf20Sopenharmony_ci	}
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	return ret;
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci/* Get the octeon id assigned to the octeon device passed as argument.
14148c2ecf20Sopenharmony_ci *  This function is exported to other modules.
14158c2ecf20Sopenharmony_ci *  @param dev - octeon device pointer passed as a void *.
14168c2ecf20Sopenharmony_ci *  @return octeon device id
14178c2ecf20Sopenharmony_ci */
14188c2ecf20Sopenharmony_ciint lio_get_device_id(void *dev)
14198c2ecf20Sopenharmony_ci{
14208c2ecf20Sopenharmony_ci	struct octeon_device *octeon_dev = (struct octeon_device *)dev;
14218c2ecf20Sopenharmony_ci	u32 i;
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_DEVICES; i++)
14248c2ecf20Sopenharmony_ci		if (octeon_device[i] == octeon_dev)
14258c2ecf20Sopenharmony_ci			return octeon_dev->octeon_id;
14268c2ecf20Sopenharmony_ci	return -1;
14278c2ecf20Sopenharmony_ci}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_civoid lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
14308c2ecf20Sopenharmony_ci{
14318c2ecf20Sopenharmony_ci	u64 instr_cnt;
14328c2ecf20Sopenharmony_ci	u32 pkts_pend;
14338c2ecf20Sopenharmony_ci	struct octeon_device *oct = NULL;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	/* the whole thing needs to be atomic, ideally */
14368c2ecf20Sopenharmony_ci	if (droq) {
14378c2ecf20Sopenharmony_ci		pkts_pend = (u32)atomic_read(&droq->pkts_pending);
14388c2ecf20Sopenharmony_ci		writel(droq->pkt_count - pkts_pend, droq->pkts_sent_reg);
14398c2ecf20Sopenharmony_ci		droq->pkt_count = pkts_pend;
14408c2ecf20Sopenharmony_ci		oct = droq->oct_dev;
14418c2ecf20Sopenharmony_ci	}
14428c2ecf20Sopenharmony_ci	if (iq) {
14438c2ecf20Sopenharmony_ci		spin_lock_bh(&iq->lock);
14448c2ecf20Sopenharmony_ci		writel(iq->pkts_processed, iq->inst_cnt_reg);
14458c2ecf20Sopenharmony_ci		iq->pkt_in_done -= iq->pkts_processed;
14468c2ecf20Sopenharmony_ci		iq->pkts_processed = 0;
14478c2ecf20Sopenharmony_ci		/* this write needs to be flushed before we release the lock */
14488c2ecf20Sopenharmony_ci		spin_unlock_bh(&iq->lock);
14498c2ecf20Sopenharmony_ci		oct = iq->oct_dev;
14508c2ecf20Sopenharmony_ci	}
14518c2ecf20Sopenharmony_ci	/*write resend. Writing RESEND in SLI_PKTX_CNTS should be enough
14528c2ecf20Sopenharmony_ci	 *to trigger tx interrupts as well, if they are pending.
14538c2ecf20Sopenharmony_ci	 */
14548c2ecf20Sopenharmony_ci	if (oct && (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))) {
14558c2ecf20Sopenharmony_ci		if (droq)
14568c2ecf20Sopenharmony_ci			writeq(CN23XX_INTR_RESEND, droq->pkts_sent_reg);
14578c2ecf20Sopenharmony_ci		/*we race with firmrware here. read and write the IN_DONE_CNTS*/
14588c2ecf20Sopenharmony_ci		else if (iq) {
14598c2ecf20Sopenharmony_ci			instr_cnt =  readq(iq->inst_cnt_reg);
14608c2ecf20Sopenharmony_ci			writeq(((instr_cnt & 0xFFFFFFFF00000000ULL) |
14618c2ecf20Sopenharmony_ci				CN23XX_INTR_RESEND),
14628c2ecf20Sopenharmony_ci			       iq->inst_cnt_reg);
14638c2ecf20Sopenharmony_ci		}
14648c2ecf20Sopenharmony_ci	}
14658c2ecf20Sopenharmony_ci}
1466