162306a36Sopenharmony_ci/********************************************************************** 262306a36Sopenharmony_ci * Author: Cavium, Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Contact: support@cavium.com 562306a36Sopenharmony_ci * Please include "LiquidIO" in the subject. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 1162306a36Sopenharmony_ci * published by the Free Software Foundation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 1662306a36Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more details. 1762306a36Sopenharmony_ci ***********************************************************************/ 1862306a36Sopenharmony_ci#include <linux/pci.h> 1962306a36Sopenharmony_ci#include <linux/netdevice.h> 2062306a36Sopenharmony_ci#include <linux/vmalloc.h> 2162306a36Sopenharmony_ci#include "liquidio_common.h" 2262306a36Sopenharmony_ci#include "octeon_droq.h" 2362306a36Sopenharmony_ci#include "octeon_iq.h" 2462306a36Sopenharmony_ci#include "response_manager.h" 2562306a36Sopenharmony_ci#include "octeon_device.h" 2662306a36Sopenharmony_ci#include "octeon_main.h" 2762306a36Sopenharmony_ci#include "octeon_network.h" 2862306a36Sopenharmony_ci#include "cn66xx_regs.h" 2962306a36Sopenharmony_ci#include "cn66xx_device.h" 3062306a36Sopenharmony_ci#include "cn23xx_pf_device.h" 3162306a36Sopenharmony_ci#include "cn23xx_vf_device.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/** Default configuration 3462306a36Sopenharmony_ci * for CN66XX OCTEON Models. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_cistatic struct octeon_config default_cn66xx_conf = { 3762306a36Sopenharmony_ci .card_type = LIO_210SV, 3862306a36Sopenharmony_ci .card_name = LIO_210SV_NAME, 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /** IQ attributes */ 4162306a36Sopenharmony_ci .iq = { 4262306a36Sopenharmony_ci .max_iqs = CN6XXX_CFG_IO_QUEUES, 4362306a36Sopenharmony_ci .pending_list_size = 4462306a36Sopenharmony_ci (CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES), 4562306a36Sopenharmony_ci .instr_type = OCTEON_64BYTE_INSTR, 4662306a36Sopenharmony_ci .db_min = CN6XXX_DB_MIN, 4762306a36Sopenharmony_ci .db_timeout = CN6XXX_DB_TIMEOUT, 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci , 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /** OQ attributes */ 5262306a36Sopenharmony_ci .oq = { 5362306a36Sopenharmony_ci .max_oqs = CN6XXX_CFG_IO_QUEUES, 5462306a36Sopenharmony_ci .refill_threshold = CN6XXX_OQ_REFIL_THRESHOLD, 5562306a36Sopenharmony_ci .oq_intr_pkt = CN6XXX_OQ_INTR_PKT, 5662306a36Sopenharmony_ci .oq_intr_time = CN6XXX_OQ_INTR_TIME, 5762306a36Sopenharmony_ci .pkts_per_intr = CN6XXX_OQ_PKTSPER_INTR, 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci , 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci .num_nic_ports = DEFAULT_NUM_NIC_PORTS_66XX, 6262306a36Sopenharmony_ci .num_def_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 6362306a36Sopenharmony_ci .num_def_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 6462306a36Sopenharmony_ci .def_rx_buf_size = CN6XXX_OQ_BUF_SIZE, 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* For ethernet interface 0: Port cfg Attributes */ 6762306a36Sopenharmony_ci .nic_if_cfg[0] = { 6862306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 6962306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 7262306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 7562306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 7862306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Num of desc for rx rings */ 8162306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Num of desc for tx rings */ 8462306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 8762306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci .gmx_port_id = 0, 9462306a36Sopenharmony_ci }, 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci .nic_if_cfg[1] = { 9762306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 9862306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 10162306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 10462306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 10762306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Num of desc for rx rings */ 11062306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* Num of desc for tx rings */ 11362306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 11662306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci .gmx_port_id = 1, 12362306a36Sopenharmony_ci }, 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /** Miscellaneous attributes */ 12662306a36Sopenharmony_ci .misc = { 12762306a36Sopenharmony_ci /* Host driver link query interval */ 12862306a36Sopenharmony_ci .oct_link_query_interval = 100, 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Octeon link query interval */ 13162306a36Sopenharmony_ci .host_link_query_interval = 500, 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci .enable_sli_oq_bp = 0, 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* Control queue group */ 13662306a36Sopenharmony_ci .ctrlq_grp = 1, 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci , 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/** Default configuration 14262306a36Sopenharmony_ci * for CN68XX OCTEON Model. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic struct octeon_config default_cn68xx_conf = { 14662306a36Sopenharmony_ci .card_type = LIO_410NV, 14762306a36Sopenharmony_ci .card_name = LIO_410NV_NAME, 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /** IQ attributes */ 15062306a36Sopenharmony_ci .iq = { 15162306a36Sopenharmony_ci .max_iqs = CN6XXX_CFG_IO_QUEUES, 15262306a36Sopenharmony_ci .pending_list_size = 15362306a36Sopenharmony_ci (CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES), 15462306a36Sopenharmony_ci .instr_type = OCTEON_64BYTE_INSTR, 15562306a36Sopenharmony_ci .db_min = CN6XXX_DB_MIN, 15662306a36Sopenharmony_ci .db_timeout = CN6XXX_DB_TIMEOUT, 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci , 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /** OQ attributes */ 16162306a36Sopenharmony_ci .oq = { 16262306a36Sopenharmony_ci .max_oqs = CN6XXX_CFG_IO_QUEUES, 16362306a36Sopenharmony_ci .refill_threshold = CN6XXX_OQ_REFIL_THRESHOLD, 16462306a36Sopenharmony_ci .oq_intr_pkt = CN6XXX_OQ_INTR_PKT, 16562306a36Sopenharmony_ci .oq_intr_time = CN6XXX_OQ_INTR_TIME, 16662306a36Sopenharmony_ci .pkts_per_intr = CN6XXX_OQ_PKTSPER_INTR, 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci , 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci .num_nic_ports = DEFAULT_NUM_NIC_PORTS_68XX, 17162306a36Sopenharmony_ci .num_def_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 17262306a36Sopenharmony_ci .num_def_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 17362306a36Sopenharmony_ci .def_rx_buf_size = CN6XXX_OQ_BUF_SIZE, 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci .nic_if_cfg[0] = { 17662306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 17762306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 18062306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 18362306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 18662306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* Num of desc for rx rings */ 18962306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* Num of desc for tx rings */ 19262306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 19562306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci .gmx_port_id = 0, 20262306a36Sopenharmony_ci }, 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci .nic_if_cfg[1] = { 20562306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 20662306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 20962306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 21262306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 21562306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Num of desc for rx rings */ 21862306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Num of desc for tx rings */ 22162306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 22462306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci .gmx_port_id = 1, 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci .nic_if_cfg[2] = { 23462306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 23562306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 23862306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 24162306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 24462306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Num of desc for rx rings */ 24762306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* Num of desc for tx rings */ 25062306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 25362306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci .gmx_port_id = 2, 26062306a36Sopenharmony_ci }, 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci .nic_if_cfg[3] = { 26362306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 26462306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 26762306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 27062306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 27362306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Num of desc for rx rings */ 27662306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* Num of desc for tx rings */ 27962306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 28262306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci .gmx_port_id = 3, 28962306a36Sopenharmony_ci }, 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /** Miscellaneous attributes */ 29262306a36Sopenharmony_ci .misc = { 29362306a36Sopenharmony_ci /* Host driver link query interval */ 29462306a36Sopenharmony_ci .oct_link_query_interval = 100, 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Octeon link query interval */ 29762306a36Sopenharmony_ci .host_link_query_interval = 500, 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci .enable_sli_oq_bp = 0, 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* Control queue group */ 30262306a36Sopenharmony_ci .ctrlq_grp = 1, 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci , 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/** Default configuration 30862306a36Sopenharmony_ci * for CN68XX OCTEON Model. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_cistatic struct octeon_config default_cn68xx_210nv_conf = { 31162306a36Sopenharmony_ci .card_type = LIO_210NV, 31262306a36Sopenharmony_ci .card_name = LIO_210NV_NAME, 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /** IQ attributes */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci .iq = { 31762306a36Sopenharmony_ci .max_iqs = CN6XXX_CFG_IO_QUEUES, 31862306a36Sopenharmony_ci .pending_list_size = 31962306a36Sopenharmony_ci (CN6XXX_MAX_IQ_DESCRIPTORS * CN6XXX_CFG_IO_QUEUES), 32062306a36Sopenharmony_ci .instr_type = OCTEON_64BYTE_INSTR, 32162306a36Sopenharmony_ci .db_min = CN6XXX_DB_MIN, 32262306a36Sopenharmony_ci .db_timeout = CN6XXX_DB_TIMEOUT, 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci , 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /** OQ attributes */ 32762306a36Sopenharmony_ci .oq = { 32862306a36Sopenharmony_ci .max_oqs = CN6XXX_CFG_IO_QUEUES, 32962306a36Sopenharmony_ci .refill_threshold = CN6XXX_OQ_REFIL_THRESHOLD, 33062306a36Sopenharmony_ci .oq_intr_pkt = CN6XXX_OQ_INTR_PKT, 33162306a36Sopenharmony_ci .oq_intr_time = CN6XXX_OQ_INTR_TIME, 33262306a36Sopenharmony_ci .pkts_per_intr = CN6XXX_OQ_PKTSPER_INTR, 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci , 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci .num_nic_ports = DEFAULT_NUM_NIC_PORTS_68XX_210NV, 33762306a36Sopenharmony_ci .num_def_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 33862306a36Sopenharmony_ci .num_def_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 33962306a36Sopenharmony_ci .def_rx_buf_size = CN6XXX_OQ_BUF_SIZE, 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci .nic_if_cfg[0] = { 34262306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 34362306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 34662306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 34962306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 35262306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Num of desc for rx rings */ 35562306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* Num of desc for tx rings */ 35862306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 36162306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci .gmx_port_id = 0, 36862306a36Sopenharmony_ci }, 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci .nic_if_cfg[1] = { 37162306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 37262306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 37562306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 37862306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 38162306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Num of desc for rx rings */ 38462306a36Sopenharmony_ci .num_rx_descs = CN6XXX_MAX_OQ_DESCRIPTORS, 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* Num of desc for tx rings */ 38762306a36Sopenharmony_ci .num_tx_descs = CN6XXX_MAX_IQ_DESCRIPTORS, 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 39062306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_ci .rx_buf_size = CN6XXX_OQ_BUF_SIZE, 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci .gmx_port_id = 1, 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /** Miscellaneous attributes */ 40062306a36Sopenharmony_ci .misc = { 40162306a36Sopenharmony_ci /* Host driver link query interval */ 40262306a36Sopenharmony_ci .oct_link_query_interval = 100, 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* Octeon link query interval */ 40562306a36Sopenharmony_ci .host_link_query_interval = 500, 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci .enable_sli_oq_bp = 0, 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* Control queue group */ 41062306a36Sopenharmony_ci .ctrlq_grp = 1, 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci , 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic struct octeon_config default_cn23xx_conf = { 41662306a36Sopenharmony_ci .card_type = LIO_23XX, 41762306a36Sopenharmony_ci .card_name = LIO_23XX_NAME, 41862306a36Sopenharmony_ci /** IQ attributes */ 41962306a36Sopenharmony_ci .iq = { 42062306a36Sopenharmony_ci .max_iqs = CN23XX_CFG_IO_QUEUES, 42162306a36Sopenharmony_ci .pending_list_size = (CN23XX_DEFAULT_IQ_DESCRIPTORS * 42262306a36Sopenharmony_ci CN23XX_CFG_IO_QUEUES), 42362306a36Sopenharmony_ci .instr_type = OCTEON_64BYTE_INSTR, 42462306a36Sopenharmony_ci .db_min = CN23XX_DB_MIN, 42562306a36Sopenharmony_ci .db_timeout = CN23XX_DB_TIMEOUT, 42662306a36Sopenharmony_ci .iq_intr_pkt = CN23XX_DEF_IQ_INTR_THRESHOLD, 42762306a36Sopenharmony_ci }, 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci /** OQ attributes */ 43062306a36Sopenharmony_ci .oq = { 43162306a36Sopenharmony_ci .max_oqs = CN23XX_CFG_IO_QUEUES, 43262306a36Sopenharmony_ci .pkts_per_intr = CN23XX_OQ_PKTSPER_INTR, 43362306a36Sopenharmony_ci .refill_threshold = CN23XX_OQ_REFIL_THRESHOLD, 43462306a36Sopenharmony_ci .oq_intr_pkt = CN23XX_OQ_INTR_PKT, 43562306a36Sopenharmony_ci .oq_intr_time = CN23XX_OQ_INTR_TIME, 43662306a36Sopenharmony_ci }, 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci .num_nic_ports = DEFAULT_NUM_NIC_PORTS_23XX, 43962306a36Sopenharmony_ci .num_def_rx_descs = CN23XX_DEFAULT_OQ_DESCRIPTORS, 44062306a36Sopenharmony_ci .num_def_tx_descs = CN23XX_DEFAULT_IQ_DESCRIPTORS, 44162306a36Sopenharmony_ci .def_rx_buf_size = CN23XX_OQ_BUF_SIZE, 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci /* For ethernet interface 0: Port cfg Attributes */ 44462306a36Sopenharmony_ci .nic_if_cfg[0] = { 44562306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 44662306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 44962306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 45262306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 45562306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* Num of desc for rx rings */ 45862306a36Sopenharmony_ci .num_rx_descs = CN23XX_DEFAULT_OQ_DESCRIPTORS, 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* Num of desc for tx rings */ 46162306a36Sopenharmony_ci .num_tx_descs = CN23XX_DEFAULT_IQ_DESCRIPTORS, 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 46462306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 46562306a36Sopenharmony_ci */ 46662306a36Sopenharmony_ci .rx_buf_size = CN23XX_OQ_BUF_SIZE, 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci .gmx_port_id = 0, 47162306a36Sopenharmony_ci }, 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci .nic_if_cfg[1] = { 47462306a36Sopenharmony_ci /* Max Txqs: Half for each of the two ports :max_iq/2 */ 47562306a36Sopenharmony_ci .max_txqs = MAX_TXQS_PER_INTF, 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_txqs */ 47862306a36Sopenharmony_ci .num_txqs = DEF_TXQS_PER_INTF, 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* Max Rxqs: Half for each of the two ports :max_oq/2 */ 48162306a36Sopenharmony_ci .max_rxqs = MAX_RXQS_PER_INTF, 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* Actual configured value. Range could be: 1...max_rxqs */ 48462306a36Sopenharmony_ci .num_rxqs = DEF_RXQS_PER_INTF, 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* Num of desc for rx rings */ 48762306a36Sopenharmony_ci .num_rx_descs = CN23XX_DEFAULT_OQ_DESCRIPTORS, 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* Num of desc for tx rings */ 49062306a36Sopenharmony_ci .num_tx_descs = CN23XX_DEFAULT_IQ_DESCRIPTORS, 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* SKB size, We need not change buf size even for Jumbo frames. 49362306a36Sopenharmony_ci * Octeon can send jumbo frames in 4 consecutive descriptors, 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci .rx_buf_size = CN23XX_OQ_BUF_SIZE, 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci .base_queue = BASE_QUEUE_NOT_REQUESTED, 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci .gmx_port_id = 1, 50062306a36Sopenharmony_ci }, 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci .misc = { 50362306a36Sopenharmony_ci /* Host driver link query interval */ 50462306a36Sopenharmony_ci .oct_link_query_interval = 100, 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* Octeon link query interval */ 50762306a36Sopenharmony_ci .host_link_query_interval = 500, 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci .enable_sli_oq_bp = 0, 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* Control queue group */ 51262306a36Sopenharmony_ci .ctrlq_grp = 1, 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci}; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic struct octeon_config_ptr { 51762306a36Sopenharmony_ci u32 conf_type; 51862306a36Sopenharmony_ci} oct_conf_info[MAX_OCTEON_DEVICES] = { 51962306a36Sopenharmony_ci { 52062306a36Sopenharmony_ci OCTEON_CONFIG_TYPE_DEFAULT, 52162306a36Sopenharmony_ci }, { 52262306a36Sopenharmony_ci OCTEON_CONFIG_TYPE_DEFAULT, 52362306a36Sopenharmony_ci }, { 52462306a36Sopenharmony_ci OCTEON_CONFIG_TYPE_DEFAULT, 52562306a36Sopenharmony_ci }, { 52662306a36Sopenharmony_ci OCTEON_CONFIG_TYPE_DEFAULT, 52762306a36Sopenharmony_ci }, 52862306a36Sopenharmony_ci}; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic char oct_dev_state_str[OCT_DEV_STATES + 1][32] = { 53162306a36Sopenharmony_ci "BEGIN", "PCI-ENABLE-DONE", "PCI-MAP-DONE", "DISPATCH-INIT-DONE", 53262306a36Sopenharmony_ci "IQ-INIT-DONE", "SCBUFF-POOL-INIT-DONE", "RESPLIST-INIT-DONE", 53362306a36Sopenharmony_ci "DROQ-INIT-DONE", "MBOX-SETUP-DONE", "MSIX-ALLOC-VECTOR-DONE", 53462306a36Sopenharmony_ci "INTR-SET-DONE", "IO-QUEUES-INIT-DONE", "CONSOLE-INIT-DONE", 53562306a36Sopenharmony_ci "HOST-READY", "CORE-READY", "RUNNING", "IN-RESET", 53662306a36Sopenharmony_ci "INVALID" 53762306a36Sopenharmony_ci}; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic char oct_dev_app_str[CVM_DRV_APP_COUNT + 1][32] = { 54062306a36Sopenharmony_ci "BASE", "NIC", "UNKNOWN"}; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic struct octeon_device *octeon_device[MAX_OCTEON_DEVICES]; 54362306a36Sopenharmony_cistatic atomic_t adapter_refcounts[MAX_OCTEON_DEVICES]; 54462306a36Sopenharmony_cistatic atomic_t adapter_fw_states[MAX_OCTEON_DEVICES]; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic u32 octeon_device_count; 54762306a36Sopenharmony_ci/* locks device array (i.e. octeon_device[]) */ 54862306a36Sopenharmony_cistatic DEFINE_SPINLOCK(octeon_devices_lock); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic struct octeon_core_setup core_setup[MAX_OCTEON_DEVICES]; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_cistatic void oct_set_config_info(int oct_id, int conf_type) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci if (conf_type < 0 || conf_type > (NUM_OCTEON_CONFS - 1)) 55562306a36Sopenharmony_ci conf_type = OCTEON_CONFIG_TYPE_DEFAULT; 55662306a36Sopenharmony_ci oct_conf_info[oct_id].conf_type = conf_type; 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_civoid octeon_init_device_list(int conf_type) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci int i; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci memset(octeon_device, 0, (sizeof(void *) * MAX_OCTEON_DEVICES)); 56462306a36Sopenharmony_ci for (i = 0; i < MAX_OCTEON_DEVICES; i++) 56562306a36Sopenharmony_ci oct_set_config_info(i, conf_type); 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_init_device_list); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic void *__retrieve_octeon_config_info(struct octeon_device *oct, 57062306a36Sopenharmony_ci u16 card_type) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci u32 oct_id = oct->octeon_id; 57362306a36Sopenharmony_ci void *ret = NULL; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci switch (oct_conf_info[oct_id].conf_type) { 57662306a36Sopenharmony_ci case OCTEON_CONFIG_TYPE_DEFAULT: 57762306a36Sopenharmony_ci if (oct->chip_id == OCTEON_CN66XX) { 57862306a36Sopenharmony_ci ret = &default_cn66xx_conf; 57962306a36Sopenharmony_ci } else if ((oct->chip_id == OCTEON_CN68XX) && 58062306a36Sopenharmony_ci (card_type == LIO_210NV)) { 58162306a36Sopenharmony_ci ret = &default_cn68xx_210nv_conf; 58262306a36Sopenharmony_ci } else if ((oct->chip_id == OCTEON_CN68XX) && 58362306a36Sopenharmony_ci (card_type == LIO_410NV)) { 58462306a36Sopenharmony_ci ret = &default_cn68xx_conf; 58562306a36Sopenharmony_ci } else if (oct->chip_id == OCTEON_CN23XX_PF_VID) { 58662306a36Sopenharmony_ci ret = &default_cn23xx_conf; 58762306a36Sopenharmony_ci } else if (oct->chip_id == OCTEON_CN23XX_VF_VID) { 58862306a36Sopenharmony_ci ret = &default_cn23xx_conf; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci break; 59162306a36Sopenharmony_ci default: 59262306a36Sopenharmony_ci break; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci return ret; 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int __verify_octeon_config_info(struct octeon_device *oct, void *conf) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci switch (oct->chip_id) { 60062306a36Sopenharmony_ci case OCTEON_CN66XX: 60162306a36Sopenharmony_ci case OCTEON_CN68XX: 60262306a36Sopenharmony_ci return lio_validate_cn6xxx_config_info(oct, conf); 60362306a36Sopenharmony_ci case OCTEON_CN23XX_PF_VID: 60462306a36Sopenharmony_ci case OCTEON_CN23XX_VF_VID: 60562306a36Sopenharmony_ci return 0; 60662306a36Sopenharmony_ci default: 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci return 1; 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_civoid *oct_get_config_info(struct octeon_device *oct, u16 card_type) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci void *conf = NULL; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci conf = __retrieve_octeon_config_info(oct, card_type); 61862306a36Sopenharmony_ci if (!conf) 61962306a36Sopenharmony_ci return NULL; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (__verify_octeon_config_info(oct, conf)) { 62262306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, "Configuration verification failed\n"); 62362306a36Sopenharmony_ci return NULL; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return conf; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cichar *lio_get_state_string(atomic_t *state_ptr) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci s32 istate = (s32)atomic_read(state_ptr); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (istate > OCT_DEV_STATES || istate < 0) 63462306a36Sopenharmony_ci return oct_dev_state_str[OCT_DEV_STATE_INVALID]; 63562306a36Sopenharmony_ci return oct_dev_state_str[istate]; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_get_state_string); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic char *get_oct_app_string(u32 app_mode) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci if (app_mode <= CVM_DRV_APP_END) 64262306a36Sopenharmony_ci return oct_dev_app_str[app_mode - CVM_DRV_APP_START]; 64362306a36Sopenharmony_ci return oct_dev_app_str[CVM_DRV_INVALID_APP - CVM_DRV_APP_START]; 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_civoid octeon_free_device_mem(struct octeon_device *oct) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci int i; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) { 65162306a36Sopenharmony_ci if (oct->io_qmask.oq & BIT_ULL(i)) 65262306a36Sopenharmony_ci vfree(oct->droq[i]); 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { 65662306a36Sopenharmony_ci if (oct->io_qmask.iq & BIT_ULL(i)) 65762306a36Sopenharmony_ci vfree(oct->instr_queue[i]); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci i = oct->octeon_id; 66162306a36Sopenharmony_ci vfree(oct); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci octeon_device[i] = NULL; 66462306a36Sopenharmony_ci octeon_device_count--; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_free_device_mem); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic struct octeon_device *octeon_allocate_device_mem(u32 pci_id, 66962306a36Sopenharmony_ci u32 priv_size) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci struct octeon_device *oct; 67262306a36Sopenharmony_ci u8 *buf = NULL; 67362306a36Sopenharmony_ci u32 octdevsize = 0, configsize = 0, size; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci switch (pci_id) { 67662306a36Sopenharmony_ci case OCTEON_CN68XX: 67762306a36Sopenharmony_ci case OCTEON_CN66XX: 67862306a36Sopenharmony_ci configsize = sizeof(struct octeon_cn6xxx); 67962306a36Sopenharmony_ci break; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci case OCTEON_CN23XX_PF_VID: 68262306a36Sopenharmony_ci configsize = sizeof(struct octeon_cn23xx_pf); 68362306a36Sopenharmony_ci break; 68462306a36Sopenharmony_ci case OCTEON_CN23XX_VF_VID: 68562306a36Sopenharmony_ci configsize = sizeof(struct octeon_cn23xx_vf); 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci default: 68862306a36Sopenharmony_ci pr_err("%s: Unknown PCI Device: 0x%x\n", 68962306a36Sopenharmony_ci __func__, 69062306a36Sopenharmony_ci pci_id); 69162306a36Sopenharmony_ci return NULL; 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (configsize & 0x7) 69562306a36Sopenharmony_ci configsize += (8 - (configsize & 0x7)); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci octdevsize = sizeof(struct octeon_device); 69862306a36Sopenharmony_ci if (octdevsize & 0x7) 69962306a36Sopenharmony_ci octdevsize += (8 - (octdevsize & 0x7)); 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if (priv_size & 0x7) 70262306a36Sopenharmony_ci priv_size += (8 - (priv_size & 0x7)); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci size = octdevsize + priv_size + configsize + 70562306a36Sopenharmony_ci (sizeof(struct octeon_dispatch) * DISPATCH_LIST_SIZE); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci buf = vzalloc(size); 70862306a36Sopenharmony_ci if (!buf) 70962306a36Sopenharmony_ci return NULL; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci oct = (struct octeon_device *)buf; 71262306a36Sopenharmony_ci oct->priv = (void *)(buf + octdevsize); 71362306a36Sopenharmony_ci oct->chip = (void *)(buf + octdevsize + priv_size); 71462306a36Sopenharmony_ci oct->dispatch.dlist = (struct octeon_dispatch *) 71562306a36Sopenharmony_ci (buf + octdevsize + priv_size + configsize); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci return oct; 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistruct octeon_device *octeon_allocate_device(u32 pci_id, 72162306a36Sopenharmony_ci u32 priv_size) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci u32 oct_idx = 0; 72462306a36Sopenharmony_ci struct octeon_device *oct = NULL; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci spin_lock(&octeon_devices_lock); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci for (oct_idx = 0; oct_idx < MAX_OCTEON_DEVICES; oct_idx++) 72962306a36Sopenharmony_ci if (!octeon_device[oct_idx]) 73062306a36Sopenharmony_ci break; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (oct_idx < MAX_OCTEON_DEVICES) { 73362306a36Sopenharmony_ci oct = octeon_allocate_device_mem(pci_id, priv_size); 73462306a36Sopenharmony_ci if (oct) { 73562306a36Sopenharmony_ci octeon_device_count++; 73662306a36Sopenharmony_ci octeon_device[oct_idx] = oct; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci spin_unlock(&octeon_devices_lock); 74162306a36Sopenharmony_ci if (!oct) 74262306a36Sopenharmony_ci return NULL; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci spin_lock_init(&oct->pci_win_lock); 74562306a36Sopenharmony_ci spin_lock_init(&oct->mem_access_lock); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci oct->octeon_id = oct_idx; 74862306a36Sopenharmony_ci snprintf(oct->device_name, sizeof(oct->device_name), 74962306a36Sopenharmony_ci "LiquidIO%d", (oct->octeon_id)); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci return oct; 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_allocate_device); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci/** Register a device's bus location at initialization time. 75662306a36Sopenharmony_ci * @param octeon_dev - pointer to the octeon device structure. 75762306a36Sopenharmony_ci * @param bus - PCIe bus # 75862306a36Sopenharmony_ci * @param dev - PCIe device # 75962306a36Sopenharmony_ci * @param func - PCIe function # 76062306a36Sopenharmony_ci * @param is_pf - TRUE for PF, FALSE for VF 76162306a36Sopenharmony_ci * @return reference count of device's adapter 76262306a36Sopenharmony_ci */ 76362306a36Sopenharmony_ciint octeon_register_device(struct octeon_device *oct, 76462306a36Sopenharmony_ci int bus, int dev, int func, int is_pf) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci int idx, refcount; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci oct->loc.bus = bus; 76962306a36Sopenharmony_ci oct->loc.dev = dev; 77062306a36Sopenharmony_ci oct->loc.func = func; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci oct->adapter_refcount = &adapter_refcounts[oct->octeon_id]; 77362306a36Sopenharmony_ci atomic_set(oct->adapter_refcount, 0); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci /* Like the reference count, the f/w state is shared 'per-adapter' */ 77662306a36Sopenharmony_ci oct->adapter_fw_state = &adapter_fw_states[oct->octeon_id]; 77762306a36Sopenharmony_ci atomic_set(oct->adapter_fw_state, FW_NEEDS_TO_BE_LOADED); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci spin_lock(&octeon_devices_lock); 78062306a36Sopenharmony_ci for (idx = (int)oct->octeon_id - 1; idx >= 0; idx--) { 78162306a36Sopenharmony_ci if (!octeon_device[idx]) { 78262306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, 78362306a36Sopenharmony_ci "%s: Internal driver error, missing dev", 78462306a36Sopenharmony_ci __func__); 78562306a36Sopenharmony_ci spin_unlock(&octeon_devices_lock); 78662306a36Sopenharmony_ci atomic_inc(oct->adapter_refcount); 78762306a36Sopenharmony_ci return 1; /* here, refcount is guaranteed to be 1 */ 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci /* If another device is at same bus/dev, use its refcounter 79062306a36Sopenharmony_ci * (and f/w state variable). 79162306a36Sopenharmony_ci */ 79262306a36Sopenharmony_ci if ((octeon_device[idx]->loc.bus == bus) && 79362306a36Sopenharmony_ci (octeon_device[idx]->loc.dev == dev)) { 79462306a36Sopenharmony_ci oct->adapter_refcount = 79562306a36Sopenharmony_ci octeon_device[idx]->adapter_refcount; 79662306a36Sopenharmony_ci oct->adapter_fw_state = 79762306a36Sopenharmony_ci octeon_device[idx]->adapter_fw_state; 79862306a36Sopenharmony_ci break; 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci spin_unlock(&octeon_devices_lock); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci atomic_inc(oct->adapter_refcount); 80462306a36Sopenharmony_ci refcount = atomic_read(oct->adapter_refcount); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "%s: %02x:%02x:%d refcount %u", __func__, 80762306a36Sopenharmony_ci oct->loc.bus, oct->loc.dev, oct->loc.func, refcount); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci return refcount; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_register_device); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci/** Deregister a device at de-initialization time. 81462306a36Sopenharmony_ci * @param octeon_dev - pointer to the octeon device structure. 81562306a36Sopenharmony_ci * @return reference count of device's adapter 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_ciint octeon_deregister_device(struct octeon_device *oct) 81862306a36Sopenharmony_ci{ 81962306a36Sopenharmony_ci int refcount; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci atomic_dec(oct->adapter_refcount); 82262306a36Sopenharmony_ci refcount = atomic_read(oct->adapter_refcount); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "%s: %04d:%02d:%d refcount %u", __func__, 82562306a36Sopenharmony_ci oct->loc.bus, oct->loc.dev, oct->loc.func, refcount); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci return refcount; 82862306a36Sopenharmony_ci} 82962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_deregister_device); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ciint 83262306a36Sopenharmony_ciocteon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs) 83362306a36Sopenharmony_ci{ 83462306a36Sopenharmony_ci struct octeon_ioq_vector *ioq_vector; 83562306a36Sopenharmony_ci int cpu_num; 83662306a36Sopenharmony_ci int size; 83762306a36Sopenharmony_ci int i; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci size = sizeof(struct octeon_ioq_vector) * num_ioqs; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci oct->ioq_vector = vzalloc(size); 84262306a36Sopenharmony_ci if (!oct->ioq_vector) 84362306a36Sopenharmony_ci return -1; 84462306a36Sopenharmony_ci for (i = 0; i < num_ioqs; i++) { 84562306a36Sopenharmony_ci ioq_vector = &oct->ioq_vector[i]; 84662306a36Sopenharmony_ci ioq_vector->oct_dev = oct; 84762306a36Sopenharmony_ci ioq_vector->iq_index = i; 84862306a36Sopenharmony_ci ioq_vector->droq_index = i; 84962306a36Sopenharmony_ci ioq_vector->mbox = oct->mbox[i]; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci cpu_num = i % num_online_cpus(); 85262306a36Sopenharmony_ci cpumask_set_cpu(cpu_num, &ioq_vector->affinity_mask); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (oct->chip_id == OCTEON_CN23XX_PF_VID) 85562306a36Sopenharmony_ci ioq_vector->ioq_num = i + oct->sriov_info.pf_srn; 85662306a36Sopenharmony_ci else 85762306a36Sopenharmony_ci ioq_vector->ioq_num = i; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci return 0; 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_allocate_ioq_vector); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_civoid 86562306a36Sopenharmony_ciocteon_free_ioq_vector(struct octeon_device *oct) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci vfree(oct->ioq_vector); 86862306a36Sopenharmony_ci} 86962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_free_ioq_vector); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci/* this function is only for setting up the first queue */ 87262306a36Sopenharmony_ciint octeon_setup_instr_queues(struct octeon_device *oct) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci u32 num_descs = 0; 87562306a36Sopenharmony_ci u32 iq_no = 0; 87662306a36Sopenharmony_ci union oct_txpciq txpciq; 87762306a36Sopenharmony_ci int numa_node = dev_to_node(&oct->pci_dev->dev); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) 88062306a36Sopenharmony_ci num_descs = 88162306a36Sopenharmony_ci CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx)); 88262306a36Sopenharmony_ci else if (OCTEON_CN23XX_PF(oct)) 88362306a36Sopenharmony_ci num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf)); 88462306a36Sopenharmony_ci else if (OCTEON_CN23XX_VF(oct)) 88562306a36Sopenharmony_ci num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_vf)); 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci oct->num_iqs = 0; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci oct->instr_queue[0] = vzalloc_node(sizeof(*oct->instr_queue[0]), 89062306a36Sopenharmony_ci numa_node); 89162306a36Sopenharmony_ci if (!oct->instr_queue[0]) 89262306a36Sopenharmony_ci oct->instr_queue[0] = 89362306a36Sopenharmony_ci vzalloc(sizeof(struct octeon_instr_queue)); 89462306a36Sopenharmony_ci if (!oct->instr_queue[0]) 89562306a36Sopenharmony_ci return 1; 89662306a36Sopenharmony_ci memset(oct->instr_queue[0], 0, sizeof(struct octeon_instr_queue)); 89762306a36Sopenharmony_ci oct->instr_queue[0]->q_index = 0; 89862306a36Sopenharmony_ci oct->instr_queue[0]->app_ctx = (void *)(size_t)0; 89962306a36Sopenharmony_ci oct->instr_queue[0]->ifidx = 0; 90062306a36Sopenharmony_ci txpciq.u64 = 0; 90162306a36Sopenharmony_ci txpciq.s.q_no = iq_no; 90262306a36Sopenharmony_ci txpciq.s.pkind = oct->pfvf_hsword.pkind; 90362306a36Sopenharmony_ci txpciq.s.use_qpg = 0; 90462306a36Sopenharmony_ci txpciq.s.qpg = 0; 90562306a36Sopenharmony_ci if (octeon_init_instr_queue(oct, txpciq, num_descs)) { 90662306a36Sopenharmony_ci /* prevent memory leak */ 90762306a36Sopenharmony_ci vfree(oct->instr_queue[0]); 90862306a36Sopenharmony_ci oct->instr_queue[0] = NULL; 90962306a36Sopenharmony_ci return 1; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci oct->num_iqs++; 91362306a36Sopenharmony_ci return 0; 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_setup_instr_queues); 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ciint octeon_setup_output_queues(struct octeon_device *oct) 91862306a36Sopenharmony_ci{ 91962306a36Sopenharmony_ci u32 num_descs = 0; 92062306a36Sopenharmony_ci u32 desc_size = 0; 92162306a36Sopenharmony_ci u32 oq_no = 0; 92262306a36Sopenharmony_ci int numa_node = dev_to_node(&oct->pci_dev->dev); 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) { 92562306a36Sopenharmony_ci num_descs = 92662306a36Sopenharmony_ci CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn6xxx)); 92762306a36Sopenharmony_ci desc_size = 92862306a36Sopenharmony_ci CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn6xxx)); 92962306a36Sopenharmony_ci } else if (OCTEON_CN23XX_PF(oct)) { 93062306a36Sopenharmony_ci num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf)); 93162306a36Sopenharmony_ci desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf)); 93262306a36Sopenharmony_ci } else if (OCTEON_CN23XX_VF(oct)) { 93362306a36Sopenharmony_ci num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_vf)); 93462306a36Sopenharmony_ci desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_vf)); 93562306a36Sopenharmony_ci } 93662306a36Sopenharmony_ci oct->num_oqs = 0; 93762306a36Sopenharmony_ci oct->droq[0] = vzalloc_node(sizeof(*oct->droq[0]), numa_node); 93862306a36Sopenharmony_ci if (!oct->droq[0]) 93962306a36Sopenharmony_ci oct->droq[0] = vzalloc(sizeof(*oct->droq[0])); 94062306a36Sopenharmony_ci if (!oct->droq[0]) 94162306a36Sopenharmony_ci return 1; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL)) { 94462306a36Sopenharmony_ci vfree(oct->droq[oq_no]); 94562306a36Sopenharmony_ci oct->droq[oq_no] = NULL; 94662306a36Sopenharmony_ci return 1; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci oct->num_oqs++; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_setup_output_queues); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ciint octeon_set_io_queues_off(struct octeon_device *oct) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci int loop = BUSY_READING_REG_VF_LOOP_COUNT; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) { 95962306a36Sopenharmony_ci octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0); 96062306a36Sopenharmony_ci octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0); 96162306a36Sopenharmony_ci } else if (oct->chip_id == OCTEON_CN23XX_VF_VID) { 96262306a36Sopenharmony_ci u32 q_no; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* IOQs will already be in reset. 96562306a36Sopenharmony_ci * If RST bit is set, wait for quiet bit to be set. 96662306a36Sopenharmony_ci * Once quiet bit is set, clear the RST bit. 96762306a36Sopenharmony_ci */ 96862306a36Sopenharmony_ci for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) { 96962306a36Sopenharmony_ci u64 reg_val = octeon_read_csr64( 97062306a36Sopenharmony_ci oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci while ((reg_val & CN23XX_PKT_INPUT_CTL_RST) && 97362306a36Sopenharmony_ci !(reg_val & CN23XX_PKT_INPUT_CTL_QUIET) && 97462306a36Sopenharmony_ci loop) { 97562306a36Sopenharmony_ci reg_val = octeon_read_csr64( 97662306a36Sopenharmony_ci oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no)); 97762306a36Sopenharmony_ci loop--; 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci if (!loop) { 98062306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, 98162306a36Sopenharmony_ci "clearing the reset reg failed or setting the quiet reg failed for qno: %u\n", 98262306a36Sopenharmony_ci q_no); 98362306a36Sopenharmony_ci return -1; 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci reg_val = reg_val & ~CN23XX_PKT_INPUT_CTL_RST; 98762306a36Sopenharmony_ci octeon_write_csr64(oct, 98862306a36Sopenharmony_ci CN23XX_SLI_IQ_PKT_CONTROL64(q_no), 98962306a36Sopenharmony_ci reg_val); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci reg_val = octeon_read_csr64( 99262306a36Sopenharmony_ci oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no)); 99362306a36Sopenharmony_ci if (reg_val & CN23XX_PKT_INPUT_CTL_RST) { 99462306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, 99562306a36Sopenharmony_ci "unable to reset qno %u\n", q_no); 99662306a36Sopenharmony_ci return -1; 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci return 0; 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_set_io_queues_off); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_civoid octeon_set_droq_pkt_op(struct octeon_device *oct, 100562306a36Sopenharmony_ci u32 q_no, 100662306a36Sopenharmony_ci u32 enable) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci u32 reg_val = 0; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci /* Disable the i/p and o/p queues for this Octeon. */ 101162306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) { 101262306a36Sopenharmony_ci reg_val = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci if (enable) 101562306a36Sopenharmony_ci reg_val = reg_val | (1 << q_no); 101662306a36Sopenharmony_ci else 101762306a36Sopenharmony_ci reg_val = reg_val & (~(1 << q_no)); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, reg_val); 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ciint octeon_init_dispatch_list(struct octeon_device *oct) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci u32 i; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci oct->dispatch.count = 0; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci for (i = 0; i < DISPATCH_LIST_SIZE; i++) { 103062306a36Sopenharmony_ci oct->dispatch.dlist[i].opcode = 0; 103162306a36Sopenharmony_ci INIT_LIST_HEAD(&oct->dispatch.dlist[i].list); 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci for (i = 0; i <= REQTYPE_LAST; i++) 103562306a36Sopenharmony_ci octeon_register_reqtype_free_fn(oct, i, NULL); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci spin_lock_init(&oct->dispatch.lock); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci return 0; 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_init_dispatch_list); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_civoid octeon_delete_dispatch_list(struct octeon_device *oct) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci u32 i; 104662306a36Sopenharmony_ci struct list_head freelist, *temp, *tmp2; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci INIT_LIST_HEAD(&freelist); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci spin_lock_bh(&oct->dispatch.lock); 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci for (i = 0; i < DISPATCH_LIST_SIZE; i++) { 105362306a36Sopenharmony_ci struct list_head *dispatch; 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci dispatch = &oct->dispatch.dlist[i].list; 105662306a36Sopenharmony_ci while (dispatch->next != dispatch) { 105762306a36Sopenharmony_ci temp = dispatch->next; 105862306a36Sopenharmony_ci list_move_tail(temp, &freelist); 105962306a36Sopenharmony_ci } 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci oct->dispatch.dlist[i].opcode = 0; 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci oct->dispatch.count = 0; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci spin_unlock_bh(&oct->dispatch.lock); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci list_for_each_safe(temp, tmp2, &freelist) { 106962306a36Sopenharmony_ci list_del(temp); 107062306a36Sopenharmony_ci kfree(temp); 107162306a36Sopenharmony_ci } 107262306a36Sopenharmony_ci} 107362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_delete_dispatch_list); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ciocteon_dispatch_fn_t 107662306a36Sopenharmony_ciocteon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode, 107762306a36Sopenharmony_ci u16 subcode) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci u32 idx; 108062306a36Sopenharmony_ci struct list_head *dispatch; 108162306a36Sopenharmony_ci octeon_dispatch_fn_t fn = NULL; 108262306a36Sopenharmony_ci u16 combined_opcode = OPCODE_SUBCODE(opcode, subcode); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci idx = combined_opcode & OCTEON_OPCODE_MASK; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci spin_lock_bh(&octeon_dev->dispatch.lock); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci if (octeon_dev->dispatch.count == 0) { 108962306a36Sopenharmony_ci spin_unlock_bh(&octeon_dev->dispatch.lock); 109062306a36Sopenharmony_ci return NULL; 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci if (!(octeon_dev->dispatch.dlist[idx].opcode)) { 109462306a36Sopenharmony_ci spin_unlock_bh(&octeon_dev->dispatch.lock); 109562306a36Sopenharmony_ci return NULL; 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci if (octeon_dev->dispatch.dlist[idx].opcode == combined_opcode) { 109962306a36Sopenharmony_ci fn = octeon_dev->dispatch.dlist[idx].dispatch_fn; 110062306a36Sopenharmony_ci } else { 110162306a36Sopenharmony_ci list_for_each(dispatch, 110262306a36Sopenharmony_ci &octeon_dev->dispatch.dlist[idx].list) { 110362306a36Sopenharmony_ci if (((struct octeon_dispatch *)dispatch)->opcode == 110462306a36Sopenharmony_ci combined_opcode) { 110562306a36Sopenharmony_ci fn = ((struct octeon_dispatch *) 110662306a36Sopenharmony_ci dispatch)->dispatch_fn; 110762306a36Sopenharmony_ci break; 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci } 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci spin_unlock_bh(&octeon_dev->dispatch.lock); 111362306a36Sopenharmony_ci return fn; 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci/* octeon_register_dispatch_fn 111762306a36Sopenharmony_ci * Parameters: 111862306a36Sopenharmony_ci * octeon_id - id of the octeon device. 111962306a36Sopenharmony_ci * opcode - opcode for which driver should call the registered function 112062306a36Sopenharmony_ci * subcode - subcode for which driver should call the registered function 112162306a36Sopenharmony_ci * fn - The function to call when a packet with "opcode" arrives in 112262306a36Sopenharmony_ci * octeon output queues. 112362306a36Sopenharmony_ci * fn_arg - The argument to be passed when calling function "fn". 112462306a36Sopenharmony_ci * Description: 112562306a36Sopenharmony_ci * Registers a function and its argument to be called when a packet 112662306a36Sopenharmony_ci * arrives in Octeon output queues with "opcode". 112762306a36Sopenharmony_ci * Returns: 112862306a36Sopenharmony_ci * Success: 0 112962306a36Sopenharmony_ci * Failure: 1 113062306a36Sopenharmony_ci * Locks: 113162306a36Sopenharmony_ci * No locks are held. 113262306a36Sopenharmony_ci */ 113362306a36Sopenharmony_ciint 113462306a36Sopenharmony_ciocteon_register_dispatch_fn(struct octeon_device *oct, 113562306a36Sopenharmony_ci u16 opcode, 113662306a36Sopenharmony_ci u16 subcode, 113762306a36Sopenharmony_ci octeon_dispatch_fn_t fn, void *fn_arg) 113862306a36Sopenharmony_ci{ 113962306a36Sopenharmony_ci u32 idx; 114062306a36Sopenharmony_ci octeon_dispatch_fn_t pfn; 114162306a36Sopenharmony_ci u16 combined_opcode = OPCODE_SUBCODE(opcode, subcode); 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci idx = combined_opcode & OCTEON_OPCODE_MASK; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci spin_lock_bh(&oct->dispatch.lock); 114662306a36Sopenharmony_ci /* Add dispatch function to first level of lookup table */ 114762306a36Sopenharmony_ci if (oct->dispatch.dlist[idx].opcode == 0) { 114862306a36Sopenharmony_ci oct->dispatch.dlist[idx].opcode = combined_opcode; 114962306a36Sopenharmony_ci oct->dispatch.dlist[idx].dispatch_fn = fn; 115062306a36Sopenharmony_ci oct->dispatch.dlist[idx].arg = fn_arg; 115162306a36Sopenharmony_ci oct->dispatch.count++; 115262306a36Sopenharmony_ci spin_unlock_bh(&oct->dispatch.lock); 115362306a36Sopenharmony_ci return 0; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci spin_unlock_bh(&oct->dispatch.lock); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci /* Check if there was a function already registered for this 115962306a36Sopenharmony_ci * opcode/subcode. 116062306a36Sopenharmony_ci */ 116162306a36Sopenharmony_ci pfn = octeon_get_dispatch(oct, opcode, subcode); 116262306a36Sopenharmony_ci if (!pfn) { 116362306a36Sopenharmony_ci struct octeon_dispatch *dispatch; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, 116662306a36Sopenharmony_ci "Adding opcode to dispatch list linked list\n"); 116762306a36Sopenharmony_ci dispatch = kmalloc(sizeof(*dispatch), GFP_KERNEL); 116862306a36Sopenharmony_ci if (!dispatch) 116962306a36Sopenharmony_ci return 1; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci dispatch->opcode = combined_opcode; 117262306a36Sopenharmony_ci dispatch->dispatch_fn = fn; 117362306a36Sopenharmony_ci dispatch->arg = fn_arg; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci /* Add dispatch function to linked list of fn ptrs 117662306a36Sopenharmony_ci * at the hashed index. 117762306a36Sopenharmony_ci */ 117862306a36Sopenharmony_ci spin_lock_bh(&oct->dispatch.lock); 117962306a36Sopenharmony_ci list_add(&dispatch->list, &oct->dispatch.dlist[idx].list); 118062306a36Sopenharmony_ci oct->dispatch.count++; 118162306a36Sopenharmony_ci spin_unlock_bh(&oct->dispatch.lock); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci } else { 118462306a36Sopenharmony_ci if (pfn == fn && 118562306a36Sopenharmony_ci octeon_get_dispatch_arg(oct, opcode, subcode) == fn_arg) 118662306a36Sopenharmony_ci return 0; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, 118962306a36Sopenharmony_ci "Found previously registered dispatch fn for opcode/subcode: %x/%x\n", 119062306a36Sopenharmony_ci opcode, subcode); 119162306a36Sopenharmony_ci return 1; 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci return 0; 119562306a36Sopenharmony_ci} 119662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_register_dispatch_fn); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ciint octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci u32 i; 120162306a36Sopenharmony_ci char app_name[16]; 120262306a36Sopenharmony_ci struct octeon_device *oct = (struct octeon_device *)buf; 120362306a36Sopenharmony_ci struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt; 120462306a36Sopenharmony_ci struct octeon_core_setup *cs = NULL; 120562306a36Sopenharmony_ci u32 num_nic_ports = 0; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) 120862306a36Sopenharmony_ci num_nic_ports = 120962306a36Sopenharmony_ci CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn6xxx)); 121062306a36Sopenharmony_ci else if (OCTEON_CN23XX_PF(oct)) 121162306a36Sopenharmony_ci num_nic_ports = 121262306a36Sopenharmony_ci CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn23xx_pf)); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci if (atomic_read(&oct->status) >= OCT_DEV_RUNNING) { 121562306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, "Received CORE OK when device state is 0x%x\n", 121662306a36Sopenharmony_ci atomic_read(&oct->status)); 121762306a36Sopenharmony_ci goto core_drv_init_err; 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci strncpy(app_name, 122162306a36Sopenharmony_ci get_oct_app_string( 122262306a36Sopenharmony_ci (u32)recv_pkt->rh.r_core_drv_init.app_mode), 122362306a36Sopenharmony_ci sizeof(app_name) - 1); 122462306a36Sopenharmony_ci oct->app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode; 122562306a36Sopenharmony_ci if (recv_pkt->rh.r_core_drv_init.app_mode == CVM_DRV_NIC_APP) { 122662306a36Sopenharmony_ci oct->fw_info.max_nic_ports = 122762306a36Sopenharmony_ci (u32)recv_pkt->rh.r_core_drv_init.max_nic_ports; 122862306a36Sopenharmony_ci oct->fw_info.num_gmx_ports = 122962306a36Sopenharmony_ci (u32)recv_pkt->rh.r_core_drv_init.num_gmx_ports; 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci if (oct->fw_info.max_nic_ports < num_nic_ports) { 123362306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, 123462306a36Sopenharmony_ci "Config has more ports than firmware allows (%d > %d).\n", 123562306a36Sopenharmony_ci num_nic_ports, oct->fw_info.max_nic_ports); 123662306a36Sopenharmony_ci goto core_drv_init_err; 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci oct->fw_info.app_cap_flags = recv_pkt->rh.r_core_drv_init.app_cap_flags; 123962306a36Sopenharmony_ci oct->fw_info.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode; 124062306a36Sopenharmony_ci oct->pfvf_hsword.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci oct->pfvf_hsword.pkind = recv_pkt->rh.r_core_drv_init.pkind; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci for (i = 0; i < oct->num_iqs; i++) 124562306a36Sopenharmony_ci oct->instr_queue[i]->txpciq.s.pkind = oct->pfvf_hsword.pkind; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci atomic_set(&oct->status, OCT_DEV_CORE_OK); 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci cs = &core_setup[oct->octeon_id]; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci if (recv_pkt->buffer_size[0] != (sizeof(*cs) + OCT_DROQ_INFO_SIZE)) { 125262306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "Core setup bytes expected %u found %d\n", 125362306a36Sopenharmony_ci (u32)sizeof(*cs), 125462306a36Sopenharmony_ci recv_pkt->buffer_size[0]); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci memcpy(cs, get_rbd( 125862306a36Sopenharmony_ci recv_pkt->buffer_ptr[0]) + OCT_DROQ_INFO_SIZE, sizeof(*cs)); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci strncpy(oct->boardinfo.name, cs->boardname, OCT_BOARD_NAME); 126162306a36Sopenharmony_ci strncpy(oct->boardinfo.serial_number, cs->board_serial_number, 126262306a36Sopenharmony_ci OCT_SERIAL_LEN); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci octeon_swap_8B_data((u64 *)cs, (sizeof(*cs) >> 3)); 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci oct->boardinfo.major = cs->board_rev_major; 126762306a36Sopenharmony_ci oct->boardinfo.minor = cs->board_rev_minor; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci dev_info(&oct->pci_dev->dev, 127062306a36Sopenharmony_ci "Running %s (%llu Hz)\n", 127162306a36Sopenharmony_ci app_name, CVM_CAST64(cs->corefreq)); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_cicore_drv_init_err: 127462306a36Sopenharmony_ci for (i = 0; i < recv_pkt->buffer_count; i++) 127562306a36Sopenharmony_ci recv_buffer_free(recv_pkt->buffer_ptr[i]); 127662306a36Sopenharmony_ci octeon_free_recv_info(recv_info); 127762306a36Sopenharmony_ci return 0; 127862306a36Sopenharmony_ci} 127962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_core_drv_init); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ciint octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no) 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci{ 128462306a36Sopenharmony_ci if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES(oct)) && 128562306a36Sopenharmony_ci (oct->io_qmask.iq & BIT_ULL(q_no))) 128662306a36Sopenharmony_ci return oct->instr_queue[q_no]->max_count; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci return -1; 128962306a36Sopenharmony_ci} 129062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_get_tx_qsize); 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ciint octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no) 129362306a36Sopenharmony_ci{ 129462306a36Sopenharmony_ci if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES(oct)) && 129562306a36Sopenharmony_ci (oct->io_qmask.oq & BIT_ULL(q_no))) 129662306a36Sopenharmony_ci return oct->droq[q_no]->max_count; 129762306a36Sopenharmony_ci return -1; 129862306a36Sopenharmony_ci} 129962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_get_rx_qsize); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci/* Retruns the host firmware handshake OCTEON specific configuration */ 130262306a36Sopenharmony_cistruct octeon_config *octeon_get_conf(struct octeon_device *oct) 130362306a36Sopenharmony_ci{ 130462306a36Sopenharmony_ci struct octeon_config *default_oct_conf = NULL; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci /* check the OCTEON Device model & return the corresponding octeon 130762306a36Sopenharmony_ci * configuration 130862306a36Sopenharmony_ci */ 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci if (OCTEON_CN6XXX(oct)) { 131162306a36Sopenharmony_ci default_oct_conf = 131262306a36Sopenharmony_ci (struct octeon_config *)(CHIP_CONF(oct, cn6xxx)); 131362306a36Sopenharmony_ci } else if (OCTEON_CN23XX_PF(oct)) { 131462306a36Sopenharmony_ci default_oct_conf = (struct octeon_config *) 131562306a36Sopenharmony_ci (CHIP_CONF(oct, cn23xx_pf)); 131662306a36Sopenharmony_ci } else if (OCTEON_CN23XX_VF(oct)) { 131762306a36Sopenharmony_ci default_oct_conf = (struct octeon_config *) 131862306a36Sopenharmony_ci (CHIP_CONF(oct, cn23xx_vf)); 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci return default_oct_conf; 132162306a36Sopenharmony_ci} 132262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_get_conf); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci/* scratch register address is same in all the OCT-II and CN70XX models */ 132562306a36Sopenharmony_ci#define CNXX_SLI_SCRATCH1 0x3C0 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci/* Get the octeon device pointer. 132862306a36Sopenharmony_ci * @param octeon_id - The id for which the octeon device pointer is required. 132962306a36Sopenharmony_ci * @return Success: Octeon device pointer. 133062306a36Sopenharmony_ci * @return Failure: NULL. 133162306a36Sopenharmony_ci */ 133262306a36Sopenharmony_cistruct octeon_device *lio_get_device(u32 octeon_id) 133362306a36Sopenharmony_ci{ 133462306a36Sopenharmony_ci if (octeon_id >= MAX_OCTEON_DEVICES) 133562306a36Sopenharmony_ci return NULL; 133662306a36Sopenharmony_ci else 133762306a36Sopenharmony_ci return octeon_device[octeon_id]; 133862306a36Sopenharmony_ci} 133962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_get_device); 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ciu64 lio_pci_readq(struct octeon_device *oct, u64 addr) 134262306a36Sopenharmony_ci{ 134362306a36Sopenharmony_ci u64 val64; 134462306a36Sopenharmony_ci unsigned long flags; 134562306a36Sopenharmony_ci u32 addrhi; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci spin_lock_irqsave(&oct->pci_win_lock, flags); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci /* The windowed read happens when the LSB of the addr is written. 135062306a36Sopenharmony_ci * So write MSB first 135162306a36Sopenharmony_ci */ 135262306a36Sopenharmony_ci addrhi = (addr >> 32); 135362306a36Sopenharmony_ci if ((oct->chip_id == OCTEON_CN66XX) || 135462306a36Sopenharmony_ci (oct->chip_id == OCTEON_CN68XX) || 135562306a36Sopenharmony_ci (oct->chip_id == OCTEON_CN23XX_PF_VID)) 135662306a36Sopenharmony_ci addrhi |= 0x00060000; 135762306a36Sopenharmony_ci writel(addrhi, oct->reg_list.pci_win_rd_addr_hi); 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci /* Read back to preserve ordering of writes */ 136062306a36Sopenharmony_ci readl(oct->reg_list.pci_win_rd_addr_hi); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci writel(addr & 0xffffffff, oct->reg_list.pci_win_rd_addr_lo); 136362306a36Sopenharmony_ci readl(oct->reg_list.pci_win_rd_addr_lo); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci val64 = readq(oct->reg_list.pci_win_rd_data); 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci spin_unlock_irqrestore(&oct->pci_win_lock, flags); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci return val64; 137062306a36Sopenharmony_ci} 137162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_pci_readq); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_civoid lio_pci_writeq(struct octeon_device *oct, 137462306a36Sopenharmony_ci u64 val, 137562306a36Sopenharmony_ci u64 addr) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci unsigned long flags; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci spin_lock_irqsave(&oct->pci_win_lock, flags); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci writeq(addr, oct->reg_list.pci_win_wr_addr); 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci /* The write happens when the LSB is written. So write MSB first. */ 138462306a36Sopenharmony_ci writel(val >> 32, oct->reg_list.pci_win_wr_data_hi); 138562306a36Sopenharmony_ci /* Read the MSB to ensure ordering of writes. */ 138662306a36Sopenharmony_ci readl(oct->reg_list.pci_win_wr_data_hi); 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci writel(val & 0xffffffff, oct->reg_list.pci_win_wr_data_lo); 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci spin_unlock_irqrestore(&oct->pci_win_lock, flags); 139162306a36Sopenharmony_ci} 139262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_pci_writeq); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ciint octeon_mem_access_ok(struct octeon_device *oct) 139562306a36Sopenharmony_ci{ 139662306a36Sopenharmony_ci u64 access_okay = 0; 139762306a36Sopenharmony_ci u64 lmc0_reset_ctl; 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci /* Check to make sure a DDR interface is enabled */ 140062306a36Sopenharmony_ci if (OCTEON_CN23XX_PF(oct)) { 140162306a36Sopenharmony_ci lmc0_reset_ctl = lio_pci_readq(oct, CN23XX_LMC0_RESET_CTL); 140262306a36Sopenharmony_ci access_okay = 140362306a36Sopenharmony_ci (lmc0_reset_ctl & CN23XX_LMC0_RESET_CTL_DDR3RST_MASK); 140462306a36Sopenharmony_ci } else { 140562306a36Sopenharmony_ci lmc0_reset_ctl = lio_pci_readq(oct, CN6XXX_LMC0_RESET_CTL); 140662306a36Sopenharmony_ci access_okay = 140762306a36Sopenharmony_ci (lmc0_reset_ctl & CN6XXX_LMC0_RESET_CTL_DDR3RST_MASK); 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci return access_okay ? 0 : 1; 141162306a36Sopenharmony_ci} 141262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_mem_access_ok); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ciint octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout) 141562306a36Sopenharmony_ci{ 141662306a36Sopenharmony_ci int ret = 1; 141762306a36Sopenharmony_ci u32 ms; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (!timeout) 142062306a36Sopenharmony_ci return ret; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci for (ms = 0; (ret != 0) && ((*timeout == 0) || (ms <= *timeout)); 142362306a36Sopenharmony_ci ms += HZ / 10) { 142462306a36Sopenharmony_ci ret = octeon_mem_access_ok(oct); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci /* wait 100 ms */ 142762306a36Sopenharmony_ci if (ret) 142862306a36Sopenharmony_ci schedule_timeout_uninterruptible(HZ / 10); 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci return ret; 143262306a36Sopenharmony_ci} 143362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(octeon_wait_for_ddr_init); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci/* Get the octeon id assigned to the octeon device passed as argument. 143662306a36Sopenharmony_ci * This function is exported to other modules. 143762306a36Sopenharmony_ci * @param dev - octeon device pointer passed as a void *. 143862306a36Sopenharmony_ci * @return octeon device id 143962306a36Sopenharmony_ci */ 144062306a36Sopenharmony_ciint lio_get_device_id(void *dev) 144162306a36Sopenharmony_ci{ 144262306a36Sopenharmony_ci struct octeon_device *octeon_dev = (struct octeon_device *)dev; 144362306a36Sopenharmony_ci u32 i; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci for (i = 0; i < MAX_OCTEON_DEVICES; i++) 144662306a36Sopenharmony_ci if (octeon_device[i] == octeon_dev) 144762306a36Sopenharmony_ci return octeon_dev->octeon_id; 144862306a36Sopenharmony_ci return -1; 144962306a36Sopenharmony_ci} 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_civoid lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq) 145262306a36Sopenharmony_ci{ 145362306a36Sopenharmony_ci u64 instr_cnt; 145462306a36Sopenharmony_ci u32 pkts_pend; 145562306a36Sopenharmony_ci struct octeon_device *oct = NULL; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci /* the whole thing needs to be atomic, ideally */ 145862306a36Sopenharmony_ci if (droq) { 145962306a36Sopenharmony_ci pkts_pend = (u32)atomic_read(&droq->pkts_pending); 146062306a36Sopenharmony_ci writel(droq->pkt_count - pkts_pend, droq->pkts_sent_reg); 146162306a36Sopenharmony_ci droq->pkt_count = pkts_pend; 146262306a36Sopenharmony_ci oct = droq->oct_dev; 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci if (iq) { 146562306a36Sopenharmony_ci spin_lock_bh(&iq->lock); 146662306a36Sopenharmony_ci writel(iq->pkts_processed, iq->inst_cnt_reg); 146762306a36Sopenharmony_ci iq->pkt_in_done -= iq->pkts_processed; 146862306a36Sopenharmony_ci iq->pkts_processed = 0; 146962306a36Sopenharmony_ci /* this write needs to be flushed before we release the lock */ 147062306a36Sopenharmony_ci spin_unlock_bh(&iq->lock); 147162306a36Sopenharmony_ci oct = iq->oct_dev; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci /*write resend. Writing RESEND in SLI_PKTX_CNTS should be enough 147462306a36Sopenharmony_ci *to trigger tx interrupts as well, if they are pending. 147562306a36Sopenharmony_ci */ 147662306a36Sopenharmony_ci if (oct && (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))) { 147762306a36Sopenharmony_ci if (droq) 147862306a36Sopenharmony_ci writeq(CN23XX_INTR_RESEND, droq->pkts_sent_reg); 147962306a36Sopenharmony_ci /*we race with firmrware here. read and write the IN_DONE_CNTS*/ 148062306a36Sopenharmony_ci else if (iq) { 148162306a36Sopenharmony_ci instr_cnt = readq(iq->inst_cnt_reg); 148262306a36Sopenharmony_ci writeq(((instr_cnt & 0xFFFFFFFF00000000ULL) | 148362306a36Sopenharmony_ci CN23XX_INTR_RESEND), 148462306a36Sopenharmony_ci iq->inst_cnt_reg); 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci } 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_enable_irq); 1489