183189849SRahul Lakkireddy /*- 283189849SRahul Lakkireddy * BSD LICENSE 383189849SRahul Lakkireddy * 404868e5bSRahul Lakkireddy * Copyright(c) 2014-2017 Chelsio Communications. 583189849SRahul Lakkireddy * All rights reserved. 683189849SRahul Lakkireddy * 783189849SRahul Lakkireddy * Redistribution and use in source and binary forms, with or without 883189849SRahul Lakkireddy * modification, are permitted provided that the following conditions 983189849SRahul Lakkireddy * are met: 1083189849SRahul Lakkireddy * 1183189849SRahul Lakkireddy * * Redistributions of source code must retain the above copyright 1283189849SRahul Lakkireddy * notice, this list of conditions and the following disclaimer. 1383189849SRahul Lakkireddy * * Redistributions in binary form must reproduce the above copyright 1483189849SRahul Lakkireddy * notice, this list of conditions and the following disclaimer in 1583189849SRahul Lakkireddy * the documentation and/or other materials provided with the 1683189849SRahul Lakkireddy * distribution. 1783189849SRahul Lakkireddy * * Neither the name of Chelsio Communications nor the names of its 1883189849SRahul Lakkireddy * contributors may be used to endorse or promote products derived 1983189849SRahul Lakkireddy * from this software without specific prior written permission. 2083189849SRahul Lakkireddy * 2183189849SRahul Lakkireddy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2283189849SRahul Lakkireddy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2383189849SRahul Lakkireddy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2483189849SRahul Lakkireddy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2583189849SRahul Lakkireddy * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2683189849SRahul Lakkireddy * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2783189849SRahul Lakkireddy * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2883189849SRahul Lakkireddy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2983189849SRahul Lakkireddy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3083189849SRahul Lakkireddy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3183189849SRahul Lakkireddy * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3283189849SRahul Lakkireddy */ 3383189849SRahul Lakkireddy 3483189849SRahul Lakkireddy #include <sys/queue.h> 3583189849SRahul Lakkireddy #include <stdio.h> 3683189849SRahul Lakkireddy #include <errno.h> 3783189849SRahul Lakkireddy #include <stdint.h> 3883189849SRahul Lakkireddy #include <string.h> 3983189849SRahul Lakkireddy #include <unistd.h> 4083189849SRahul Lakkireddy #include <stdarg.h> 4183189849SRahul Lakkireddy #include <inttypes.h> 4283189849SRahul Lakkireddy #include <netinet/in.h> 4383189849SRahul Lakkireddy 4483189849SRahul Lakkireddy #include <rte_byteorder.h> 4583189849SRahul Lakkireddy #include <rte_common.h> 4683189849SRahul Lakkireddy #include <rte_cycles.h> 4783189849SRahul Lakkireddy #include <rte_interrupts.h> 4883189849SRahul Lakkireddy #include <rte_log.h> 4983189849SRahul Lakkireddy #include <rte_debug.h> 5083189849SRahul Lakkireddy #include <rte_pci.h> 5183189849SRahul Lakkireddy #include <rte_atomic.h> 5283189849SRahul Lakkireddy #include <rte_branch_prediction.h> 5383189849SRahul Lakkireddy #include <rte_memory.h> 5483189849SRahul Lakkireddy #include <rte_tailq.h> 5583189849SRahul Lakkireddy #include <rte_eal.h> 5683189849SRahul Lakkireddy #include <rte_alarm.h> 5783189849SRahul Lakkireddy #include <rte_ether.h> 58ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 597d012402SJan Blunck #include <rte_ethdev_pci.h> 6083189849SRahul Lakkireddy #include <rte_malloc.h> 6183189849SRahul Lakkireddy #include <rte_random.h> 6283189849SRahul Lakkireddy #include <rte_dev.h> 6383189849SRahul Lakkireddy 6483189849SRahul Lakkireddy #include "common.h" 6583189849SRahul Lakkireddy #include "t4_regs.h" 6683189849SRahul Lakkireddy #include "t4_msg.h" 6783189849SRahul Lakkireddy #include "cxgbe.h" 6883189849SRahul Lakkireddy 6992c8a632SRahul Lakkireddy /* 7092c8a632SRahul Lakkireddy * Response queue handler for the FW event queue. 7192c8a632SRahul Lakkireddy */ 7292c8a632SRahul Lakkireddy static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, 7392c8a632SRahul Lakkireddy __rte_unused const struct pkt_gl *gl) 7492c8a632SRahul Lakkireddy { 7592c8a632SRahul Lakkireddy u8 opcode = ((const struct rss_header *)rsp)->opcode; 7692c8a632SRahul Lakkireddy 7792c8a632SRahul Lakkireddy rsp++; /* skip RSS header */ 7892c8a632SRahul Lakkireddy 7992c8a632SRahul Lakkireddy /* 8092c8a632SRahul Lakkireddy * FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG. 8192c8a632SRahul Lakkireddy */ 8292c8a632SRahul Lakkireddy if (unlikely(opcode == CPL_FW4_MSG && 8392c8a632SRahul Lakkireddy ((const struct cpl_fw4_msg *)rsp)->type == 8492c8a632SRahul Lakkireddy FW_TYPE_RSSCPL)) { 8592c8a632SRahul Lakkireddy rsp++; 8692c8a632SRahul Lakkireddy opcode = ((const struct rss_header *)rsp)->opcode; 8792c8a632SRahul Lakkireddy rsp++; 8892c8a632SRahul Lakkireddy if (opcode != CPL_SGE_EGR_UPDATE) { 8992c8a632SRahul Lakkireddy dev_err(q->adapter, "unexpected FW4/CPL %#x on FW event queue\n", 9092c8a632SRahul Lakkireddy opcode); 9192c8a632SRahul Lakkireddy goto out; 9292c8a632SRahul Lakkireddy } 9392c8a632SRahul Lakkireddy } 9492c8a632SRahul Lakkireddy 9592c8a632SRahul Lakkireddy if (likely(opcode == CPL_SGE_EGR_UPDATE)) { 9692c8a632SRahul Lakkireddy /* do nothing */ 9792c8a632SRahul Lakkireddy } else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) { 9892c8a632SRahul Lakkireddy const struct cpl_fw6_msg *msg = (const void *)rsp; 9992c8a632SRahul Lakkireddy 10092c8a632SRahul Lakkireddy t4_handle_fw_rpl(q->adapter, msg->data); 10192c8a632SRahul Lakkireddy } else { 10292c8a632SRahul Lakkireddy dev_err(adapter, "unexpected CPL %#x on FW event queue\n", 10392c8a632SRahul Lakkireddy opcode); 10492c8a632SRahul Lakkireddy } 10592c8a632SRahul Lakkireddy out: 10692c8a632SRahul Lakkireddy return 0; 10792c8a632SRahul Lakkireddy } 10892c8a632SRahul Lakkireddy 10992c8a632SRahul Lakkireddy int setup_sge_fwevtq(struct adapter *adapter) 11092c8a632SRahul Lakkireddy { 11192c8a632SRahul Lakkireddy struct sge *s = &adapter->sge; 11292c8a632SRahul Lakkireddy int err = 0; 11392c8a632SRahul Lakkireddy int msi_idx = 0; 11492c8a632SRahul Lakkireddy 11592c8a632SRahul Lakkireddy err = t4_sge_alloc_rxq(adapter, &s->fw_evtq, true, adapter->eth_dev, 11692c8a632SRahul Lakkireddy msi_idx, NULL, fwevtq_handler, -1, NULL, 0, 11792c8a632SRahul Lakkireddy rte_socket_id()); 11892c8a632SRahul Lakkireddy return err; 11992c8a632SRahul Lakkireddy } 12092c8a632SRahul Lakkireddy 12192c8a632SRahul Lakkireddy static int closest_timer(const struct sge *s, int time) 12292c8a632SRahul Lakkireddy { 12392c8a632SRahul Lakkireddy unsigned int i, match = 0; 12492c8a632SRahul Lakkireddy int delta, min_delta = INT_MAX; 12592c8a632SRahul Lakkireddy 12692c8a632SRahul Lakkireddy for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) { 12792c8a632SRahul Lakkireddy delta = time - s->timer_val[i]; 12892c8a632SRahul Lakkireddy if (delta < 0) 12992c8a632SRahul Lakkireddy delta = -delta; 13092c8a632SRahul Lakkireddy if (delta < min_delta) { 13192c8a632SRahul Lakkireddy min_delta = delta; 13292c8a632SRahul Lakkireddy match = i; 13392c8a632SRahul Lakkireddy } 13492c8a632SRahul Lakkireddy } 13592c8a632SRahul Lakkireddy return match; 13692c8a632SRahul Lakkireddy } 13792c8a632SRahul Lakkireddy 13892c8a632SRahul Lakkireddy static int closest_thres(const struct sge *s, int thres) 13992c8a632SRahul Lakkireddy { 14092c8a632SRahul Lakkireddy unsigned int i, match = 0; 14192c8a632SRahul Lakkireddy int delta, min_delta = INT_MAX; 14292c8a632SRahul Lakkireddy 14392c8a632SRahul Lakkireddy for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) { 14492c8a632SRahul Lakkireddy delta = thres - s->counter_val[i]; 14592c8a632SRahul Lakkireddy if (delta < 0) 14692c8a632SRahul Lakkireddy delta = -delta; 14792c8a632SRahul Lakkireddy if (delta < min_delta) { 14892c8a632SRahul Lakkireddy min_delta = delta; 14992c8a632SRahul Lakkireddy match = i; 15092c8a632SRahul Lakkireddy } 15192c8a632SRahul Lakkireddy } 15292c8a632SRahul Lakkireddy return match; 15392c8a632SRahul Lakkireddy } 15492c8a632SRahul Lakkireddy 15592c8a632SRahul Lakkireddy /** 15692c8a632SRahul Lakkireddy * cxgb4_set_rspq_intr_params - set a queue's interrupt holdoff parameters 15792c8a632SRahul Lakkireddy * @q: the Rx queue 15892c8a632SRahul Lakkireddy * @us: the hold-off time in us, or 0 to disable timer 15992c8a632SRahul Lakkireddy * @cnt: the hold-off packet count, or 0 to disable counter 16092c8a632SRahul Lakkireddy * 16192c8a632SRahul Lakkireddy * Sets an Rx queue's interrupt hold-off time and packet count. At least 16292c8a632SRahul Lakkireddy * one of the two needs to be enabled for the queue to generate interrupts. 16392c8a632SRahul Lakkireddy */ 16492c8a632SRahul Lakkireddy int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us, 16592c8a632SRahul Lakkireddy unsigned int cnt) 16692c8a632SRahul Lakkireddy { 16792c8a632SRahul Lakkireddy struct adapter *adap = q->adapter; 16892c8a632SRahul Lakkireddy unsigned int timer_val; 16992c8a632SRahul Lakkireddy 17092c8a632SRahul Lakkireddy if (cnt) { 17192c8a632SRahul Lakkireddy int err; 17292c8a632SRahul Lakkireddy u32 v, new_idx; 17392c8a632SRahul Lakkireddy 17492c8a632SRahul Lakkireddy new_idx = closest_thres(&adap->sge, cnt); 17592c8a632SRahul Lakkireddy if (q->desc && q->pktcnt_idx != new_idx) { 17692c8a632SRahul Lakkireddy /* the queue has already been created, update it */ 17792c8a632SRahul Lakkireddy v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | 17892c8a632SRahul Lakkireddy V_FW_PARAMS_PARAM_X( 17992c8a632SRahul Lakkireddy FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) | 18092c8a632SRahul Lakkireddy V_FW_PARAMS_PARAM_YZ(q->cntxt_id); 18192c8a632SRahul Lakkireddy err = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, 18292c8a632SRahul Lakkireddy &v, &new_idx); 18392c8a632SRahul Lakkireddy if (err) 18492c8a632SRahul Lakkireddy return err; 18592c8a632SRahul Lakkireddy } 18692c8a632SRahul Lakkireddy q->pktcnt_idx = new_idx; 18792c8a632SRahul Lakkireddy } 18892c8a632SRahul Lakkireddy 18992c8a632SRahul Lakkireddy timer_val = (us == 0) ? X_TIMERREG_RESTART_COUNTER : 19092c8a632SRahul Lakkireddy closest_timer(&adap->sge, us); 19192c8a632SRahul Lakkireddy 19292c8a632SRahul Lakkireddy if ((us | cnt) == 0) 19392c8a632SRahul Lakkireddy q->intr_params = V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX); 19492c8a632SRahul Lakkireddy else 19592c8a632SRahul Lakkireddy q->intr_params = V_QINTR_TIMER_IDX(timer_val) | 19692c8a632SRahul Lakkireddy V_QINTR_CNT_EN(cnt > 0); 19792c8a632SRahul Lakkireddy return 0; 19892c8a632SRahul Lakkireddy } 19992c8a632SRahul Lakkireddy 20092c8a632SRahul Lakkireddy static inline bool is_x_1g_port(const struct link_config *lc) 20192c8a632SRahul Lakkireddy { 20276488837SRahul Lakkireddy return (lc->pcaps & FW_PORT_CAP32_SPEED_1G) != 0; 20392c8a632SRahul Lakkireddy } 20492c8a632SRahul Lakkireddy 20592c8a632SRahul Lakkireddy static inline bool is_x_10g_port(const struct link_config *lc) 20692c8a632SRahul Lakkireddy { 2079da2a694SRahul Lakkireddy unsigned int speeds, high_speeds; 2089da2a694SRahul Lakkireddy 20976488837SRahul Lakkireddy speeds = V_FW_PORT_CAP32_SPEED(G_FW_PORT_CAP32_SPEED(lc->pcaps)); 21076488837SRahul Lakkireddy high_speeds = speeds & 21176488837SRahul Lakkireddy ~(FW_PORT_CAP32_SPEED_100M | FW_PORT_CAP32_SPEED_1G); 2129da2a694SRahul Lakkireddy 2139da2a694SRahul Lakkireddy return high_speeds != 0; 21492c8a632SRahul Lakkireddy } 21592c8a632SRahul Lakkireddy 21692c8a632SRahul Lakkireddy inline void init_rspq(struct adapter *adap, struct sge_rspq *q, 21792c8a632SRahul Lakkireddy unsigned int us, unsigned int cnt, 21892c8a632SRahul Lakkireddy unsigned int size, unsigned int iqe_size) 21992c8a632SRahul Lakkireddy { 22092c8a632SRahul Lakkireddy q->adapter = adap; 22192c8a632SRahul Lakkireddy cxgb4_set_rspq_intr_params(q, us, cnt); 22292c8a632SRahul Lakkireddy q->iqe_len = iqe_size; 22392c8a632SRahul Lakkireddy q->size = size; 22492c8a632SRahul Lakkireddy } 22592c8a632SRahul Lakkireddy 22692c8a632SRahul Lakkireddy int cfg_queue_count(struct rte_eth_dev *eth_dev) 22792c8a632SRahul Lakkireddy { 22892c8a632SRahul Lakkireddy struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); 22992c8a632SRahul Lakkireddy struct adapter *adap = pi->adapter; 23092c8a632SRahul Lakkireddy struct sge *s = &adap->sge; 23192c8a632SRahul Lakkireddy unsigned int max_queues = s->max_ethqsets / adap->params.nports; 23292c8a632SRahul Lakkireddy 23392c8a632SRahul Lakkireddy if ((eth_dev->data->nb_rx_queues < 1) || 23492c8a632SRahul Lakkireddy (eth_dev->data->nb_tx_queues < 1)) 23592c8a632SRahul Lakkireddy return -EINVAL; 23692c8a632SRahul Lakkireddy 23792c8a632SRahul Lakkireddy if ((eth_dev->data->nb_rx_queues > max_queues) || 23892c8a632SRahul Lakkireddy (eth_dev->data->nb_tx_queues > max_queues)) 23992c8a632SRahul Lakkireddy return -EINVAL; 24092c8a632SRahul Lakkireddy 24192c8a632SRahul Lakkireddy if (eth_dev->data->nb_rx_queues > pi->rss_size) 24292c8a632SRahul Lakkireddy return -EINVAL; 24392c8a632SRahul Lakkireddy 24492c8a632SRahul Lakkireddy /* We must configure RSS, since config has changed*/ 24592c8a632SRahul Lakkireddy pi->flags &= ~PORT_RSS_DONE; 24692c8a632SRahul Lakkireddy 24792c8a632SRahul Lakkireddy pi->n_rx_qsets = eth_dev->data->nb_rx_queues; 24892c8a632SRahul Lakkireddy pi->n_tx_qsets = eth_dev->data->nb_tx_queues; 24992c8a632SRahul Lakkireddy 25092c8a632SRahul Lakkireddy return 0; 25192c8a632SRahul Lakkireddy } 25292c8a632SRahul Lakkireddy 25392c8a632SRahul Lakkireddy void cfg_queues(struct rte_eth_dev *eth_dev) 25492c8a632SRahul Lakkireddy { 25592c8a632SRahul Lakkireddy struct rte_config *config = rte_eal_get_configuration(); 25692c8a632SRahul Lakkireddy struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); 25792c8a632SRahul Lakkireddy struct adapter *adap = pi->adapter; 25892c8a632SRahul Lakkireddy struct sge *s = &adap->sge; 25992c8a632SRahul Lakkireddy unsigned int i, nb_ports = 0, qidx = 0; 26092c8a632SRahul Lakkireddy unsigned int q_per_port = 0; 26192c8a632SRahul Lakkireddy 26292c8a632SRahul Lakkireddy if (!(adap->flags & CFG_QUEUES)) { 26392c8a632SRahul Lakkireddy for_each_port(adap, i) { 26492c8a632SRahul Lakkireddy struct port_info *tpi = adap2pinfo(adap, i); 26592c8a632SRahul Lakkireddy 26692c8a632SRahul Lakkireddy nb_ports += (is_x_10g_port(&tpi->link_cfg)) || 26792c8a632SRahul Lakkireddy is_x_1g_port(&tpi->link_cfg) ? 1 : 0; 26892c8a632SRahul Lakkireddy } 26992c8a632SRahul Lakkireddy 27092c8a632SRahul Lakkireddy /* 27192c8a632SRahul Lakkireddy * We default up to # of cores queues per 1G/10G port. 27292c8a632SRahul Lakkireddy */ 27392c8a632SRahul Lakkireddy if (nb_ports) 27492c8a632SRahul Lakkireddy q_per_port = (MAX_ETH_QSETS - 27592c8a632SRahul Lakkireddy (adap->params.nports - nb_ports)) / 27692c8a632SRahul Lakkireddy nb_ports; 27792c8a632SRahul Lakkireddy 27892c8a632SRahul Lakkireddy if (q_per_port > config->lcore_count) 27992c8a632SRahul Lakkireddy q_per_port = config->lcore_count; 28092c8a632SRahul Lakkireddy 28192c8a632SRahul Lakkireddy for_each_port(adap, i) { 28292c8a632SRahul Lakkireddy struct port_info *pi = adap2pinfo(adap, i); 28392c8a632SRahul Lakkireddy 28492c8a632SRahul Lakkireddy pi->first_qset = qidx; 28592c8a632SRahul Lakkireddy 28692c8a632SRahul Lakkireddy /* Initially n_rx_qsets == n_tx_qsets */ 28792c8a632SRahul Lakkireddy pi->n_rx_qsets = (is_x_10g_port(&pi->link_cfg) || 28892c8a632SRahul Lakkireddy is_x_1g_port(&pi->link_cfg)) ? 28992c8a632SRahul Lakkireddy q_per_port : 1; 29092c8a632SRahul Lakkireddy pi->n_tx_qsets = pi->n_rx_qsets; 29192c8a632SRahul Lakkireddy 29292c8a632SRahul Lakkireddy if (pi->n_rx_qsets > pi->rss_size) 29392c8a632SRahul Lakkireddy pi->n_rx_qsets = pi->rss_size; 29492c8a632SRahul Lakkireddy 29592c8a632SRahul Lakkireddy qidx += pi->n_rx_qsets; 29692c8a632SRahul Lakkireddy } 29792c8a632SRahul Lakkireddy 29892c8a632SRahul Lakkireddy s->max_ethqsets = qidx; 29992c8a632SRahul Lakkireddy 30092c8a632SRahul Lakkireddy for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) { 30192c8a632SRahul Lakkireddy struct sge_eth_rxq *r = &s->ethrxq[i]; 30292c8a632SRahul Lakkireddy 3036c280962SRahul Lakkireddy init_rspq(adap, &r->rspq, 5, 32, 1024, 64); 30492c8a632SRahul Lakkireddy r->usembufs = 1; 30592c8a632SRahul Lakkireddy r->fl.size = (r->usembufs ? 1024 : 72); 30692c8a632SRahul Lakkireddy } 30792c8a632SRahul Lakkireddy 30892c8a632SRahul Lakkireddy for (i = 0; i < ARRAY_SIZE(s->ethtxq); i++) 30992c8a632SRahul Lakkireddy s->ethtxq[i].q.size = 1024; 31092c8a632SRahul Lakkireddy 31192c8a632SRahul Lakkireddy init_rspq(adap, &adap->sge.fw_evtq, 0, 0, 1024, 64); 31292c8a632SRahul Lakkireddy adap->flags |= CFG_QUEUES; 31392c8a632SRahul Lakkireddy } 31492c8a632SRahul Lakkireddy } 31592c8a632SRahul Lakkireddy 316856505d3SRahul Lakkireddy void cxgbe_stats_get(struct port_info *pi, struct port_stats *stats) 317856505d3SRahul Lakkireddy { 318856505d3SRahul Lakkireddy t4_get_port_stats_offset(pi->adapter, pi->tx_chan, stats, 319856505d3SRahul Lakkireddy &pi->stats_base); 320856505d3SRahul Lakkireddy } 321856505d3SRahul Lakkireddy 322856505d3SRahul Lakkireddy void cxgbe_stats_reset(struct port_info *pi) 323856505d3SRahul Lakkireddy { 324856505d3SRahul Lakkireddy t4_clr_port_stats(pi->adapter, pi->tx_chan); 325856505d3SRahul Lakkireddy } 326856505d3SRahul Lakkireddy 32783189849SRahul Lakkireddy static void setup_memwin(struct adapter *adap) 32883189849SRahul Lakkireddy { 32983189849SRahul Lakkireddy u32 mem_win0_base; 33083189849SRahul Lakkireddy 33183189849SRahul Lakkireddy /* For T5, only relative offset inside the PCIe BAR is passed */ 33283189849SRahul Lakkireddy mem_win0_base = MEMWIN0_BASE; 33383189849SRahul Lakkireddy 33483189849SRahul Lakkireddy /* 33583189849SRahul Lakkireddy * Set up memory window for accessing adapter memory ranges. (Read 33683189849SRahul Lakkireddy * back MA register to ensure that changes propagate before we attempt 33783189849SRahul Lakkireddy * to use the new values.) 33883189849SRahul Lakkireddy */ 33983189849SRahul Lakkireddy t4_write_reg(adap, 34083189849SRahul Lakkireddy PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, 34183189849SRahul Lakkireddy MEMWIN_NIC), 34283189849SRahul Lakkireddy mem_win0_base | V_BIR(0) | 34383189849SRahul Lakkireddy V_WINDOW(ilog2(MEMWIN0_APERTURE) - X_WINDOW_SHIFT)); 34483189849SRahul Lakkireddy t4_read_reg(adap, 34583189849SRahul Lakkireddy PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, 34683189849SRahul Lakkireddy MEMWIN_NIC)); 34783189849SRahul Lakkireddy } 34883189849SRahul Lakkireddy 34992c8a632SRahul Lakkireddy static int init_rss(struct adapter *adap) 35092c8a632SRahul Lakkireddy { 35192c8a632SRahul Lakkireddy unsigned int i; 35292c8a632SRahul Lakkireddy int err; 35392c8a632SRahul Lakkireddy 35492c8a632SRahul Lakkireddy err = t4_init_rss_mode(adap, adap->mbox); 35592c8a632SRahul Lakkireddy if (err) 35692c8a632SRahul Lakkireddy return err; 35792c8a632SRahul Lakkireddy 35892c8a632SRahul Lakkireddy for_each_port(adap, i) { 35992c8a632SRahul Lakkireddy struct port_info *pi = adap2pinfo(adap, i); 36092c8a632SRahul Lakkireddy 3618dca8cc5SRahul Lakkireddy pi->rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0); 36292c8a632SRahul Lakkireddy if (!pi->rss) 36392c8a632SRahul Lakkireddy return -ENOMEM; 36408e21af9SKumar Sanghvi 36508e21af9SKumar Sanghvi pi->rss_hf = CXGBE_RSS_HF_ALL; 36692c8a632SRahul Lakkireddy } 36792c8a632SRahul Lakkireddy return 0; 36892c8a632SRahul Lakkireddy } 36992c8a632SRahul Lakkireddy 370c962618cSRahul Lakkireddy /** 371c962618cSRahul Lakkireddy * Dump basic information about the adapter. 372c962618cSRahul Lakkireddy */ 373*5e80364aSKumar Sanghvi void print_adapter_info(struct adapter *adap) 374c962618cSRahul Lakkireddy { 375c962618cSRahul Lakkireddy /** 376c962618cSRahul Lakkireddy * Hardware/Firmware/etc. Version/Revision IDs. 377c962618cSRahul Lakkireddy */ 378c962618cSRahul Lakkireddy t4_dump_version_info(adap); 379c962618cSRahul Lakkireddy } 380c962618cSRahul Lakkireddy 381*5e80364aSKumar Sanghvi void print_port_info(struct adapter *adap) 38283189849SRahul Lakkireddy { 38383189849SRahul Lakkireddy int i; 38483189849SRahul Lakkireddy char buf[80]; 38583189849SRahul Lakkireddy struct rte_pci_addr *loc = &adap->pdev->addr; 38683189849SRahul Lakkireddy 38783189849SRahul Lakkireddy for_each_port(adap, i) { 3882195df6dSRahul Lakkireddy const struct port_info *pi = adap2pinfo(adap, i); 38983189849SRahul Lakkireddy char *bufp = buf; 39083189849SRahul Lakkireddy 39176488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M) 3929da2a694SRahul Lakkireddy bufp += sprintf(bufp, "100M/"); 39376488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G) 3949da2a694SRahul Lakkireddy bufp += sprintf(bufp, "1G/"); 39576488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_10G) 39683189849SRahul Lakkireddy bufp += sprintf(bufp, "10G/"); 39776488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_25G) 3989da2a694SRahul Lakkireddy bufp += sprintf(bufp, "25G/"); 39976488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_40G) 40083189849SRahul Lakkireddy bufp += sprintf(bufp, "40G/"); 40176488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_50G) 40276488837SRahul Lakkireddy bufp += sprintf(bufp, "50G/"); 40376488837SRahul Lakkireddy if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100G) 4049da2a694SRahul Lakkireddy bufp += sprintf(bufp, "100G/"); 40583189849SRahul Lakkireddy if (bufp != buf) 40683189849SRahul Lakkireddy --bufp; 40783189849SRahul Lakkireddy sprintf(bufp, "BASE-%s", 408efa8a43eSBruce Richardson t4_get_port_type_description( 409efa8a43eSBruce Richardson (enum fw_port_type)pi->port_type)); 41083189849SRahul Lakkireddy 41183189849SRahul Lakkireddy dev_info(adap, 41283189849SRahul Lakkireddy " " PCI_PRI_FMT " Chelsio rev %d %s %s\n", 41383189849SRahul Lakkireddy loc->domain, loc->bus, loc->devid, loc->function, 41483189849SRahul Lakkireddy CHELSIO_CHIP_RELEASE(adap->params.chip), buf, 41583189849SRahul Lakkireddy (adap->flags & USING_MSIX) ? " MSI-X" : 41683189849SRahul Lakkireddy (adap->flags & USING_MSI) ? " MSI" : ""); 41783189849SRahul Lakkireddy } 41883189849SRahul Lakkireddy } 41983189849SRahul Lakkireddy 420ee606d92SRahul Lakkireddy static void configure_pcie_ext_tag(struct adapter *adapter) 421ee606d92SRahul Lakkireddy { 422ee606d92SRahul Lakkireddy u16 v; 423ee606d92SRahul Lakkireddy int pos = t4_os_find_pci_capability(adapter, PCI_CAP_ID_EXP); 424ee606d92SRahul Lakkireddy 425ee606d92SRahul Lakkireddy if (!pos) 426ee606d92SRahul Lakkireddy return; 427ee606d92SRahul Lakkireddy 428ee606d92SRahul Lakkireddy if (pos > 0) { 429ee606d92SRahul Lakkireddy t4_os_pci_read_cfg2(adapter, pos + PCI_EXP_DEVCTL, &v); 430ee606d92SRahul Lakkireddy v |= PCI_EXP_DEVCTL_EXT_TAG; 431ee606d92SRahul Lakkireddy t4_os_pci_write_cfg2(adapter, pos + PCI_EXP_DEVCTL, v); 432ee606d92SRahul Lakkireddy if (is_t6(adapter->params.chip)) { 433ee606d92SRahul Lakkireddy t4_set_reg_field(adapter, A_PCIE_CFG2, 434ee606d92SRahul Lakkireddy V_T6_TOTMAXTAG(M_T6_TOTMAXTAG), 435ee606d92SRahul Lakkireddy V_T6_TOTMAXTAG(7)); 436ee606d92SRahul Lakkireddy t4_set_reg_field(adapter, A_PCIE_CMD_CFG, 437ee606d92SRahul Lakkireddy V_T6_MINTAG(M_T6_MINTAG), 438ee606d92SRahul Lakkireddy V_T6_MINTAG(8)); 439ee606d92SRahul Lakkireddy } else { 440ee606d92SRahul Lakkireddy t4_set_reg_field(adapter, A_PCIE_CFG2, 441ee606d92SRahul Lakkireddy V_TOTMAXTAG(M_TOTMAXTAG), 442ee606d92SRahul Lakkireddy V_TOTMAXTAG(3)); 443ee606d92SRahul Lakkireddy t4_set_reg_field(adapter, A_PCIE_CMD_CFG, 444ee606d92SRahul Lakkireddy V_MINTAG(M_MINTAG), 445ee606d92SRahul Lakkireddy V_MINTAG(8)); 446ee606d92SRahul Lakkireddy } 447ee606d92SRahul Lakkireddy } 448ee606d92SRahul Lakkireddy } 449ee606d92SRahul Lakkireddy 45083189849SRahul Lakkireddy /* 45183189849SRahul Lakkireddy * Tweak configuration based on system architecture, etc. Most of these have 45283189849SRahul Lakkireddy * defaults assigned to them by Firmware Configuration Files (if we're using 45383189849SRahul Lakkireddy * them) but need to be explicitly set if we're using hard-coded 45483189849SRahul Lakkireddy * initialization. So these are essentially common tweaks/settings for 45583189849SRahul Lakkireddy * Configuration Files and hard-coded initialization ... 45683189849SRahul Lakkireddy */ 45783189849SRahul Lakkireddy static int adap_init0_tweaks(struct adapter *adapter) 45883189849SRahul Lakkireddy { 45983189849SRahul Lakkireddy u8 rx_dma_offset; 46083189849SRahul Lakkireddy 46183189849SRahul Lakkireddy /* 46283189849SRahul Lakkireddy * Fix up various Host-Dependent Parameters like Page Size, Cache 46383189849SRahul Lakkireddy * Line Size, etc. The firmware default is for a 4KB Page Size and 46483189849SRahul Lakkireddy * 64B Cache Line Size ... 46583189849SRahul Lakkireddy */ 4661f8613f1SRahul Lakkireddy t4_fixup_host_params_compat(adapter, CXGBE_PAGE_SIZE, L1_CACHE_BYTES, 46783189849SRahul Lakkireddy T5_LAST_REV); 46883189849SRahul Lakkireddy 46983189849SRahul Lakkireddy /* 47083189849SRahul Lakkireddy * Keep the chip default offset to deliver Ingress packets into our 47183189849SRahul Lakkireddy * DMA buffers to zero 47283189849SRahul Lakkireddy */ 47383189849SRahul Lakkireddy rx_dma_offset = 0; 47483189849SRahul Lakkireddy t4_set_reg_field(adapter, A_SGE_CONTROL, V_PKTSHIFT(M_PKTSHIFT), 47583189849SRahul Lakkireddy V_PKTSHIFT(rx_dma_offset)); 47683189849SRahul Lakkireddy 477bf89cbedSRahul Lakkireddy t4_set_reg_field(adapter, A_SGE_FLM_CFG, 478bf89cbedSRahul Lakkireddy V_CREDITCNT(M_CREDITCNT) | M_CREDITCNTPACKING, 479bf89cbedSRahul Lakkireddy V_CREDITCNT(3) | V_CREDITCNTPACKING(1)); 480bf89cbedSRahul Lakkireddy 4816c280962SRahul Lakkireddy t4_set_reg_field(adapter, A_SGE_INGRESS_RX_THRESHOLD, 4826c280962SRahul Lakkireddy V_THRESHOLD_3(M_THRESHOLD_3), V_THRESHOLD_3(32U)); 4836c280962SRahul Lakkireddy 484bf89cbedSRahul Lakkireddy t4_set_reg_field(adapter, A_SGE_CONTROL2, V_IDMAARBROUNDROBIN(1U), 485bf89cbedSRahul Lakkireddy V_IDMAARBROUNDROBIN(1U)); 486bf89cbedSRahul Lakkireddy 48783189849SRahul Lakkireddy /* 48883189849SRahul Lakkireddy * Don't include the "IP Pseudo Header" in CPL_RX_PKT checksums: Linux 48983189849SRahul Lakkireddy * adds the pseudo header itself. 49083189849SRahul Lakkireddy */ 49183189849SRahul Lakkireddy t4_tp_wr_bits_indirect(adapter, A_TP_INGRESS_CONFIG, 49283189849SRahul Lakkireddy F_CSUM_HAS_PSEUDO_HDR, 0); 49383189849SRahul Lakkireddy 49483189849SRahul Lakkireddy return 0; 49583189849SRahul Lakkireddy } 49683189849SRahul Lakkireddy 49783189849SRahul Lakkireddy /* 49883189849SRahul Lakkireddy * Attempt to initialize the adapter via a Firmware Configuration File. 49983189849SRahul Lakkireddy */ 50083189849SRahul Lakkireddy static int adap_init0_config(struct adapter *adapter, int reset) 50183189849SRahul Lakkireddy { 50283189849SRahul Lakkireddy struct fw_caps_config_cmd caps_cmd; 50383189849SRahul Lakkireddy unsigned long mtype = 0, maddr = 0; 50483189849SRahul Lakkireddy u32 finiver, finicsum, cfcsum; 50583189849SRahul Lakkireddy int ret; 50683189849SRahul Lakkireddy int config_issued = 0; 50783189849SRahul Lakkireddy int cfg_addr; 50883189849SRahul Lakkireddy char config_name[20]; 50983189849SRahul Lakkireddy 51083189849SRahul Lakkireddy /* 51183189849SRahul Lakkireddy * Reset device if necessary. 51283189849SRahul Lakkireddy */ 51383189849SRahul Lakkireddy if (reset) { 51483189849SRahul Lakkireddy ret = t4_fw_reset(adapter, adapter->mbox, 51583189849SRahul Lakkireddy F_PIORSTMODE | F_PIORST); 51683189849SRahul Lakkireddy if (ret < 0) { 51783189849SRahul Lakkireddy dev_warn(adapter, "Firmware reset failed, error %d\n", 51883189849SRahul Lakkireddy -ret); 51983189849SRahul Lakkireddy goto bye; 52083189849SRahul Lakkireddy } 52183189849SRahul Lakkireddy } 52283189849SRahul Lakkireddy 52383189849SRahul Lakkireddy cfg_addr = t4_flash_cfg_addr(adapter); 52483189849SRahul Lakkireddy if (cfg_addr < 0) { 52583189849SRahul Lakkireddy ret = cfg_addr; 52683189849SRahul Lakkireddy dev_warn(adapter, "Finding address for firmware config file in flash failed, error %d\n", 52783189849SRahul Lakkireddy -ret); 52883189849SRahul Lakkireddy goto bye; 52983189849SRahul Lakkireddy } 53083189849SRahul Lakkireddy 53183189849SRahul Lakkireddy strcpy(config_name, "On Flash"); 53283189849SRahul Lakkireddy mtype = FW_MEMTYPE_CF_FLASH; 53383189849SRahul Lakkireddy maddr = cfg_addr; 53483189849SRahul Lakkireddy 53583189849SRahul Lakkireddy /* 53683189849SRahul Lakkireddy * Issue a Capability Configuration command to the firmware to get it 53783189849SRahul Lakkireddy * to parse the Configuration File. We don't use t4_fw_config_file() 53883189849SRahul Lakkireddy * because we want the ability to modify various features after we've 53983189849SRahul Lakkireddy * processed the configuration file ... 54083189849SRahul Lakkireddy */ 54183189849SRahul Lakkireddy memset(&caps_cmd, 0, sizeof(caps_cmd)); 54283189849SRahul Lakkireddy caps_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | 54383189849SRahul Lakkireddy F_FW_CMD_REQUEST | F_FW_CMD_READ); 54483189849SRahul Lakkireddy caps_cmd.cfvalid_to_len16 = 54583189849SRahul Lakkireddy cpu_to_be32(F_FW_CAPS_CONFIG_CMD_CFVALID | 54683189849SRahul Lakkireddy V_FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | 54783189849SRahul Lakkireddy V_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | 54883189849SRahul Lakkireddy FW_LEN16(caps_cmd)); 54983189849SRahul Lakkireddy ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), 55083189849SRahul Lakkireddy &caps_cmd); 55183189849SRahul Lakkireddy /* 55283189849SRahul Lakkireddy * If the CAPS_CONFIG failed with an ENOENT (for a Firmware 55383189849SRahul Lakkireddy * Configuration File in FLASH), our last gasp effort is to use the 55483189849SRahul Lakkireddy * Firmware Configuration File which is embedded in the firmware. A 55583189849SRahul Lakkireddy * very few early versions of the firmware didn't have one embedded 55683189849SRahul Lakkireddy * but we can ignore those. 55783189849SRahul Lakkireddy */ 55883189849SRahul Lakkireddy if (ret == -ENOENT) { 55983189849SRahul Lakkireddy dev_info(adapter, "%s: Going for embedded config in firmware..\n", 56083189849SRahul Lakkireddy __func__); 56183189849SRahul Lakkireddy 56283189849SRahul Lakkireddy memset(&caps_cmd, 0, sizeof(caps_cmd)); 56383189849SRahul Lakkireddy caps_cmd.op_to_write = 56483189849SRahul Lakkireddy cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | 56583189849SRahul Lakkireddy F_FW_CMD_REQUEST | F_FW_CMD_READ); 56683189849SRahul Lakkireddy caps_cmd.cfvalid_to_len16 = cpu_to_be32(FW_LEN16(caps_cmd)); 56783189849SRahul Lakkireddy ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, 56883189849SRahul Lakkireddy sizeof(caps_cmd), &caps_cmd); 56983189849SRahul Lakkireddy strcpy(config_name, "Firmware Default"); 57083189849SRahul Lakkireddy } 57183189849SRahul Lakkireddy 57283189849SRahul Lakkireddy config_issued = 1; 57383189849SRahul Lakkireddy if (ret < 0) 57483189849SRahul Lakkireddy goto bye; 57583189849SRahul Lakkireddy 57683189849SRahul Lakkireddy finiver = be32_to_cpu(caps_cmd.finiver); 57783189849SRahul Lakkireddy finicsum = be32_to_cpu(caps_cmd.finicsum); 57883189849SRahul Lakkireddy cfcsum = be32_to_cpu(caps_cmd.cfcsum); 57983189849SRahul Lakkireddy if (finicsum != cfcsum) 58083189849SRahul Lakkireddy dev_warn(adapter, "Configuration File checksum mismatch: [fini] csum=%#x, computed csum=%#x\n", 58183189849SRahul Lakkireddy finicsum, cfcsum); 58283189849SRahul Lakkireddy 58383189849SRahul Lakkireddy /* 58483189849SRahul Lakkireddy * If we're a pure NIC driver then disable all offloading facilities. 58583189849SRahul Lakkireddy * This will allow the firmware to optimize aspects of the hardware 58683189849SRahul Lakkireddy * configuration which will result in improved performance. 58783189849SRahul Lakkireddy */ 58883189849SRahul Lakkireddy caps_cmd.niccaps &= cpu_to_be16(~(FW_CAPS_CONFIG_NIC_HASHFILTER | 58983189849SRahul Lakkireddy FW_CAPS_CONFIG_NIC_ETHOFLD)); 59083189849SRahul Lakkireddy caps_cmd.toecaps = 0; 59183189849SRahul Lakkireddy caps_cmd.iscsicaps = 0; 59283189849SRahul Lakkireddy caps_cmd.rdmacaps = 0; 59383189849SRahul Lakkireddy caps_cmd.fcoecaps = 0; 59483189849SRahul Lakkireddy 59583189849SRahul Lakkireddy /* 59683189849SRahul Lakkireddy * And now tell the firmware to use the configuration we just loaded. 59783189849SRahul Lakkireddy */ 59883189849SRahul Lakkireddy caps_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | 59983189849SRahul Lakkireddy F_FW_CMD_REQUEST | F_FW_CMD_WRITE); 60083189849SRahul Lakkireddy caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); 60183189849SRahul Lakkireddy ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), 60283189849SRahul Lakkireddy NULL); 60383189849SRahul Lakkireddy if (ret < 0) { 60483189849SRahul Lakkireddy dev_warn(adapter, "Unable to finalize Firmware Capabilities %d\n", 60583189849SRahul Lakkireddy -ret); 60683189849SRahul Lakkireddy goto bye; 60783189849SRahul Lakkireddy } 60883189849SRahul Lakkireddy 60983189849SRahul Lakkireddy /* 61083189849SRahul Lakkireddy * Tweak configuration based on system architecture, etc. 61183189849SRahul Lakkireddy */ 61283189849SRahul Lakkireddy ret = adap_init0_tweaks(adapter); 61383189849SRahul Lakkireddy if (ret < 0) { 61483189849SRahul Lakkireddy dev_warn(adapter, "Unable to do init0-tweaks %d\n", -ret); 61583189849SRahul Lakkireddy goto bye; 61683189849SRahul Lakkireddy } 61783189849SRahul Lakkireddy 61883189849SRahul Lakkireddy /* 61983189849SRahul Lakkireddy * And finally tell the firmware to initialize itself using the 62083189849SRahul Lakkireddy * parameters from the Configuration File. 62183189849SRahul Lakkireddy */ 62283189849SRahul Lakkireddy ret = t4_fw_initialize(adapter, adapter->mbox); 62383189849SRahul Lakkireddy if (ret < 0) { 62483189849SRahul Lakkireddy dev_warn(adapter, "Initializing Firmware failed, error %d\n", 62583189849SRahul Lakkireddy -ret); 62683189849SRahul Lakkireddy goto bye; 62783189849SRahul Lakkireddy } 62883189849SRahul Lakkireddy 62983189849SRahul Lakkireddy /* 63083189849SRahul Lakkireddy * Return successfully and note that we're operating with parameters 63183189849SRahul Lakkireddy * not supplied by the driver, rather than from hard-wired 63298a7ea33SJerin Jacob * initialization constants buried in the driver. 63383189849SRahul Lakkireddy */ 63483189849SRahul Lakkireddy dev_info(adapter, 63583189849SRahul Lakkireddy "Successfully configured using Firmware Configuration File \"%s\", version %#x, computed checksum %#x\n", 63683189849SRahul Lakkireddy config_name, finiver, cfcsum); 63783189849SRahul Lakkireddy 63883189849SRahul Lakkireddy return 0; 63983189849SRahul Lakkireddy 64083189849SRahul Lakkireddy /* 64183189849SRahul Lakkireddy * Something bad happened. Return the error ... (If the "error" 64283189849SRahul Lakkireddy * is that there's no Configuration File on the adapter we don't 64383189849SRahul Lakkireddy * want to issue a warning since this is fairly common.) 64483189849SRahul Lakkireddy */ 64583189849SRahul Lakkireddy bye: 64683189849SRahul Lakkireddy if (config_issued && ret != -ENOENT) 64783189849SRahul Lakkireddy dev_warn(adapter, "\"%s\" configuration file error %d\n", 64883189849SRahul Lakkireddy config_name, -ret); 64983189849SRahul Lakkireddy 65083189849SRahul Lakkireddy dev_debug(adapter, "%s: returning ret = %d ..\n", __func__, ret); 65183189849SRahul Lakkireddy return ret; 65283189849SRahul Lakkireddy } 65383189849SRahul Lakkireddy 65483189849SRahul Lakkireddy static int adap_init0(struct adapter *adap) 65583189849SRahul Lakkireddy { 65683189849SRahul Lakkireddy int ret = 0; 65783189849SRahul Lakkireddy u32 v, port_vec; 65883189849SRahul Lakkireddy enum dev_state state; 65983189849SRahul Lakkireddy u32 params[7], val[7]; 66083189849SRahul Lakkireddy int reset = 1; 66183189849SRahul Lakkireddy int mbox = adap->mbox; 66283189849SRahul Lakkireddy 66383189849SRahul Lakkireddy /* 66483189849SRahul Lakkireddy * Contact FW, advertising Master capability. 66583189849SRahul Lakkireddy */ 66683189849SRahul Lakkireddy ret = t4_fw_hello(adap, adap->mbox, adap->mbox, MASTER_MAY, &state); 66783189849SRahul Lakkireddy if (ret < 0) { 66883189849SRahul Lakkireddy dev_err(adap, "%s: could not connect to FW, error %d\n", 66983189849SRahul Lakkireddy __func__, -ret); 67083189849SRahul Lakkireddy goto bye; 67183189849SRahul Lakkireddy } 67283189849SRahul Lakkireddy 67383189849SRahul Lakkireddy CXGBE_DEBUG_MBOX(adap, "%s: adap->mbox = %d; ret = %d\n", __func__, 67483189849SRahul Lakkireddy adap->mbox, ret); 67583189849SRahul Lakkireddy 67683189849SRahul Lakkireddy if (ret == mbox) 67783189849SRahul Lakkireddy adap->flags |= MASTER_PF; 67883189849SRahul Lakkireddy 67983189849SRahul Lakkireddy if (state == DEV_STATE_INIT) { 68083189849SRahul Lakkireddy /* 68183189849SRahul Lakkireddy * Force halt and reset FW because a previous instance may have 68283189849SRahul Lakkireddy * exited abnormally without properly shutting down 68383189849SRahul Lakkireddy */ 68483189849SRahul Lakkireddy ret = t4_fw_halt(adap, adap->mbox, reset); 68583189849SRahul Lakkireddy if (ret < 0) { 68683189849SRahul Lakkireddy dev_err(adap, "Failed to halt. Exit.\n"); 68783189849SRahul Lakkireddy goto bye; 68883189849SRahul Lakkireddy } 68983189849SRahul Lakkireddy 69083189849SRahul Lakkireddy ret = t4_fw_restart(adap, adap->mbox, reset); 69183189849SRahul Lakkireddy if (ret < 0) { 69283189849SRahul Lakkireddy dev_err(adap, "Failed to restart. Exit.\n"); 69383189849SRahul Lakkireddy goto bye; 69483189849SRahul Lakkireddy } 695efa8a43eSBruce Richardson state = (enum dev_state)((unsigned)state & ~DEV_STATE_INIT); 69683189849SRahul Lakkireddy } 69783189849SRahul Lakkireddy 698c962618cSRahul Lakkireddy t4_get_version_info(adap); 69983189849SRahul Lakkireddy 70083189849SRahul Lakkireddy ret = t4_get_core_clock(adap, &adap->params.vpd); 70183189849SRahul Lakkireddy if (ret < 0) { 70283189849SRahul Lakkireddy dev_err(adap, "%s: could not get core clock, error %d\n", 70383189849SRahul Lakkireddy __func__, -ret); 70483189849SRahul Lakkireddy goto bye; 70583189849SRahul Lakkireddy } 70683189849SRahul Lakkireddy 70783189849SRahul Lakkireddy /* 70883189849SRahul Lakkireddy * If the firmware is initialized already (and we're not forcing a 70983189849SRahul Lakkireddy * master initialization), note that we're living with existing 71083189849SRahul Lakkireddy * adapter parameters. Otherwise, it's time to try initializing the 71183189849SRahul Lakkireddy * adapter ... 71283189849SRahul Lakkireddy */ 71383189849SRahul Lakkireddy if (state == DEV_STATE_INIT) { 71483189849SRahul Lakkireddy dev_info(adap, "Coming up as %s: Adapter already initialized\n", 71583189849SRahul Lakkireddy adap->flags & MASTER_PF ? "MASTER" : "SLAVE"); 71683189849SRahul Lakkireddy } else { 71783189849SRahul Lakkireddy dev_info(adap, "Coming up as MASTER: Initializing adapter\n"); 71883189849SRahul Lakkireddy 71983189849SRahul Lakkireddy ret = adap_init0_config(adap, reset); 72083189849SRahul Lakkireddy if (ret == -ENOENT) { 72183189849SRahul Lakkireddy dev_err(adap, 72283189849SRahul Lakkireddy "No Configuration File present on adapter. Using hard-wired configuration parameters.\n"); 72383189849SRahul Lakkireddy goto bye; 72483189849SRahul Lakkireddy } 72583189849SRahul Lakkireddy } 72683189849SRahul Lakkireddy if (ret < 0) { 72783189849SRahul Lakkireddy dev_err(adap, "could not initialize adapter, error %d\n", -ret); 72883189849SRahul Lakkireddy goto bye; 72983189849SRahul Lakkireddy } 73083189849SRahul Lakkireddy 7315eb55bf8SRahul Lakkireddy /* Find out what ports are available to us. */ 7325eb55bf8SRahul Lakkireddy v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | 7335eb55bf8SRahul Lakkireddy V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); 7345eb55bf8SRahul Lakkireddy ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, &v, &port_vec); 7355eb55bf8SRahul Lakkireddy if (ret < 0) { 7365eb55bf8SRahul Lakkireddy dev_err(adap, "%s: failure in t4_query_params; error = %d\n", 7375eb55bf8SRahul Lakkireddy __func__, ret); 7385eb55bf8SRahul Lakkireddy goto bye; 7395eb55bf8SRahul Lakkireddy } 7405eb55bf8SRahul Lakkireddy 7415eb55bf8SRahul Lakkireddy adap->params.nports = hweight32(port_vec); 7425eb55bf8SRahul Lakkireddy adap->params.portvec = port_vec; 7435eb55bf8SRahul Lakkireddy 7445eb55bf8SRahul Lakkireddy dev_debug(adap, "%s: adap->params.nports = %u\n", __func__, 7455eb55bf8SRahul Lakkireddy adap->params.nports); 7465eb55bf8SRahul Lakkireddy 74783189849SRahul Lakkireddy /* 74883189849SRahul Lakkireddy * Give the SGE code a chance to pull in anything that it needs ... 74983189849SRahul Lakkireddy * Note that this must be called after we retrieve our VPD parameters 75083189849SRahul Lakkireddy * in order to know how to convert core ticks to seconds, etc. 75183189849SRahul Lakkireddy */ 75283189849SRahul Lakkireddy ret = t4_sge_init(adap); 75383189849SRahul Lakkireddy if (ret < 0) { 75483189849SRahul Lakkireddy dev_err(adap, "t4_sge_init failed with error %d\n", 75583189849SRahul Lakkireddy -ret); 75683189849SRahul Lakkireddy goto bye; 75783189849SRahul Lakkireddy } 75883189849SRahul Lakkireddy 75983189849SRahul Lakkireddy /* 76083189849SRahul Lakkireddy * Grab some of our basic fundamental operating parameters. 76183189849SRahul Lakkireddy */ 76283189849SRahul Lakkireddy #define FW_PARAM_DEV(param) \ 76383189849SRahul Lakkireddy (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ 76483189849SRahul Lakkireddy V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) 76583189849SRahul Lakkireddy 76683189849SRahul Lakkireddy #define FW_PARAM_PFVF(param) \ 76783189849SRahul Lakkireddy (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ 76883189849SRahul Lakkireddy V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \ 76983189849SRahul Lakkireddy V_FW_PARAMS_PARAM_Y(0) | \ 77083189849SRahul Lakkireddy V_FW_PARAMS_PARAM_Z(0)) 77183189849SRahul Lakkireddy 77283189849SRahul Lakkireddy /* If we're running on newer firmware, let it know that we're 77383189849SRahul Lakkireddy * prepared to deal with encapsulated CPL messages. Older 77483189849SRahul Lakkireddy * firmware won't understand this and we'll just get 77583189849SRahul Lakkireddy * unencapsulated messages ... 77683189849SRahul Lakkireddy */ 77783189849SRahul Lakkireddy params[0] = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); 77883189849SRahul Lakkireddy val[0] = 1; 77983189849SRahul Lakkireddy (void)t4_set_params(adap, adap->mbox, adap->pf, 0, 1, params, val); 78083189849SRahul Lakkireddy 78183189849SRahul Lakkireddy /* 78283189849SRahul Lakkireddy * Find out whether we're allowed to use the T5+ ULPTX MEMWRITE DSGL 78383189849SRahul Lakkireddy * capability. Earlier versions of the firmware didn't have the 78483189849SRahul Lakkireddy * ULPTX_MEMWRITE_DSGL so we'll interpret a query failure as no 78583189849SRahul Lakkireddy * permission to use ULPTX MEMWRITE DSGL. 78683189849SRahul Lakkireddy */ 78783189849SRahul Lakkireddy if (is_t4(adap->params.chip)) { 78883189849SRahul Lakkireddy adap->params.ulptx_memwrite_dsgl = false; 78983189849SRahul Lakkireddy } else { 79083189849SRahul Lakkireddy params[0] = FW_PARAM_DEV(ULPTX_MEMWRITE_DSGL); 79183189849SRahul Lakkireddy ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 79283189849SRahul Lakkireddy 1, params, val); 79383189849SRahul Lakkireddy adap->params.ulptx_memwrite_dsgl = (ret == 0 && val[0] != 0); 79483189849SRahul Lakkireddy } 79583189849SRahul Lakkireddy 79683189849SRahul Lakkireddy /* 79783189849SRahul Lakkireddy * The MTU/MSS Table is initialized by now, so load their values. If 79883189849SRahul Lakkireddy * we're initializing the adapter, then we'll make any modifications 79983189849SRahul Lakkireddy * we want to the MTU/MSS Table and also initialize the congestion 80083189849SRahul Lakkireddy * parameters. 80183189849SRahul Lakkireddy */ 80283189849SRahul Lakkireddy t4_read_mtu_tbl(adap, adap->params.mtus, NULL); 80383189849SRahul Lakkireddy if (state != DEV_STATE_INIT) { 80483189849SRahul Lakkireddy int i; 80583189849SRahul Lakkireddy 80683189849SRahul Lakkireddy /* 80783189849SRahul Lakkireddy * The default MTU Table contains values 1492 and 1500. 80883189849SRahul Lakkireddy * However, for TCP, it's better to have two values which are 80983189849SRahul Lakkireddy * a multiple of 8 +/- 4 bytes apart near this popular MTU. 81083189849SRahul Lakkireddy * This allows us to have a TCP Data Payload which is a 81183189849SRahul Lakkireddy * multiple of 8 regardless of what combination of TCP Options 81283189849SRahul Lakkireddy * are in use (always a multiple of 4 bytes) which is 81383189849SRahul Lakkireddy * important for performance reasons. For instance, if no 81483189849SRahul Lakkireddy * options are in use, then we have a 20-byte IP header and a 81583189849SRahul Lakkireddy * 20-byte TCP header. In this case, a 1500-byte MSS would 81683189849SRahul Lakkireddy * result in a TCP Data Payload of 1500 - 40 == 1460 bytes 81783189849SRahul Lakkireddy * which is not a multiple of 8. So using an MSS of 1488 in 81883189849SRahul Lakkireddy * this case results in a TCP Data Payload of 1448 bytes which 81983189849SRahul Lakkireddy * is a multiple of 8. On the other hand, if 12-byte TCP Time 82083189849SRahul Lakkireddy * Stamps have been negotiated, then an MTU of 1500 bytes 82183189849SRahul Lakkireddy * results in a TCP Data Payload of 1448 bytes which, as 82283189849SRahul Lakkireddy * above, is a multiple of 8 bytes ... 82383189849SRahul Lakkireddy */ 82483189849SRahul Lakkireddy for (i = 0; i < NMTUS; i++) 82583189849SRahul Lakkireddy if (adap->params.mtus[i] == 1492) { 82683189849SRahul Lakkireddy adap->params.mtus[i] = 1488; 82783189849SRahul Lakkireddy break; 82883189849SRahul Lakkireddy } 82983189849SRahul Lakkireddy 83083189849SRahul Lakkireddy t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, 83183189849SRahul Lakkireddy adap->params.b_wnd); 83283189849SRahul Lakkireddy } 83383189849SRahul Lakkireddy t4_init_sge_params(adap); 83483189849SRahul Lakkireddy t4_init_tp_params(adap); 835ee606d92SRahul Lakkireddy configure_pcie_ext_tag(adap); 83683189849SRahul Lakkireddy 83783189849SRahul Lakkireddy adap->params.drv_memwin = MEMWIN_NIC; 83883189849SRahul Lakkireddy adap->flags |= FW_OK; 83983189849SRahul Lakkireddy dev_debug(adap, "%s: returning zero..\n", __func__); 84083189849SRahul Lakkireddy return 0; 84183189849SRahul Lakkireddy 84283189849SRahul Lakkireddy /* 84383189849SRahul Lakkireddy * Something bad happened. If a command timed out or failed with EIO 84483189849SRahul Lakkireddy * FW does not operate within its spec or something catastrophic 84583189849SRahul Lakkireddy * happened to HW/FW, stop issuing commands. 84683189849SRahul Lakkireddy */ 84783189849SRahul Lakkireddy bye: 84883189849SRahul Lakkireddy if (ret != -ETIMEDOUT && ret != -EIO) 84983189849SRahul Lakkireddy t4_fw_bye(adap, adap->mbox); 85083189849SRahul Lakkireddy return ret; 85183189849SRahul Lakkireddy } 85283189849SRahul Lakkireddy 85383189849SRahul Lakkireddy /** 85483189849SRahul Lakkireddy * t4_os_portmod_changed - handle port module changes 85583189849SRahul Lakkireddy * @adap: the adapter associated with the module change 85683189849SRahul Lakkireddy * @port_id: the port index whose module status has changed 85783189849SRahul Lakkireddy * 85883189849SRahul Lakkireddy * This is the OS-dependent handler for port module changes. It is 85983189849SRahul Lakkireddy * invoked when a port module is removed or inserted for any OS-specific 86083189849SRahul Lakkireddy * processing. 86183189849SRahul Lakkireddy */ 86283189849SRahul Lakkireddy void t4_os_portmod_changed(const struct adapter *adap, int port_id) 86383189849SRahul Lakkireddy { 86483189849SRahul Lakkireddy static const char * const mod_str[] = { 86583189849SRahul Lakkireddy NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" 86683189849SRahul Lakkireddy }; 86783189849SRahul Lakkireddy 8682195df6dSRahul Lakkireddy const struct port_info *pi = adap2pinfo(adap, port_id); 86983189849SRahul Lakkireddy 87083189849SRahul Lakkireddy if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) 87183189849SRahul Lakkireddy dev_info(adap, "Port%d: port module unplugged\n", pi->port_id); 87283189849SRahul Lakkireddy else if (pi->mod_type < ARRAY_SIZE(mod_str)) 87383189849SRahul Lakkireddy dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id, 87483189849SRahul Lakkireddy mod_str[pi->mod_type]); 87583189849SRahul Lakkireddy else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) 8769da2a694SRahul Lakkireddy dev_info(adap, "Port%d: unsupported port module inserted\n", 87783189849SRahul Lakkireddy pi->port_id); 87883189849SRahul Lakkireddy else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) 8799da2a694SRahul Lakkireddy dev_info(adap, "Port%d: unknown port module inserted\n", 88083189849SRahul Lakkireddy pi->port_id); 88183189849SRahul Lakkireddy else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) 88283189849SRahul Lakkireddy dev_info(adap, "Port%d: transceiver module error\n", 88383189849SRahul Lakkireddy pi->port_id); 88483189849SRahul Lakkireddy else 88583189849SRahul Lakkireddy dev_info(adap, "Port%d: unknown module type %d inserted\n", 88683189849SRahul Lakkireddy pi->port_id, pi->mod_type); 88783189849SRahul Lakkireddy } 88883189849SRahul Lakkireddy 88992c8a632SRahul Lakkireddy /** 8900462d115SRahul Lakkireddy * link_start - enable a port 8910462d115SRahul Lakkireddy * @dev: the port to enable 8920462d115SRahul Lakkireddy * 8930462d115SRahul Lakkireddy * Performs the MAC and PHY actions needed to enable a port. 8940462d115SRahul Lakkireddy */ 8950462d115SRahul Lakkireddy int link_start(struct port_info *pi) 8960462d115SRahul Lakkireddy { 8970462d115SRahul Lakkireddy struct adapter *adapter = pi->adapter; 8980462d115SRahul Lakkireddy int ret; 8995a9e303aSRahul Lakkireddy unsigned int mtu; 9005a9e303aSRahul Lakkireddy 9015a9e303aSRahul Lakkireddy mtu = pi->eth_dev->data->dev_conf.rxmode.max_rx_pkt_len - 9025a9e303aSRahul Lakkireddy (ETHER_HDR_LEN + ETHER_CRC_LEN); 9030462d115SRahul Lakkireddy 9040462d115SRahul Lakkireddy /* 9050462d115SRahul Lakkireddy * We do not set address filters and promiscuity here, the stack does 9060462d115SRahul Lakkireddy * that step explicitly. 9070462d115SRahul Lakkireddy */ 9084b2eff45SRahul Lakkireddy ret = t4_set_rxmode(adapter, adapter->mbox, pi->viid, mtu, -1, -1, 9090462d115SRahul Lakkireddy -1, 1, true); 9100462d115SRahul Lakkireddy if (ret == 0) { 9110462d115SRahul Lakkireddy ret = t4_change_mac(adapter, adapter->mbox, pi->viid, 9120462d115SRahul Lakkireddy pi->xact_addr_filt, 9130462d115SRahul Lakkireddy (u8 *)&pi->eth_dev->data->mac_addrs[0], 9140462d115SRahul Lakkireddy true, true); 9150462d115SRahul Lakkireddy if (ret >= 0) { 9160462d115SRahul Lakkireddy pi->xact_addr_filt = ret; 9170462d115SRahul Lakkireddy ret = 0; 9180462d115SRahul Lakkireddy } 9190462d115SRahul Lakkireddy } 920*5e80364aSKumar Sanghvi if (ret == 0 && is_pf4(adapter)) 9210462d115SRahul Lakkireddy ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, 9220462d115SRahul Lakkireddy &pi->link_cfg); 9230462d115SRahul Lakkireddy if (ret == 0) { 9240462d115SRahul Lakkireddy /* 9250462d115SRahul Lakkireddy * Enabling a Virtual Interface can result in an interrupt 9260462d115SRahul Lakkireddy * during the processing of the VI Enable command and, in some 9270462d115SRahul Lakkireddy * paths, result in an attempt to issue another command in the 9280462d115SRahul Lakkireddy * interrupt context. Thus, we disable interrupts during the 9290462d115SRahul Lakkireddy * course of the VI Enable command ... 9300462d115SRahul Lakkireddy */ 9310462d115SRahul Lakkireddy ret = t4_enable_vi_params(adapter, adapter->mbox, pi->viid, 9320462d115SRahul Lakkireddy true, true, false); 9330462d115SRahul Lakkireddy } 9340462d115SRahul Lakkireddy return ret; 9350462d115SRahul Lakkireddy } 9360462d115SRahul Lakkireddy 9370462d115SRahul Lakkireddy /** 93808e21af9SKumar Sanghvi * cxgbe_write_rss_conf - flash the RSS configuration for a given port 93908e21af9SKumar Sanghvi * @pi: the port 94008e21af9SKumar Sanghvi * @rss_hf: Hash configuration to apply 94108e21af9SKumar Sanghvi */ 94208e21af9SKumar Sanghvi int cxgbe_write_rss_conf(const struct port_info *pi, uint64_t rss_hf) 94308e21af9SKumar Sanghvi { 94408e21af9SKumar Sanghvi struct adapter *adapter = pi->adapter; 94508e21af9SKumar Sanghvi const struct sge_eth_rxq *rxq; 94608e21af9SKumar Sanghvi u64 flags = 0; 94708e21af9SKumar Sanghvi u16 rss; 94808e21af9SKumar Sanghvi int err; 94908e21af9SKumar Sanghvi 95008e21af9SKumar Sanghvi /* Should never be called before setting up sge eth rx queues */ 95108e21af9SKumar Sanghvi if (!(adapter->flags & FULL_INIT_DONE)) { 95208e21af9SKumar Sanghvi dev_err(adap, "%s No RXQs available on port %d\n", 95308e21af9SKumar Sanghvi __func__, pi->port_id); 95408e21af9SKumar Sanghvi return -EINVAL; 95508e21af9SKumar Sanghvi } 95608e21af9SKumar Sanghvi 95708e21af9SKumar Sanghvi /* Don't allow unsupported hash functions */ 95808e21af9SKumar Sanghvi if (rss_hf & ~CXGBE_RSS_HF_ALL) 95908e21af9SKumar Sanghvi return -EINVAL; 96008e21af9SKumar Sanghvi 96108e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_IPV4) 96208e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN; 96308e21af9SKumar Sanghvi 96408e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) 96508e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; 96608e21af9SKumar Sanghvi 96708e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) 96808e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | 96908e21af9SKumar Sanghvi F_FW_RSS_VI_CONFIG_CMD_UDPEN; 97008e21af9SKumar Sanghvi 97108e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_IPV6) 97208e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN; 97308e21af9SKumar Sanghvi 97408e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) 97508e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; 97608e21af9SKumar Sanghvi 97708e21af9SKumar Sanghvi if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) 97808e21af9SKumar Sanghvi flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | 97908e21af9SKumar Sanghvi F_FW_RSS_VI_CONFIG_CMD_UDPEN; 98008e21af9SKumar Sanghvi 98108e21af9SKumar Sanghvi rxq = &adapter->sge.ethrxq[pi->first_qset]; 98208e21af9SKumar Sanghvi rss = rxq[0].rspq.abs_id; 98308e21af9SKumar Sanghvi 98408e21af9SKumar Sanghvi /* If Tunnel All Lookup isn't specified in the global RSS 98508e21af9SKumar Sanghvi * Configuration, then we need to specify a default Ingress 98608e21af9SKumar Sanghvi * Queue for any ingress packets which aren't hashed. We'll 98708e21af9SKumar Sanghvi * use our first ingress queue ... 98808e21af9SKumar Sanghvi */ 98908e21af9SKumar Sanghvi err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid, 99008e21af9SKumar Sanghvi flags, rss); 99108e21af9SKumar Sanghvi return err; 99208e21af9SKumar Sanghvi } 99308e21af9SKumar Sanghvi 99408e21af9SKumar Sanghvi /** 99508e21af9SKumar Sanghvi * cxgbe_write_rss - write the RSS table for a given port 99692c8a632SRahul Lakkireddy * @pi: the port 99792c8a632SRahul Lakkireddy * @queues: array of queue indices for RSS 99892c8a632SRahul Lakkireddy * 99992c8a632SRahul Lakkireddy * Sets up the portion of the HW RSS table for the port's VI to distribute 100092c8a632SRahul Lakkireddy * packets to the Rx queues in @queues. 100192c8a632SRahul Lakkireddy */ 100208e21af9SKumar Sanghvi int cxgbe_write_rss(const struct port_info *pi, const u16 *queues) 100392c8a632SRahul Lakkireddy { 100492c8a632SRahul Lakkireddy u16 *rss; 100592c8a632SRahul Lakkireddy int i, err; 100692c8a632SRahul Lakkireddy struct adapter *adapter = pi->adapter; 100792c8a632SRahul Lakkireddy const struct sge_eth_rxq *rxq; 100892c8a632SRahul Lakkireddy 100992c8a632SRahul Lakkireddy /* Should never be called before setting up sge eth rx queues */ 101092c8a632SRahul Lakkireddy BUG_ON(!(adapter->flags & FULL_INIT_DONE)); 101192c8a632SRahul Lakkireddy 101292c8a632SRahul Lakkireddy rxq = &adapter->sge.ethrxq[pi->first_qset]; 101392c8a632SRahul Lakkireddy rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0); 101492c8a632SRahul Lakkireddy if (!rss) 101592c8a632SRahul Lakkireddy return -ENOMEM; 101692c8a632SRahul Lakkireddy 101792c8a632SRahul Lakkireddy /* map the queue indices to queue ids */ 101892c8a632SRahul Lakkireddy for (i = 0; i < pi->rss_size; i++, queues++) 101992c8a632SRahul Lakkireddy rss[i] = rxq[*queues].rspq.abs_id; 102092c8a632SRahul Lakkireddy 102192c8a632SRahul Lakkireddy err = t4_config_rss_range(adapter, adapter->pf, pi->viid, 0, 102292c8a632SRahul Lakkireddy pi->rss_size, rss, pi->rss_size); 102392c8a632SRahul Lakkireddy rte_free(rss); 102492c8a632SRahul Lakkireddy return err; 102592c8a632SRahul Lakkireddy } 102692c8a632SRahul Lakkireddy 102792c8a632SRahul Lakkireddy /** 102892c8a632SRahul Lakkireddy * setup_rss - configure RSS 102992c8a632SRahul Lakkireddy * @adapter: the adapter 103092c8a632SRahul Lakkireddy * 103192c8a632SRahul Lakkireddy * Sets up RSS to distribute packets to multiple receive queues. We 103292c8a632SRahul Lakkireddy * configure the RSS CPU lookup table to distribute to the number of HW 103392c8a632SRahul Lakkireddy * receive queues, and the response queue lookup table to narrow that 103492c8a632SRahul Lakkireddy * down to the response queues actually configured for each port. 103592c8a632SRahul Lakkireddy * We always configure the RSS mapping for all ports since the mapping 103692c8a632SRahul Lakkireddy * table has plenty of entries. 103792c8a632SRahul Lakkireddy */ 103892c8a632SRahul Lakkireddy int setup_rss(struct port_info *pi) 103992c8a632SRahul Lakkireddy { 104092c8a632SRahul Lakkireddy int j, err; 104192c8a632SRahul Lakkireddy struct adapter *adapter = pi->adapter; 104292c8a632SRahul Lakkireddy 104392c8a632SRahul Lakkireddy dev_debug(adapter, "%s: pi->rss_size = %u; pi->n_rx_qsets = %u\n", 104492c8a632SRahul Lakkireddy __func__, pi->rss_size, pi->n_rx_qsets); 104592c8a632SRahul Lakkireddy 10461039ee1cSEmmanuel Roullit if (!(pi->flags & PORT_RSS_DONE)) { 104792c8a632SRahul Lakkireddy if (adapter->flags & FULL_INIT_DONE) { 104892c8a632SRahul Lakkireddy /* Fill default values with equal distribution */ 104992c8a632SRahul Lakkireddy for (j = 0; j < pi->rss_size; j++) 105092c8a632SRahul Lakkireddy pi->rss[j] = j % pi->n_rx_qsets; 105192c8a632SRahul Lakkireddy 105208e21af9SKumar Sanghvi err = cxgbe_write_rss(pi, pi->rss); 105308e21af9SKumar Sanghvi if (err) 105408e21af9SKumar Sanghvi return err; 105508e21af9SKumar Sanghvi 105608e21af9SKumar Sanghvi err = cxgbe_write_rss_conf(pi, pi->rss_hf); 105792c8a632SRahul Lakkireddy if (err) 105892c8a632SRahul Lakkireddy return err; 105992c8a632SRahul Lakkireddy pi->flags |= PORT_RSS_DONE; 106092c8a632SRahul Lakkireddy } 106192c8a632SRahul Lakkireddy } 106292c8a632SRahul Lakkireddy return 0; 106392c8a632SRahul Lakkireddy } 106492c8a632SRahul Lakkireddy 10650462d115SRahul Lakkireddy /* 10660462d115SRahul Lakkireddy * Enable NAPI scheduling and interrupt generation for all Rx queues. 10670462d115SRahul Lakkireddy */ 1068d87ba24dSRahul Lakkireddy static void enable_rx(struct adapter *adap, struct sge_rspq *q) 10690462d115SRahul Lakkireddy { 10700462d115SRahul Lakkireddy /* 0-increment GTS to start the timer and enable interrupts */ 10710462d115SRahul Lakkireddy t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS), 10720462d115SRahul Lakkireddy V_SEINTARM(q->intr_params) | 10730462d115SRahul Lakkireddy V_INGRESSQID(q->cntxt_id)); 10740462d115SRahul Lakkireddy } 1075d87ba24dSRahul Lakkireddy 1076d87ba24dSRahul Lakkireddy void cxgbe_enable_rx_queues(struct port_info *pi) 1077d87ba24dSRahul Lakkireddy { 1078d87ba24dSRahul Lakkireddy struct adapter *adap = pi->adapter; 1079d87ba24dSRahul Lakkireddy struct sge *s = &adap->sge; 1080d87ba24dSRahul Lakkireddy unsigned int i; 1081d87ba24dSRahul Lakkireddy 1082d87ba24dSRahul Lakkireddy for (i = 0; i < pi->n_rx_qsets; i++) 1083d87ba24dSRahul Lakkireddy enable_rx(adap, &s->ethrxq[pi->first_qset + i].rspq); 10840462d115SRahul Lakkireddy } 10850462d115SRahul Lakkireddy 10860462d115SRahul Lakkireddy /** 1087e307e65bSRahul Lakkireddy * fw_caps_to_speed_caps - translate Firmware Port Caps to Speed Caps. 1088e307e65bSRahul Lakkireddy * @port_type: Firmware Port Type 1089e307e65bSRahul Lakkireddy * @fw_caps: Firmware Port Capabilities 1090e307e65bSRahul Lakkireddy * @speed_caps: Device Info Speed Capabilities 1091e307e65bSRahul Lakkireddy * 1092e307e65bSRahul Lakkireddy * Translate a Firmware Port Capabilities specification to Device Info 1093e307e65bSRahul Lakkireddy * Speed Capabilities. 1094e307e65bSRahul Lakkireddy */ 1095e307e65bSRahul Lakkireddy static void fw_caps_to_speed_caps(enum fw_port_type port_type, 1096e307e65bSRahul Lakkireddy unsigned int fw_caps, 1097e307e65bSRahul Lakkireddy u32 *speed_caps) 1098e307e65bSRahul Lakkireddy { 1099e307e65bSRahul Lakkireddy #define SET_SPEED(__speed_name) \ 1100e307e65bSRahul Lakkireddy do { \ 1101e307e65bSRahul Lakkireddy *speed_caps |= ETH_LINK_ ## __speed_name; \ 1102e307e65bSRahul Lakkireddy } while (0) 1103e307e65bSRahul Lakkireddy 1104e307e65bSRahul Lakkireddy #define FW_CAPS_TO_SPEED(__fw_name) \ 1105e307e65bSRahul Lakkireddy do { \ 110676488837SRahul Lakkireddy if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \ 1107e307e65bSRahul Lakkireddy SET_SPEED(__fw_name); \ 1108e307e65bSRahul Lakkireddy } while (0) 1109e307e65bSRahul Lakkireddy 1110e307e65bSRahul Lakkireddy switch (port_type) { 1111e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BT_SGMII: 1112e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BT_XFI: 1113e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BT_XAUI: 1114e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_100M); 1115e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_1G); 1116e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_10G); 1117e307e65bSRahul Lakkireddy break; 1118e307e65bSRahul Lakkireddy 1119e307e65bSRahul Lakkireddy case FW_PORT_TYPE_KX4: 1120e307e65bSRahul Lakkireddy case FW_PORT_TYPE_KX: 1121e307e65bSRahul Lakkireddy case FW_PORT_TYPE_FIBER_XFI: 1122e307e65bSRahul Lakkireddy case FW_PORT_TYPE_FIBER_XAUI: 1123e307e65bSRahul Lakkireddy case FW_PORT_TYPE_SFP: 1124e307e65bSRahul Lakkireddy case FW_PORT_TYPE_QSFP_10G: 1125e307e65bSRahul Lakkireddy case FW_PORT_TYPE_QSA: 1126e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_1G); 1127e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_10G); 1128e307e65bSRahul Lakkireddy break; 1129e307e65bSRahul Lakkireddy 1130e307e65bSRahul Lakkireddy case FW_PORT_TYPE_KR: 1131e307e65bSRahul Lakkireddy SET_SPEED(SPEED_10G); 1132e307e65bSRahul Lakkireddy break; 1133e307e65bSRahul Lakkireddy 1134e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BP_AP: 1135e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BP4_AP: 1136e307e65bSRahul Lakkireddy SET_SPEED(SPEED_1G); 1137e307e65bSRahul Lakkireddy SET_SPEED(SPEED_10G); 1138e307e65bSRahul Lakkireddy break; 1139e307e65bSRahul Lakkireddy 1140e307e65bSRahul Lakkireddy case FW_PORT_TYPE_BP40_BA: 1141e307e65bSRahul Lakkireddy case FW_PORT_TYPE_QSFP: 1142e307e65bSRahul Lakkireddy SET_SPEED(SPEED_40G); 1143e307e65bSRahul Lakkireddy break; 1144e307e65bSRahul Lakkireddy 1145e307e65bSRahul Lakkireddy case FW_PORT_TYPE_CR_QSFP: 1146e307e65bSRahul Lakkireddy case FW_PORT_TYPE_SFP28: 1147e307e65bSRahul Lakkireddy case FW_PORT_TYPE_KR_SFP28: 1148e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_1G); 1149e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_10G); 1150e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_25G); 1151e307e65bSRahul Lakkireddy break; 1152e307e65bSRahul Lakkireddy 1153e307e65bSRahul Lakkireddy case FW_PORT_TYPE_CR2_QSFP: 1154e307e65bSRahul Lakkireddy SET_SPEED(SPEED_50G); 1155e307e65bSRahul Lakkireddy break; 1156e307e65bSRahul Lakkireddy 1157e307e65bSRahul Lakkireddy case FW_PORT_TYPE_KR4_100G: 1158e307e65bSRahul Lakkireddy case FW_PORT_TYPE_CR4_QSFP: 1159e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_25G); 1160e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_40G); 116176488837SRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_50G); 1162e307e65bSRahul Lakkireddy FW_CAPS_TO_SPEED(SPEED_100G); 1163e307e65bSRahul Lakkireddy break; 1164e307e65bSRahul Lakkireddy 1165e307e65bSRahul Lakkireddy default: 1166e307e65bSRahul Lakkireddy break; 1167e307e65bSRahul Lakkireddy } 1168e307e65bSRahul Lakkireddy 1169e307e65bSRahul Lakkireddy #undef FW_CAPS_TO_SPEED 1170e307e65bSRahul Lakkireddy #undef SET_SPEED 1171e307e65bSRahul Lakkireddy } 1172e307e65bSRahul Lakkireddy 1173e307e65bSRahul Lakkireddy /** 1174e307e65bSRahul Lakkireddy * cxgbe_get_speed_caps - Fetch supported speed capabilities 1175e307e65bSRahul Lakkireddy * @pi: Underlying port's info 1176e307e65bSRahul Lakkireddy * @speed_caps: Device Info speed capabilities 1177e307e65bSRahul Lakkireddy * 1178e307e65bSRahul Lakkireddy * Fetch supported speed capabilities of the underlying port. 1179e307e65bSRahul Lakkireddy */ 1180e307e65bSRahul Lakkireddy void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps) 1181e307e65bSRahul Lakkireddy { 1182e307e65bSRahul Lakkireddy *speed_caps = 0; 1183e307e65bSRahul Lakkireddy 118476488837SRahul Lakkireddy fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps, 1185e307e65bSRahul Lakkireddy speed_caps); 1186e307e65bSRahul Lakkireddy 118776488837SRahul Lakkireddy if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)) 1188e307e65bSRahul Lakkireddy *speed_caps |= ETH_LINK_SPEED_FIXED; 1189e307e65bSRahul Lakkireddy } 1190e307e65bSRahul Lakkireddy 1191e307e65bSRahul Lakkireddy /** 11920462d115SRahul Lakkireddy * cxgb_up - enable the adapter 11930462d115SRahul Lakkireddy * @adap: adapter being enabled 11940462d115SRahul Lakkireddy * 11950462d115SRahul Lakkireddy * Called when the first port is enabled, this function performs the 11960462d115SRahul Lakkireddy * actions necessary to make an adapter operational, such as completing 11970462d115SRahul Lakkireddy * the initialization of HW modules, and enabling interrupts. 11980462d115SRahul Lakkireddy */ 11990462d115SRahul Lakkireddy int cxgbe_up(struct adapter *adap) 12000462d115SRahul Lakkireddy { 1201d87ba24dSRahul Lakkireddy enable_rx(adap, &adap->sge.fw_evtq); 12020462d115SRahul Lakkireddy t4_sge_tx_monitor_start(adap); 1203*5e80364aSKumar Sanghvi if (is_pf4(adap)) 12040462d115SRahul Lakkireddy t4_intr_enable(adap); 12050462d115SRahul Lakkireddy adap->flags |= FULL_INIT_DONE; 12060462d115SRahul Lakkireddy 12070462d115SRahul Lakkireddy /* TODO: deadman watchdog ?? */ 12080462d115SRahul Lakkireddy return 0; 12090462d115SRahul Lakkireddy } 12100462d115SRahul Lakkireddy 12110462d115SRahul Lakkireddy /* 12120462d115SRahul Lakkireddy * Close the port 12130462d115SRahul Lakkireddy */ 12140462d115SRahul Lakkireddy int cxgbe_down(struct port_info *pi) 12150462d115SRahul Lakkireddy { 12160462d115SRahul Lakkireddy struct adapter *adapter = pi->adapter; 12170462d115SRahul Lakkireddy int err = 0; 12180462d115SRahul Lakkireddy 12190462d115SRahul Lakkireddy err = t4_enable_vi(adapter, adapter->mbox, pi->viid, false, false); 12200462d115SRahul Lakkireddy if (err) { 12210462d115SRahul Lakkireddy dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err); 12220462d115SRahul Lakkireddy return err; 12230462d115SRahul Lakkireddy } 12240462d115SRahul Lakkireddy 1225*5e80364aSKumar Sanghvi t4_reset_link_config(adapter, pi->pidx); 12260462d115SRahul Lakkireddy return 0; 12270462d115SRahul Lakkireddy } 12280462d115SRahul Lakkireddy 12290462d115SRahul Lakkireddy /* 12300462d115SRahul Lakkireddy * Release resources when all the ports have been stopped. 12310462d115SRahul Lakkireddy */ 12320462d115SRahul Lakkireddy void cxgbe_close(struct adapter *adapter) 12330462d115SRahul Lakkireddy { 12340462d115SRahul Lakkireddy struct port_info *pi; 12350462d115SRahul Lakkireddy int i; 12360462d115SRahul Lakkireddy 12370462d115SRahul Lakkireddy if (adapter->flags & FULL_INIT_DONE) { 1238*5e80364aSKumar Sanghvi if (is_pf4(adapter)) 12390462d115SRahul Lakkireddy t4_intr_disable(adapter); 12400462d115SRahul Lakkireddy t4_sge_tx_monitor_stop(adapter); 12410462d115SRahul Lakkireddy t4_free_sge_resources(adapter); 12420462d115SRahul Lakkireddy for_each_port(adapter, i) { 12430462d115SRahul Lakkireddy pi = adap2pinfo(adapter, i); 12440462d115SRahul Lakkireddy if (pi->viid != 0) 12450462d115SRahul Lakkireddy t4_free_vi(adapter, adapter->mbox, 12460462d115SRahul Lakkireddy adapter->pf, 0, pi->viid); 12470462d115SRahul Lakkireddy rte_free(pi->eth_dev->data->mac_addrs); 12482195df6dSRahul Lakkireddy /* Skip first port since it'll be freed by DPDK stack */ 12492195df6dSRahul Lakkireddy if (i) { 12502195df6dSRahul Lakkireddy rte_free(pi->eth_dev->data->dev_private); 12512195df6dSRahul Lakkireddy rte_eth_dev_release_port(pi->eth_dev); 12522195df6dSRahul Lakkireddy } 12530462d115SRahul Lakkireddy } 12540462d115SRahul Lakkireddy adapter->flags &= ~FULL_INIT_DONE; 12550462d115SRahul Lakkireddy } 12560462d115SRahul Lakkireddy 1257*5e80364aSKumar Sanghvi if (is_pf4(adapter) && (adapter->flags & FW_OK)) 12580462d115SRahul Lakkireddy t4_fw_bye(adapter, adapter->mbox); 12590462d115SRahul Lakkireddy } 12600462d115SRahul Lakkireddy 126183189849SRahul Lakkireddy int cxgbe_probe(struct adapter *adapter) 126283189849SRahul Lakkireddy { 126383189849SRahul Lakkireddy struct port_info *pi; 126404868e5bSRahul Lakkireddy int chip; 126583189849SRahul Lakkireddy int func, i; 126683189849SRahul Lakkireddy int err = 0; 126704868e5bSRahul Lakkireddy u32 whoami; 126883189849SRahul Lakkireddy 126904868e5bSRahul Lakkireddy whoami = t4_read_reg(adapter, A_PL_WHOAMI); 127004868e5bSRahul Lakkireddy chip = t4_get_chip_type(adapter, 127104868e5bSRahul Lakkireddy CHELSIO_PCI_ID_VER(adapter->pdev->id.device_id)); 127204868e5bSRahul Lakkireddy if (chip < 0) 127304868e5bSRahul Lakkireddy return chip; 127404868e5bSRahul Lakkireddy 127504868e5bSRahul Lakkireddy func = CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5 ? 127604868e5bSRahul Lakkireddy G_SOURCEPF(whoami) : G_T6_SOURCEPF(whoami); 127704868e5bSRahul Lakkireddy 127883189849SRahul Lakkireddy adapter->mbox = func; 127983189849SRahul Lakkireddy adapter->pf = func; 128083189849SRahul Lakkireddy 128183189849SRahul Lakkireddy t4_os_lock_init(&adapter->mbox_lock); 128283189849SRahul Lakkireddy TAILQ_INIT(&adapter->mbox_list); 128383189849SRahul Lakkireddy 128483189849SRahul Lakkireddy err = t4_prep_adapter(adapter); 128583189849SRahul Lakkireddy if (err) 128683189849SRahul Lakkireddy return err; 128783189849SRahul Lakkireddy 128883189849SRahul Lakkireddy setup_memwin(adapter); 128983189849SRahul Lakkireddy err = adap_init0(adapter); 129083189849SRahul Lakkireddy if (err) { 129183189849SRahul Lakkireddy dev_err(adapter, "%s: Adapter initialization failed, error %d\n", 129283189849SRahul Lakkireddy __func__, err); 129383189849SRahul Lakkireddy goto out_free; 129483189849SRahul Lakkireddy } 129583189849SRahul Lakkireddy 129683189849SRahul Lakkireddy if (!is_t4(adapter->params.chip)) { 129783189849SRahul Lakkireddy /* 129883189849SRahul Lakkireddy * The userspace doorbell BAR is split evenly into doorbell 129983189849SRahul Lakkireddy * regions, each associated with an egress queue. If this 130083189849SRahul Lakkireddy * per-queue region is large enough (at least UDBS_SEG_SIZE) 130183189849SRahul Lakkireddy * then it can be used to submit a tx work request with an 130283189849SRahul Lakkireddy * implied doorbell. Enable write combining on the BAR if 130383189849SRahul Lakkireddy * there is room for such work requests. 130483189849SRahul Lakkireddy */ 130583189849SRahul Lakkireddy int s_qpp, qpp, num_seg; 130683189849SRahul Lakkireddy 130783189849SRahul Lakkireddy s_qpp = (S_QUEUESPERPAGEPF0 + 130883189849SRahul Lakkireddy (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * 130983189849SRahul Lakkireddy adapter->pf); 131083189849SRahul Lakkireddy qpp = 1 << ((t4_read_reg(adapter, 131183189849SRahul Lakkireddy A_SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp) 131283189849SRahul Lakkireddy & M_QUEUESPERPAGEPF0); 13131f8613f1SRahul Lakkireddy num_seg = CXGBE_PAGE_SIZE / UDBS_SEG_SIZE; 131483189849SRahul Lakkireddy if (qpp > num_seg) 131583189849SRahul Lakkireddy dev_warn(adapter, "Incorrect SGE EGRESS QUEUES_PER_PAGE configuration, continuing in debug mode\n"); 131683189849SRahul Lakkireddy 131783189849SRahul Lakkireddy adapter->bar2 = (void *)adapter->pdev->mem_resource[2].addr; 131883189849SRahul Lakkireddy if (!adapter->bar2) { 131983189849SRahul Lakkireddy dev_err(adapter, "cannot map device bar2 region\n"); 132083189849SRahul Lakkireddy err = -ENOMEM; 132183189849SRahul Lakkireddy goto out_free; 132283189849SRahul Lakkireddy } 132383189849SRahul Lakkireddy t4_write_reg(adapter, A_SGE_STAT_CFG, V_STATSOURCE_T5(7) | 132483189849SRahul Lakkireddy V_STATMODE(0)); 132583189849SRahul Lakkireddy } 132683189849SRahul Lakkireddy 132783189849SRahul Lakkireddy for_each_port(adapter, i) { 132883189849SRahul Lakkireddy const unsigned int numa_node = rte_socket_id(); 13292195df6dSRahul Lakkireddy char name[RTE_ETH_NAME_MAX_LEN]; 13302195df6dSRahul Lakkireddy struct rte_eth_dev *eth_dev; 133183189849SRahul Lakkireddy 13322195df6dSRahul Lakkireddy snprintf(name, sizeof(name), "%s_%d", 13332195df6dSRahul Lakkireddy adapter->pdev->device.name, i); 133483189849SRahul Lakkireddy 133583189849SRahul Lakkireddy if (i == 0) { 133683189849SRahul Lakkireddy /* First port is already allocated by DPDK */ 13372195df6dSRahul Lakkireddy eth_dev = adapter->eth_dev; 133883189849SRahul Lakkireddy goto allocate_mac; 133983189849SRahul Lakkireddy } 134083189849SRahul Lakkireddy 134183189849SRahul Lakkireddy /* 134283189849SRahul Lakkireddy * now do all data allocation - for eth_dev structure, 134383189849SRahul Lakkireddy * and internal (private) data for the remaining ports 134483189849SRahul Lakkireddy */ 134583189849SRahul Lakkireddy 134683189849SRahul Lakkireddy /* reserve an ethdev entry */ 13472195df6dSRahul Lakkireddy eth_dev = rte_eth_dev_allocate(name); 13482195df6dSRahul Lakkireddy if (!eth_dev) 134983189849SRahul Lakkireddy goto out_free; 135083189849SRahul Lakkireddy 13512195df6dSRahul Lakkireddy eth_dev->data->dev_private = 13522195df6dSRahul Lakkireddy rte_zmalloc_socket(name, sizeof(struct port_info), 13532195df6dSRahul Lakkireddy RTE_CACHE_LINE_SIZE, numa_node); 13542195df6dSRahul Lakkireddy if (!eth_dev->data->dev_private) 135583189849SRahul Lakkireddy goto out_free; 135683189849SRahul Lakkireddy 135783189849SRahul Lakkireddy allocate_mac: 13582195df6dSRahul Lakkireddy pi = (struct port_info *)eth_dev->data->dev_private; 13592195df6dSRahul Lakkireddy adapter->port[i] = pi; 13602195df6dSRahul Lakkireddy pi->eth_dev = eth_dev; 13612195df6dSRahul Lakkireddy pi->adapter = adapter; 13622195df6dSRahul Lakkireddy pi->xact_addr_filt = -1; 13632195df6dSRahul Lakkireddy pi->port_id = i; 1364*5e80364aSKumar Sanghvi pi->pidx = i; 13652195df6dSRahul Lakkireddy 1366eac901ceSJan Blunck pi->eth_dev->device = &adapter->pdev->device; 136783189849SRahul Lakkireddy pi->eth_dev->dev_ops = adapter->eth_dev->dev_ops; 13684a01078bSRahul Lakkireddy pi->eth_dev->tx_pkt_burst = adapter->eth_dev->tx_pkt_burst; 136992c8a632SRahul Lakkireddy pi->eth_dev->rx_pkt_burst = adapter->eth_dev->rx_pkt_burst; 137013b0f500SRahul Lakkireddy 1371eac901ceSJan Blunck rte_eth_copy_pci_info(pi->eth_dev, adapter->pdev); 137213b0f500SRahul Lakkireddy 137383189849SRahul Lakkireddy pi->eth_dev->data->mac_addrs = rte_zmalloc(name, 137483189849SRahul Lakkireddy ETHER_ADDR_LEN, 0); 137583189849SRahul Lakkireddy if (!pi->eth_dev->data->mac_addrs) { 137683189849SRahul Lakkireddy dev_err(adapter, "%s: Mem allocation failed for storing mac addr, aborting\n", 137783189849SRahul Lakkireddy __func__); 137883189849SRahul Lakkireddy err = -1; 137983189849SRahul Lakkireddy goto out_free; 138083189849SRahul Lakkireddy } 138183189849SRahul Lakkireddy } 138283189849SRahul Lakkireddy 138383189849SRahul Lakkireddy if (adapter->flags & FW_OK) { 138483189849SRahul Lakkireddy err = t4_port_init(adapter, adapter->mbox, adapter->pf, 0); 138583189849SRahul Lakkireddy if (err) { 138683189849SRahul Lakkireddy dev_err(adapter, "%s: t4_port_init failed with err %d\n", 138783189849SRahul Lakkireddy __func__, err); 138883189849SRahul Lakkireddy goto out_free; 138983189849SRahul Lakkireddy } 139083189849SRahul Lakkireddy } 139183189849SRahul Lakkireddy 139292c8a632SRahul Lakkireddy cfg_queues(adapter->eth_dev); 139392c8a632SRahul Lakkireddy 1394c962618cSRahul Lakkireddy print_adapter_info(adapter); 139583189849SRahul Lakkireddy print_port_info(adapter); 139683189849SRahul Lakkireddy 139792c8a632SRahul Lakkireddy err = init_rss(adapter); 139892c8a632SRahul Lakkireddy if (err) 139992c8a632SRahul Lakkireddy goto out_free; 140092c8a632SRahul Lakkireddy 140183189849SRahul Lakkireddy return 0; 140283189849SRahul Lakkireddy 140383189849SRahul Lakkireddy out_free: 140483189849SRahul Lakkireddy for_each_port(adapter, i) { 140583189849SRahul Lakkireddy pi = adap2pinfo(adapter, i); 140683189849SRahul Lakkireddy if (pi->viid != 0) 140783189849SRahul Lakkireddy t4_free_vi(adapter, adapter->mbox, adapter->pf, 140883189849SRahul Lakkireddy 0, pi->viid); 140983189849SRahul Lakkireddy /* Skip first port since it'll be de-allocated by DPDK */ 141083189849SRahul Lakkireddy if (i == 0) 141183189849SRahul Lakkireddy continue; 14122195df6dSRahul Lakkireddy if (pi->eth_dev) { 14132195df6dSRahul Lakkireddy if (pi->eth_dev->data->dev_private) 14142195df6dSRahul Lakkireddy rte_free(pi->eth_dev->data->dev_private); 14152195df6dSRahul Lakkireddy rte_eth_dev_release_port(pi->eth_dev); 14162195df6dSRahul Lakkireddy } 141783189849SRahul Lakkireddy } 141883189849SRahul Lakkireddy 141983189849SRahul Lakkireddy if (adapter->flags & FW_OK) 142083189849SRahul Lakkireddy t4_fw_bye(adapter, adapter->mbox); 142183189849SRahul Lakkireddy return -err; 142283189849SRahul Lakkireddy } 1423