X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fcxgbe%2Fcxgbe_ethdev.c;h=920e071695365fceb48d7f40bb4eeefe1b866222;hb=946c9ed956168155a8177bab012f582fdc91e415;hp=cb100fca18758337b9b87d2b5c337d0715a5a3cf;hpb=0462d115441d1619ba19313b8daaff679854cc49;p=dpdk.git diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index cb100fca18..920e071695 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -141,8 +141,14 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev, struct adapter *adapter = pi->adapter; int max_queues = adapter->sge.max_ethqsets / adapter->params.nports; - device_info->min_rx_bufsize = 68; /* XXX: Smallest pkt size */ - device_info->max_rx_pktlen = 1500; /* XXX: For now we support mtu */ + static const struct rte_eth_desc_lim cxgbe_desc_lim = { + .nb_max = CXGBE_MAX_RING_DESC_SIZE, + .nb_min = CXGBE_MIN_RING_DESC_SIZE, + .nb_align = 1, + }; + + device_info->min_rx_bufsize = CXGBE_MIN_RX_BUFSIZE; + device_info->max_rx_pktlen = CXGBE_MAX_RX_PKTLEN; device_info->max_rx_queues = max_queues; device_info->max_tx_queues = max_queues; device_info->max_mac_addrs = 1; @@ -162,6 +168,98 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev, DEV_TX_OFFLOAD_TCP_TSO; device_info->reta_size = pi->rss_size; + + device_info->rx_desc_lim = cxgbe_desc_lim; + device_info->tx_desc_lim = cxgbe_desc_lim; +} + +static void cxgbe_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + + t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, + 1, -1, 1, -1, false); +} + +static void cxgbe_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + + t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, + 0, -1, 1, -1, false); +} + +static void cxgbe_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + + /* TODO: address filters ?? */ + + t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, + -1, 1, 1, -1, false); +} + +static void cxgbe_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + + /* TODO: address filters ?? */ + + t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, + -1, 0, 1, -1, false); +} + +static int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, + __rte_unused int wait_to_complete) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + struct sge *s = &adapter->sge; + struct rte_eth_link *old_link = ð_dev->data->dev_link; + unsigned int work_done, budget = 4; + + cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); + if (old_link->link_status == pi->link_cfg.link_ok) + return -1; /* link not changed */ + + eth_dev->data->dev_link.link_status = pi->link_cfg.link_ok; + eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; + eth_dev->data->dev_link.link_speed = pi->link_cfg.speed; + + /* link has changed */ + return 0; +} + +static int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + struct rte_eth_dev_info dev_info; + int err; + uint16_t new_mtu = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; + + cxgbe_dev_info_get(eth_dev, &dev_info); + + /* Must accommodate at least ETHER_MIN_MTU */ + if ((new_mtu < ETHER_MIN_MTU) || (new_mtu > dev_info.max_rx_pktlen)) + return -EINVAL; + + /* set to jumbo mode if needed */ + if (new_mtu > ETHER_MAX_LEN) + eth_dev->data->dev_conf.rxmode.jumbo_frame = 1; + else + eth_dev->data->dev_conf.rxmode.jumbo_frame = 0; + + err = t4_set_rxmode(adapter, adapter->mbox, pi->viid, new_mtu, -1, -1, + -1, -1, true); + if (!err) + eth_dev->data->dev_conf.rxmode.max_rx_pkt_len = new_mtu; + + return err; } static int cxgbe_dev_tx_queue_start(struct rte_eth_dev *eth_dev, @@ -437,6 +535,8 @@ static int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, int err = 0; int msi_idx = 0; unsigned int temp_nb_desc; + struct rte_eth_dev_info dev_info; + unsigned int pkt_len = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; RTE_SET_USED(rx_conf); @@ -444,6 +544,17 @@ static int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, __func__, eth_dev->data->nb_rx_queues, queue_idx, nb_desc, socket_id, mp); + cxgbe_dev_info_get(eth_dev, &dev_info); + + /* Must accommodate at least ETHER_MIN_MTU */ + if ((pkt_len < dev_info.min_rx_bufsize) || + (pkt_len > dev_info.max_rx_pktlen)) { + dev_err(adap, "%s: max pkt len must be > %d and <= %d\n", + __func__, dev_info.min_rx_bufsize, + dev_info.max_rx_pktlen); + return -EINVAL; + } + /* Free up the existing queue */ if (eth_dev->data->rx_queues[queue_idx]) { cxgbe_dev_rx_queue_release(eth_dev->data->rx_queues[queue_idx]); @@ -473,6 +584,12 @@ static int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, if ((&rxq->fl) != NULL) rxq->fl.size = temp_nb_desc; + /* Set to jumbo mode if necessary */ + if (pkt_len > ETHER_MAX_LEN) + eth_dev->data->dev_conf.rxmode.jumbo_frame = 1; + else + eth_dev->data->dev_conf.rxmode.jumbo_frame = 0; + err = t4_sge_alloc_rxq(adapter, &rxq->rspq, false, eth_dev, msi_idx, &rxq->fl, t4_ethrx_handler, t4_get_mps_bg_map(adapter, pi->tx_chan), mp, @@ -500,12 +617,151 @@ static void cxgbe_dev_rx_queue_release(void *q) } } +/* + * Get port statistics. + */ +static void cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev, + struct rte_eth_stats *eth_stats) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + struct sge *s = &adapter->sge; + struct port_stats ps; + unsigned int i; + + cxgbe_stats_get(pi, &ps); + + /* RX Stats */ + eth_stats->ipackets = ps.rx_frames; + eth_stats->ibytes = ps.rx_octets; + eth_stats->imcasts = ps.rx_mcast_frames; + eth_stats->imissed = ps.rx_ovflow0 + ps.rx_ovflow1 + + ps.rx_ovflow2 + ps.rx_ovflow3 + + ps.rx_trunc0 + ps.rx_trunc1 + + ps.rx_trunc2 + ps.rx_trunc3; + eth_stats->ibadcrc = ps.rx_fcs_err; + eth_stats->ibadlen = ps.rx_jabber + ps.rx_too_long + ps.rx_runt; + eth_stats->ierrors = ps.rx_symbol_err + eth_stats->ibadcrc + + eth_stats->ibadlen + ps.rx_len_err + + eth_stats->imissed; + eth_stats->rx_pause_xon = ps.rx_pause; + + /* TX Stats */ + eth_stats->opackets = ps.tx_frames; + eth_stats->obytes = ps.tx_octets; + eth_stats->oerrors = ps.tx_error_frames; + eth_stats->tx_pause_xon = ps.tx_pause; + + for (i = 0; i < pi->n_rx_qsets; i++) { + struct sge_eth_rxq *rxq = + &s->ethrxq[pi->first_qset + i]; + + eth_stats->q_ipackets[i] = rxq->stats.pkts; + eth_stats->q_ibytes[i] = rxq->stats.rx_bytes; + } + + for (i = 0; i < pi->n_tx_qsets; i++) { + struct sge_eth_txq *txq = + &s->ethtxq[pi->first_qset + i]; + + eth_stats->q_opackets[i] = txq->stats.pkts; + eth_stats->q_obytes[i] = txq->stats.tx_bytes; + eth_stats->q_errors[i] = txq->stats.mapping_err; + } +} + +/* + * Reset port statistics. + */ +static void cxgbe_dev_stats_reset(struct rte_eth_dev *eth_dev) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + struct sge *s = &adapter->sge; + unsigned int i; + + cxgbe_stats_reset(pi); + for (i = 0; i < pi->n_rx_qsets; i++) { + struct sge_eth_rxq *rxq = + &s->ethrxq[pi->first_qset + i]; + + rxq->stats.pkts = 0; + rxq->stats.rx_bytes = 0; + } + for (i = 0; i < pi->n_tx_qsets; i++) { + struct sge_eth_txq *txq = + &s->ethtxq[pi->first_qset + i]; + + txq->stats.pkts = 0; + txq->stats.tx_bytes = 0; + txq->stats.mapping_err = 0; + } +} + +static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev, + struct rte_eth_fc_conf *fc_conf) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct link_config *lc = &pi->link_cfg; + int rx_pause, tx_pause; + + fc_conf->autoneg = lc->fc & PAUSE_AUTONEG; + rx_pause = lc->fc & PAUSE_RX; + tx_pause = lc->fc & PAUSE_TX; + + if (rx_pause && tx_pause) + fc_conf->mode = RTE_FC_FULL; + else if (rx_pause) + fc_conf->mode = RTE_FC_RX_PAUSE; + else if (tx_pause) + fc_conf->mode = RTE_FC_TX_PAUSE; + else + fc_conf->mode = RTE_FC_NONE; + return 0; +} + +static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev, + struct rte_eth_fc_conf *fc_conf) +{ + struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); + struct adapter *adapter = pi->adapter; + struct link_config *lc = &pi->link_cfg; + + if (lc->supported & FW_PORT_CAP_ANEG) { + if (fc_conf->autoneg) + lc->requested_fc |= PAUSE_AUTONEG; + else + lc->requested_fc &= ~PAUSE_AUTONEG; + } + + if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || + (fc_conf->mode & RTE_FC_RX_PAUSE)) + lc->requested_fc |= PAUSE_RX; + else + lc->requested_fc &= ~PAUSE_RX; + + if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || + (fc_conf->mode & RTE_FC_TX_PAUSE)) + lc->requested_fc |= PAUSE_TX; + else + lc->requested_fc &= ~PAUSE_TX; + + return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, + &pi->link_cfg); +} + static struct eth_dev_ops cxgbe_eth_dev_ops = { .dev_start = cxgbe_dev_start, .dev_stop = cxgbe_dev_stop, .dev_close = cxgbe_dev_close, + .promiscuous_enable = cxgbe_dev_promiscuous_enable, + .promiscuous_disable = cxgbe_dev_promiscuous_disable, + .allmulticast_enable = cxgbe_dev_allmulticast_enable, + .allmulticast_disable = cxgbe_dev_allmulticast_disable, .dev_configure = cxgbe_dev_configure, .dev_infos_get = cxgbe_dev_info_get, + .link_update = cxgbe_dev_link_update, + .mtu_set = cxgbe_dev_mtu_set, .tx_queue_setup = cxgbe_dev_tx_queue_setup, .tx_queue_start = cxgbe_dev_tx_queue_start, .tx_queue_stop = cxgbe_dev_tx_queue_stop, @@ -514,6 +770,10 @@ static struct eth_dev_ops cxgbe_eth_dev_ops = { .rx_queue_start = cxgbe_dev_rx_queue_start, .rx_queue_stop = cxgbe_dev_rx_queue_stop, .rx_queue_release = cxgbe_dev_rx_queue_release, + .stats_get = cxgbe_dev_stats_get, + .stats_reset = cxgbe_dev_stats_reset, + .flow_ctrl_get = cxgbe_flow_ctrl_get, + .flow_ctrl_set = cxgbe_flow_ctrl_set, }; /*