#include <rte_log.h>
#include <rte_debug.h>
#include <rte_pci.h>
-#include <rte_atomic.h>
#include <rte_branch_prediction.h>
#include <rte_memory.h>
#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_alarm.h>
#include <rte_ether.h>
-#include <rte_ethdev_driver.h>
+#include <ethdev_driver.h>
#include <rte_malloc.h>
#include <rte_random.h>
#include <rte_dev.h>
*/
#define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN
-/*
- * Rx buffer sizes for "usembufs" Free List buffers (one ingress packet
- * per mbuf buffer). We currently only support two sizes for 1500- and
- * 9000-byte MTUs. We could easily support more but there doesn't seem to be
- * much need for that ...
- */
-#define FL_MTU_SMALL 1500
-#define FL_MTU_LARGE 9000
-
-static inline unsigned int fl_mtu_bufsize(struct adapter *adapter,
- unsigned int mtu)
-{
- struct sge *s = &adapter->sge;
-
- return CXGBE_ALIGN(s->pktshift + RTE_ETHER_HDR_LEN + VLAN_HLEN + mtu,
- s->fl_align);
-}
-
-#define FL_MTU_SMALL_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_SMALL)
-#define FL_MTU_LARGE_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_LARGE)
-
/*
* Bits 0..3 of rx_sw_desc.dma_addr have special meaning. The hardware uses
* these to specify the buffer size as an index into the SGE Free List Buffer
RX_BUF_FLAGS = 0x1f, /* bottom five bits are special */
RX_BUF_SIZE = 0x0f, /* bottom three bits are for buf sizes */
RX_UNMAPPED_BUF = 0x10, /* buffer is not mapped */
-
- /*
- * XXX We shouldn't depend on being able to use these indices.
- * XXX Especially when some other Master PF has initialized the
- * XXX adapter or we use the Firmware Configuration File. We
- * XXX should really search through the Host Buffer Size register
- * XXX array for the appropriately sized buffer indices.
- */
- RX_SMALL_PG_BUF = 0x0, /* small (PAGE_SIZE) page buffer */
- RX_LARGE_PG_BUF = 0x1, /* buffer large page buffer */
-
- RX_SMALL_MTU_BUF = 0x2, /* small MTU buffer */
- RX_LARGE_MTU_BUF = 0x3, /* large MTU buffer */
};
/**
* @fl: the Free List
*
* Tests specified Free List to see whether the number of buffers
- * available to the hardware has falled below our "starvation"
+ * available to the hardware has fallen below our "starvation"
* threshold.
*/
static inline bool fl_starving(const struct adapter *adapter,
static inline unsigned int get_buf_size(struct adapter *adapter,
const struct rx_sw_desc *d)
{
- unsigned int rx_buf_size_idx = d->dma_addr & RX_BUF_SIZE;
- unsigned int buf_size = 0;
-
- switch (rx_buf_size_idx) {
- case RX_SMALL_MTU_BUF:
- buf_size = FL_MTU_SMALL_BUFSIZE(adapter);
- break;
-
- case RX_LARGE_MTU_BUF:
- buf_size = FL_MTU_LARGE_BUFSIZE(adapter);
- break;
-
- default:
- BUG_ON(1);
- /* NOT REACHED */
- }
-
- return buf_size;
+ return adapter->sge.fl_buffer_size[d->dma_addr & RX_BUF_SIZE];
}
/**
int n)
{
struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, fl);
- unsigned int cred = q->avail;
- __be64 *d = &q->desc[q->pidx];
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
- unsigned int buf_size_idx = RX_SMALL_MTU_BUF;
+ __be64 *d = &q->desc[q->pidx];
struct rte_mbuf *buf_bulk[n];
+ unsigned int cred = q->avail;
int ret, i;
- struct rte_pktmbuf_pool_private *mbp_priv;
- u8 jumbo_en = rxq->rspq.eth_dev->data->dev_conf.rxmode.offloads &
- DEV_RX_OFFLOAD_JUMBO_FRAME;
-
- /* Use jumbo mtu buffers if mbuf data room size can fit jumbo data. */
- mbp_priv = rte_mempool_get_priv(rxq->rspq.mb_pool);
- if (jumbo_en &&
- ((mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM) >= 9000))
- buf_size_idx = RX_LARGE_MTU_BUF;
ret = rte_mempool_get_bulk(rxq->rspq.mb_pool, (void *)buf_bulk, n);
if (unlikely(ret != 0)) {
}
rte_mbuf_refcnt_set(mbuf, 1);
- mbuf->data_off =
- (uint16_t)((char *)
- RTE_PTR_ALIGN((char *)mbuf->buf_addr +
- RTE_PKTMBUF_HEADROOM,
- adap->sge.fl_align) -
- (char *)mbuf->buf_addr);
+ mbuf->data_off = RTE_PKTMBUF_HEADROOM;
mbuf->next = NULL;
mbuf->nb_segs = 1;
mbuf->port = rxq->rspq.port_id;
- mapping = (dma_addr_t)RTE_ALIGN(mbuf->buf_iova +
- mbuf->data_off,
- adap->sge.fl_align);
- mapping |= buf_size_idx;
+ mapping = (dma_addr_t)(mbuf->buf_iova + mbuf->data_off);
+ mapping |= q->fl_buf_size_idx;
*d++ = cpu_to_be64(mapping);
set_rx_sw_desc(sd, mbuf, mapping);
sd++;
*/
static inline int is_eth_imm(const struct rte_mbuf *m)
{
- unsigned int hdrlen = (m->ol_flags & PKT_TX_TCP_SEG) ?
+ unsigned int hdrlen = (m->ol_flags & RTE_MBUF_F_TX_TCP_SEG) ?
sizeof(struct cpl_tx_pkt_lso_core) : 0;
hdrlen += sizeof(struct cpl_tx_pkt);
* @q: the Tx queue
* @n: number of new descriptors to give to HW
*
- * Ring the doorbel for a Tx queue.
+ * Ring the doorbell for a Tx queue.
*/
static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q)
{
{
int csum_type;
- if (m->ol_flags & PKT_TX_IP_CKSUM) {
- switch (m->ol_flags & PKT_TX_L4_MASK) {
- case PKT_TX_TCP_CKSUM:
+ if (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
+ switch (m->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
+ case RTE_MBUF_F_TX_TCP_CKSUM:
csum_type = TX_CSUM_TCPIP;
break;
- case PKT_TX_UDP_CKSUM:
+ case RTE_MBUF_F_TX_UDP_CKSUM:
csum_type = TX_CSUM_UDPIP;
break;
default:
#define MAX_COALESCE_LEN 64000
-static inline int wraps_around(struct sge_txq *q, int ndesc)
+static inline bool wraps_around(struct sge_txq *q, int ndesc)
{
- return (q->pidx + ndesc) > q->size ? 1 : 0;
+ return (q->pidx + ndesc) > q->size ? true : false;
}
static void tx_timer_cb(void *data)
/* fill the pkts WR header */
wr = (void *)&q->desc[q->pidx];
- wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS2_WR));
vmwr = (void *)&q->desc[q->pidx];
wr_mid = V_FW_WR_LEN16(DIV_ROUND_UP(q->coalesce.flits, 2));
wr->npkt = q->coalesce.idx;
wr->r3 = 0;
if (is_pf4(adap)) {
- wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS2_WR));
wr->type = q->coalesce.type;
+ if (likely(wr->type != 0))
+ wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS2_WR));
+ else
+ wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS_WR));
} else {
wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS_VM_WR));
vmwr->r4 = 0;
}
/**
- * should_tx_packet_coalesce - decides wether to coalesce an mbuf or not
+ * should_tx_packet_coalesce - decides whether to coalesce an mbuf or not
* @txq: tx queue where the mbuf is sent
* @mbuf: mbuf to be sent
* @nflits: return value for number of flits needed
ndesc = DIV_ROUND_UP(q->coalesce.flits + flits, 8);
credits = txq_avail(q) - ndesc;
+ if (unlikely(wraps_around(q, ndesc)))
+ return 0;
+
/* If we are wrapping or this is last mbuf then, send the
* already coalesced mbufs and let the non-coalesce pass
* handle the mbuf.
*/
- if (unlikely(credits < 0 || wraps_around(q, ndesc))) {
+ if (unlikely(credits < 0)) {
ship_tx_pkt_coalesce_wr(adap, txq);
- return 0;
+ return -EBUSY;
}
/* If the max coalesce len or the max WR len is reached
ndesc = flits_to_desc(q->coalesce.flits + flits);
credits = txq_avail(q) - ndesc;
- if (unlikely(credits < 0 || wraps_around(q, ndesc)))
+ if (unlikely(wraps_around(q, ndesc)))
return 0;
+
+ if (unlikely(credits < 0))
+ return -EBUSY;
+
q->coalesce.flits += wr_size / sizeof(__be64);
q->coalesce.type = type;
q->coalesce.ptr = (unsigned char *)&q->desc[q->pidx] +
struct cpl_tx_pkt_core *cpl;
struct tx_sw_desc *sd;
unsigned int idx = q->coalesce.idx, len = mbuf->pkt_len;
- unsigned int max_coal_pkt_num = is_pf4(adap) ? ETH_COALESCE_PKT_NUM :
- ETH_COALESCE_VF_PKT_NUM;
if (q->coalesce.type == 0) {
mc = (struct ulp_txpkt *)q->coalesce.ptr;
/* fill the cpl message, same as in t4_eth_xmit, this should be kept
* similar to t4_eth_xmit
*/
- if (mbuf->ol_flags & PKT_TX_IP_CKSUM) {
+ if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
cntrl = hwcsum(adap->params.chip, mbuf) |
F_TXPKT_IPCSUM_DIS;
txq->stats.tx_cso++;
cntrl = F_TXPKT_L4CSUM_DIS | F_TXPKT_IPCSUM_DIS;
}
- if (mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ if (mbuf->ol_flags & RTE_MBUF_F_TX_VLAN) {
txq->stats.vlan_ins++;
cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(mbuf->vlan_tci);
}
* for coalescing the next Tx burst and send the packets now.
*/
q->coalesce.idx++;
- if (q->coalesce.idx == max_coal_pkt_num ||
+ if (q->coalesce.idx == adap->params.max_tx_coalesce_num ||
(adap->devargs.tx_mode_latency && q->coalesce.idx >= nb_pkts))
ship_tx_pkt_coalesce_wr(adap, txq);
unsigned int flits, ndesc, cflits;
int l3hdr_len, l4hdr_len, eth_xtra_len;
int len, last_desc;
- int credits;
+ int should_coal, credits;
u32 wr_mid;
u64 cntrl, *end;
bool v6;
- u32 max_pkt_len = txq->data->dev_conf.rxmode.max_rx_pkt_len;
+ u32 max_pkt_len;
/* Reject xmit if queue is stopped */
if (unlikely(txq->flags & EQ_STOPPED))
return 0;
}
- if ((!(m->ol_flags & PKT_TX_TCP_SEG)) &&
+ max_pkt_len = txq->data->mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
+ if ((!(m->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) &&
(unlikely(m->pkt_len > max_pkt_len)))
goto out_free;
/* align the end of coalesce WR to a 512 byte boundary */
txq->q.coalesce.max = (8 - (txq->q.pidx & 7)) * 8;
- if (!((m->ol_flags & PKT_TX_TCP_SEG) ||
- m->pkt_len > RTE_ETHER_MAX_LEN)) {
- if (should_tx_packet_coalesce(txq, mbuf, &cflits, adap)) {
+ if ((m->ol_flags & RTE_MBUF_F_TX_TCP_SEG) == 0) {
+ should_coal = should_tx_packet_coalesce(txq, mbuf, &cflits, adap);
+ if (should_coal > 0) {
if (unlikely(map_mbuf(mbuf, addr) < 0)) {
dev_warn(adap, "%s: mapping err for coalesce\n",
__func__);
}
return tx_do_packet_coalesce(txq, mbuf, cflits, adap,
pi, addr, nb_pkts);
- } else {
- return -EBUSY;
+ } else if (should_coal < 0) {
+ return should_coal;
}
}
end = (u64 *)vmwr + flits;
}
- len = 0;
- len += sizeof(*cpl);
+ len = sizeof(*cpl);
/* Coalescing skipped and we send through normal path */
- if (!(m->ol_flags & PKT_TX_TCP_SEG)) {
+ if (!(m->ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
wr->op_immdlen = htonl(V_FW_WR_OP(is_pf4(adap) ?
FW_ETH_TX_PKT_WR :
FW_ETH_TX_PKT_VM_WR) |
cpl = (void *)(wr + 1);
else
cpl = (void *)(vmwr + 1);
- if (m->ol_flags & PKT_TX_IP_CKSUM) {
+ if (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
cntrl = hwcsum(adap->params.chip, m) |
F_TXPKT_IPCSUM_DIS;
txq->stats.tx_cso++;
lso = (void *)(wr + 1);
else
lso = (void *)(vmwr + 1);
- v6 = (m->ol_flags & PKT_TX_IPV6) != 0;
+ v6 = (m->ol_flags & RTE_MBUF_F_TX_IPV6) != 0;
l3hdr_len = m->l3_len;
l4hdr_len = m->l4_len;
eth_xtra_len = m->l2_len - RTE_ETHER_HDR_LEN;
txq->stats.tx_cso += m->tso_segsz;
}
- if (m->ol_flags & PKT_TX_VLAN_PKT) {
+ if (m->ol_flags & RTE_MBUF_F_TX_VLAN) {
txq->stats.vlan_ins++;
cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(m->vlan_tci);
}
/**
* alloc_ring - allocate resources for an SGE descriptor ring
- * @dev: the PCI device's core device
+ * @dev: the port associated with the queue
+ * @z_name: memzone's name
+ * @queue_id: queue index
+ * @socket_id: preferred socket id for memory allocations
* @nelem: the number of descriptors
* @elem_size: the size of each descriptor
+ * @stat_size: extra space in HW ring for status information
* @sw_size: the size of the SW state associated with each ring element
* @phys: the physical address of the allocated ring
* @metadata: address of the array holding the SW state for the ring
- * @stat_size: extra space in HW ring for status information
- * @node: preferred node for memory allocations
*
* Allocates resources for an SGE descriptor ring, such as Tx queues,
* free buffer lists, or response queues. Each SGE ring requires
* of the function), the bus address of the HW ring, and the address
* of the SW ring.
*/
-static void *alloc_ring(size_t nelem, size_t elem_size,
- size_t sw_size, dma_addr_t *phys, void *metadata,
- size_t stat_size, __rte_unused uint16_t queue_id,
- int socket_id, const char *z_name,
- const char *z_name_sw)
+static void *alloc_ring(struct rte_eth_dev *dev, const char *z_name,
+ uint16_t queue_id, int socket_id, size_t nelem,
+ size_t elem_size, size_t stat_size, size_t sw_size,
+ dma_addr_t *phys, void *metadata)
{
size_t len = CXGBE_MAX_RING_DESC_SIZE * elem_size + stat_size;
+ char z_name_sw[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *tz;
void *s = NULL;
+ snprintf(z_name_sw, sizeof(z_name_sw), "eth_p%d_q%d_%s_sw_ring",
+ dev->data->port_id, queue_id, z_name);
+
dev_debug(adapter, "%s: nelem = %zu; elem_size = %zu; sw_size = %zu; "
"stat_size = %zu; queue_id = %u; socket_id = %d; z_name = %s;"
" z_name_sw = %s\n", __func__, nelem, elem_size, sw_size,
stat_size, queue_id, socket_id, z_name, z_name_sw);
- tz = rte_memzone_lookup(z_name);
- if (tz) {
- dev_debug(adapter, "%s: tz exists...returning existing..\n",
- __func__);
- goto alloc_sw_ring;
- }
-
/*
* Allocate TX/RX ring hardware descriptors. A memzone large enough to
* handle the maximum ring size is allocated in order to allow for
* resizing in later calls to the queue setup function.
*/
- tz = rte_memzone_reserve_aligned(z_name, len, socket_id,
- RTE_MEMZONE_IOVA_CONTIG, 4096);
+ tz = rte_eth_dma_zone_reserve(dev, z_name, queue_id, len, 4096,
+ socket_id);
if (!tz)
return NULL;
-alloc_sw_ring:
memset(tz->addr, 0, len);
if (sw_size) {
s = rte_zmalloc_socket(z_name_sw, nelem * sw_size,
if (cpl->vlan_ex)
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L2_ETHER_VLAN,
- PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED);
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
else
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L2_ETHER, 0);
if (cpl->l2info & htonl(F_RXF_IP))
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L3_IPV4,
- csum_ok ? PKT_RX_IP_CKSUM_GOOD :
- PKT_RX_IP_CKSUM_BAD);
+ csum_ok ? RTE_MBUF_F_RX_IP_CKSUM_GOOD :
+ RTE_MBUF_F_RX_IP_CKSUM_BAD);
else if (cpl->l2info & htonl(F_RXF_IP6))
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L3_IPV6,
- csum_ok ? PKT_RX_IP_CKSUM_GOOD :
- PKT_RX_IP_CKSUM_BAD);
+ csum_ok ? RTE_MBUF_F_RX_IP_CKSUM_GOOD :
+ RTE_MBUF_F_RX_IP_CKSUM_BAD);
if (cpl->l2info & htonl(F_RXF_TCP))
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L4_TCP,
- csum_ok ? PKT_RX_L4_CKSUM_GOOD :
- PKT_RX_L4_CKSUM_BAD);
+ csum_ok ? RTE_MBUF_F_RX_L4_CKSUM_GOOD :
+ RTE_MBUF_F_RX_L4_CKSUM_BAD);
else if (cpl->l2info & htonl(F_RXF_UDP))
cxgbe_set_mbuf_info(pkt, RTE_PTYPE_L4_UDP,
- csum_ok ? PKT_RX_L4_CKSUM_GOOD :
- PKT_RX_L4_CKSUM_BAD);
+ csum_ok ? RTE_MBUF_F_RX_L4_CKSUM_GOOD :
+ RTE_MBUF_F_RX_L4_CKSUM_BAD);
}
/**
if (!rss_hdr->filter_tid &&
rss_hdr->hash_type) {
- pkt->ol_flags |= PKT_RX_RSS_HASH;
+ pkt->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
pkt->hash.rss =
ntohl(rss_hdr->hash_val);
}
unsigned int params;
u32 val;
+ if (unlikely(rxq->flags & IQ_STOPPED)) {
+ *work_done = 0;
+ return 0;
+ }
+
*work_done = process_responses(q, budget, rx_pkts);
if (*work_done) {
return adapter->bar2 + bar2_qoffset;
}
-int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq)
+int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_eth_rxq *rxq)
{
- struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq);
unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff;
+ rxq->flags &= ~IQ_STOPPED;
return t4_iq_start_stop(adap, adap->mbox, true, adap->pf, 0,
- rq->cntxt_id, fl_id, 0xffff);
+ rxq->rspq.cntxt_id, fl_id, 0xffff);
}
-int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq)
+int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_eth_rxq *rxq)
{
- struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq);
unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff;
+ rxq->flags |= IQ_STOPPED;
return t4_iq_start_stop(adap, adap->mbox, false, adap->pf, 0,
- rq->cntxt_id, fl_id, 0xffff);
+ rxq->rspq.cntxt_id, fl_id, 0xffff);
+}
+
+static int cxgbe_sge_fl_buf_size_index(const struct adapter *adap,
+ struct rte_mempool *mp)
+{
+ int fl_buf_size, size, delta, min_delta = INT_MAX;
+ unsigned int i, match = UINT_MAX;
+ const struct sge *s = &adap->sge;
+
+ size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
+ for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++) {
+ fl_buf_size = s->fl_buffer_size[i];
+ if (fl_buf_size > size || fl_buf_size == 0)
+ continue;
+
+ delta = size - fl_buf_size;
+ if (delta < 0)
+ delta = -delta;
+ if (delta < min_delta) {
+ min_delta = delta;
+ match = i;
+ }
+ }
+
+ if (match == UINT_MAX) {
+ dev_err(adap,
+ "Could not find valid buffer size for mbuf data room: %d\n",
+ size);
+ return -EINVAL;
+ }
+
+ return match;
}
/*
struct sge_fl *fl, rspq_handler_t hnd, int cong,
struct rte_mempool *mp, int queue_id, int socket_id)
{
- int ret, flsz = 0;
- struct fw_iq_cmd c;
- struct sge *s = &adap->sge;
struct port_info *pi = eth_dev->data->dev_private;
- char z_name[RTE_MEMZONE_NAMESIZE];
- char z_name_sw[RTE_MEMZONE_NAMESIZE];
+ u8 pciechan, fl_buf_size_idx = 0;
+ struct sge *s = &adap->sge;
unsigned int nb_refill;
- u8 pciechan;
+ struct fw_iq_cmd c;
+ int ret, flsz = 0;
+
+ if (fl != NULL) {
+ ret = cxgbe_sge_fl_buf_size_index(adap, mp);
+ if (ret < 0)
+ return ret;
+
+ fl_buf_size_idx = ret;
+ }
/* Size needs to be multiple of 16, including status entry. */
iq->size = cxgbe_roundup(iq->size, 16);
- snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
- eth_dev->data->port_id, queue_id,
- fwevtq ? "fwq_ring" : "rx_ring");
- snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
- iq->desc = alloc_ring(iq->size, iq->iqe_len, 0, &iq->phys_addr, NULL, 0,
- queue_id, socket_id, z_name, z_name_sw);
+ iq->desc = alloc_ring(eth_dev, fwevtq ? "fwq_ring" : "rx_ring",
+ queue_id, socket_id, iq->size, iq->iqe_len,
+ 0, 0, &iq->phys_addr, NULL);
if (!iq->desc)
return -ENOMEM;
c.iqaddr = cpu_to_be64(iq->phys_addr);
if (fl) {
- struct sge_eth_rxq *rxq = container_of(fl, struct sge_eth_rxq,
- fl);
unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
/*
* for its status page) along with the associated software
* descriptor ring. The free list size needs to be a multiple
* of the Egress Queue Unit and at least 2 Egress Units larger
- * than the SGE's Egress Congrestion Threshold
+ * than the SGE's Egress Congestion Threshold
* (fl_starve_thres - 1).
*/
if (fl->size < s->fl_starve_thres - 1 + 2 * 8)
fl->size = s->fl_starve_thres - 1 + 2 * 8;
fl->size = cxgbe_roundup(fl->size, 8);
- snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
- eth_dev->data->port_id, queue_id,
- fwevtq ? "fwq_ring" : "fl_ring");
- snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
- fl->desc = alloc_ring(fl->size, sizeof(__be64),
+ fl->desc = alloc_ring(eth_dev, "fl_ring", queue_id, socket_id,
+ fl->size, sizeof(__be64), s->stat_len,
sizeof(struct rx_sw_desc),
- &fl->addr, &fl->sdesc, s->stat_len,
- queue_id, socket_id, z_name, z_name_sw);
-
- if (!fl->desc)
- goto fl_nomem;
+ &fl->addr, &fl->sdesc);
+ if (!fl->desc) {
+ ret = -ENOMEM;
+ goto err;
+ }
flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
c.iqns_to_fl0congen |=
htonl(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) |
- (unlikely(rxq->usembufs) ?
- 0 : F_FW_IQ_CMD_FL0PACKEN) |
- F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO |
- F_FW_IQ_CMD_FL0PADEN);
+ F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO);
if (is_pf4(adap) && cong >= 0)
c.iqns_to_fl0congen |=
htonl(V_FW_IQ_CMD_FL0CNGCHMAP(cong) |
iq->stat = (void *)&iq->desc[iq->size * 8];
iq->eth_dev = eth_dev;
iq->handler = hnd;
- iq->port_id = pi->pidx;
+ iq->port_id = eth_dev->data->port_id;
iq->mb_pool = mp;
/* set offset to -1 to distinguish ingress queues without FL */
fl->pidx = 0;
fl->cidx = 0;
fl->alloc_failed = 0;
+ fl->fl_buf_size_idx = fl_buf_size_idx;
/*
* Note, we must initialize the BAR2 Free List User Doorbell
* simple (and hopefully less wrong).
*/
if (is_pf4(adap) && !is_t4(adap->params.chip) && cong >= 0) {
- u32 param, val;
+ u8 cng_ch_bits_log = adap->params.arch.cng_ch_bits_log;
+ u32 param, val, ch_map = 0;
int i;
param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
X_CONMCTXT_CNGTPMODE_CHANNEL);
for (i = 0; i < 4; i++) {
if (cong & (1 << i))
- val |= V_CONMCTXT_CNGCHMAP(1 <<
- (i << 2));
+ ch_map |= 1 << (i << cng_ch_bits_log);
}
+ val |= V_CONMCTXT_CNGCHMAP(ch_map);
}
ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1,
¶m, &val);
refill_fl_err:
t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP,
iq->cntxt_id, fl->cntxt_id, 0xffff);
-fl_nomem:
- ret = -ENOMEM;
err:
iq->cntxt_id = 0;
iq->abs_id = 0;
struct fw_eq_eth_cmd c;
struct sge *s = &adap->sge;
struct port_info *pi = eth_dev->data->dev_private;
- char z_name[RTE_MEMZONE_NAMESIZE];
- char z_name_sw[RTE_MEMZONE_NAMESIZE];
u8 pciechan;
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
- snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
- eth_dev->data->port_id, queue_id, "tx_ring");
- snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
- txq->q.desc = alloc_ring(txq->q.size, sizeof(struct tx_desc),
- sizeof(struct tx_sw_desc), &txq->q.phys_addr,
- &txq->q.sdesc, s->stat_len, queue_id,
- socket_id, z_name, z_name_sw);
+ txq->q.desc = alloc_ring(eth_dev, "tx_ring", queue_id, socket_id,
+ txq->q.size, sizeof(struct tx_desc),
+ s->stat_len, sizeof(struct tx_sw_desc),
+ &txq->q.phys_addr, &txq->q.sdesc);
if (!txq->q.desc)
return -ENOMEM;
struct fw_eq_ctrl_cmd c;
struct sge *s = &adap->sge;
struct port_info *pi = eth_dev->data->dev_private;
- char z_name[RTE_MEMZONE_NAMESIZE];
- char z_name_sw[RTE_MEMZONE_NAMESIZE];
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
- snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
- eth_dev->data->port_id, queue_id, "ctrl_tx_ring");
- snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
- txq->q.desc = alloc_ring(txq->q.size, sizeof(struct tx_desc),
- 0, &txq->q.phys_addr,
- NULL, 0, queue_id,
- socket_id, z_name, z_name_sw);
+ txq->q.desc = alloc_ring(eth_dev, "ctrl_tx_ring", queue_id,
+ socket_id, txq->q.size, sizeof(struct tx_desc),
+ 0, 0, &txq->q.phys_addr, NULL);
if (!txq->q.desc)
return -ENOMEM;
*/
void t4_sge_eth_clear_queues(struct port_info *pi)
{
- int i;
struct adapter *adap = pi->adapter;
- struct sge_eth_rxq *rxq = &adap->sge.ethrxq[pi->first_qset];
- struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset];
+ struct sge_eth_rxq *rxq;
+ struct sge_eth_txq *txq;
+ int i;
+ rxq = &adap->sge.ethrxq[pi->first_rxqset];
for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
if (rxq->rspq.desc)
- t4_sge_eth_rxq_stop(adap, &rxq->rspq);
+ t4_sge_eth_rxq_stop(adap, rxq);
}
+
+ txq = &adap->sge.ethtxq[pi->first_txqset];
for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
if (txq->q.desc) {
struct sge_txq *q = &txq->q;
void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq)
{
if (rxq->rspq.desc) {
- t4_sge_eth_rxq_stop(adap, &rxq->rspq);
+ t4_sge_eth_rxq_stop(adap, rxq);
free_rspq_fl(adap, &rxq->rspq, rxq->fl.size ? &rxq->fl : NULL);
}
}
}
}
+void t4_sge_eth_release_queues(struct port_info *pi)
+{
+ struct adapter *adap = pi->adapter;
+ struct sge_eth_rxq *rxq;
+ struct sge_eth_txq *txq;
+ unsigned int i;
+
+ rxq = &adap->sge.ethrxq[pi->first_rxqset];
+ /* clean up Ethernet Tx/Rx queues */
+ for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
+ /* Free only the queues allocated */
+ if (rxq->rspq.desc) {
+ t4_sge_eth_rxq_release(adap, rxq);
+ rte_eth_dma_zone_free(rxq->rspq.eth_dev, "fl_ring", i);
+ rte_eth_dma_zone_free(rxq->rspq.eth_dev, "rx_ring", i);
+ rxq->rspq.eth_dev = NULL;
+ }
+ }
+
+ txq = &adap->sge.ethtxq[pi->first_txqset];
+ for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
+ /* Free only the queues allocated */
+ if (txq->q.desc) {
+ t4_sge_eth_txq_release(adap, txq);
+ rte_eth_dma_zone_free(txq->eth_dev, "tx_ring", i);
+ txq->eth_dev = NULL;
+ }
+ }
+}
+
void t4_sge_tx_monitor_start(struct adapter *adap)
{
rte_eal_alarm_set(50, tx_timer_cb, (void *)adap);
void t4_free_sge_resources(struct adapter *adap)
{
unsigned int i;
- struct sge_eth_rxq *rxq = &adap->sge.ethrxq[0];
- struct sge_eth_txq *txq = &adap->sge.ethtxq[0];
-
- /* clean up Ethernet Tx/Rx queues */
- for (i = 0; i < adap->sge.max_ethqsets; i++, rxq++, txq++) {
- /* Free only the queues allocated */
- if (rxq->rspq.desc) {
- t4_sge_eth_rxq_release(adap, rxq);
- rxq->rspq.eth_dev = NULL;
- }
- if (txq->q.desc) {
- t4_sge_eth_txq_release(adap, txq);
- txq->eth_dev = NULL;
- }
- }
/* clean up control Tx queues */
for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
reclaim_completed_tx_imm(&cq->q);
t4_ctrl_eq_free(adap, adap->mbox, adap->pf, 0,
cq->q.cntxt_id);
+ rte_eth_dma_zone_free(adap->eth_dev, "ctrl_tx_ring", i);
+ rte_mempool_free(cq->mb_pool);
free_txq(&cq->q);
}
}
- if (adap->sge.fw_evtq.desc)
+ /* clean up firmware event queue */
+ if (adap->sge.fw_evtq.desc) {
free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
+ rte_eth_dma_zone_free(adap->eth_dev, "fwq_ring", 0);
+ }
}
/**
*/
static int t4_sge_init_soft(struct adapter *adap)
{
- struct sge *s = &adap->sge;
- u32 fl_small_pg, fl_large_pg, fl_small_mtu, fl_large_mtu;
u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5;
+ struct sge *s = &adap->sge;
u32 ingress_rx_threshold;
+ u8 i;
/*
* Verify that CPL messages are going to the Ingress Queue for
}
/*
- * Validate the Host Buffer Register Array indices that we want to
+ * Read the Host Buffer Register Array indices that we want to
* use ...
- *
- * XXX Note that we should really read through the Host Buffer Size
- * XXX register array and find the indices of the Buffer Sizes which
- * XXX meet our needs!
- */
-#define READ_FL_BUF(x) \
- t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE0 + (x) * sizeof(u32))
-
- fl_small_pg = READ_FL_BUF(RX_SMALL_PG_BUF);
- fl_large_pg = READ_FL_BUF(RX_LARGE_PG_BUF);
- fl_small_mtu = READ_FL_BUF(RX_SMALL_MTU_BUF);
- fl_large_mtu = READ_FL_BUF(RX_LARGE_MTU_BUF);
-
- /*
- * We only bother using the Large Page logic if the Large Page Buffer
- * is larger than our Page Size Buffer.
*/
- if (fl_large_pg <= fl_small_pg)
- fl_large_pg = 0;
-
-#undef READ_FL_BUF
-
- /*
- * The Page Size Buffer must be exactly equal to our Page Size and the
- * Large Page Size Buffer should be 0 (per above) or a power of 2.
- */
- if (fl_small_pg != CXGBE_PAGE_SIZE ||
- (fl_large_pg & (fl_large_pg - 1)) != 0) {
- dev_err(adap, "bad SGE FL page buffer sizes [%d, %d]\n",
- fl_small_pg, fl_large_pg);
- return -EINVAL;
- }
- if (fl_large_pg)
- s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT;
-
- if (adap->use_unpacked_mode) {
- int err = 0;
-
- if (fl_small_mtu < FL_MTU_SMALL_BUFSIZE(adap)) {
- dev_err(adap, "bad SGE FL small MTU %d\n",
- fl_small_mtu);
- err = -EINVAL;
- }
- if (fl_large_mtu < FL_MTU_LARGE_BUFSIZE(adap)) {
- dev_err(adap, "bad SGE FL large MTU %d\n",
- fl_large_mtu);
- err = -EINVAL;
- }
- if (err)
- return err;
- }
+ for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++)
+ s->fl_buffer_size[i] = t4_read_reg(adap,
+ A_SGE_FL_BUFFER_SIZE0 +
+ i * sizeof(u32));
/*
* Retrieve our RX interrupt holdoff timer values and counter
sge_control = t4_read_reg(adap, A_SGE_CONTROL);
s->pktshift = G_PKTSHIFT(sge_control);
s->stat_len = (sge_control & F_EGRSTATUSPAGESIZE) ? 128 : 64;
- s->fl_align = t4_fl_pkt_align(adap);
ret = t4_sge_init_soft(adap);
if (ret < 0) {
dev_err(adap, "%s: t4_sge_init_soft failed, error %d\n",
struct sge_params *sge_params = &adap->params.sge;
u32 sge_ingress_queues_per_page;
u32 sge_egress_queues_per_page;
- u32 sge_control, sge_control2;
- u32 fl_small_pg, fl_large_pg;
u32 sge_ingress_rx_threshold;
u32 sge_timer_value_0_and_1;
u32 sge_timer_value_2_and_3;
unsigned int s_hps, s_qpp;
u32 sge_host_page_size;
u32 params[7], vals[7];
+ u32 sge_control;
int v;
+ u8 i;
/* query basic params from fw */
params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
- V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0));
- params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
- V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE1));
- params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
- params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
+ params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
- params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
+ params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
v = t4vf_query_params(adap, 7, params, vals);
if (v != FW_SUCCESS)
sge_control = vals[0];
sge_host_page_size = vals[1];
- fl_small_pg = vals[2];
- fl_large_pg = vals[3];
- sge_timer_value_0_and_1 = vals[4];
- sge_timer_value_2_and_3 = vals[5];
- sge_timer_value_4_and_5 = vals[6];
+ sge_timer_value_0_and_1 = vals[2];
+ sge_timer_value_2_and_3 = vals[3];
+ sge_timer_value_4_and_5 = vals[4];
+
+ for (i = 0; i < RTE_DIM(s->fl_buffer_size); i++) {
+ params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
+ V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 +
+ i * sizeof(u32)));
+ v = t4vf_query_params(adap, 1, params, vals);
+ if (v != FW_SUCCESS)
+ return v;
+
+ s->fl_buffer_size[i] = vals[0];
+ }
/*
* Start by vetting the basic SGE parameters which have been set up by
* the Physical Function Driver.
*/
- /* We only bother using the Large Page logic if the Large Page Buffer
- * is larger than our Page Size Buffer.
- */
- if (fl_large_pg <= fl_small_pg)
- fl_large_pg = 0;
-
- /* The Page Size Buffer must be exactly equal to our Page Size and the
- * Large Page Size Buffer should be 0 (per above) or a power of 2.
- */
- if (fl_small_pg != CXGBE_PAGE_SIZE ||
- (fl_large_pg & (fl_large_pg - 1)) != 0) {
- dev_err(adapter->pdev_dev, "bad SGE FL buffer sizes [%d, %d]\n",
- fl_small_pg, fl_large_pg);
- return -EINVAL;
- }
-
if ((sge_control & F_RXPKTCPLMODE) !=
V_RXPKTCPLMODE(X_RXPKTCPLMODE_SPLIT)) {
dev_err(adapter->pdev_dev, "bad SGE CPL MODE\n");
return -EINVAL;
}
-
- /* Grab ingress packing boundary from SGE_CONTROL2 for */
- params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
- V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2));
- v = t4vf_query_params(adap, 1, params, vals);
- if (v != FW_SUCCESS) {
- dev_err(adapter, "Unable to get SGE Control2; "
- "probably old firmware.\n");
- return v;
- }
- sge_control2 = vals[0];
-
params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
/*
* Now translate the queried parameters into our internal forms.
*/
- if (fl_large_pg)
- s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT;
s->stat_len = ((sge_control & F_EGRSTATUSPAGESIZE)
? 128 : 64);
s->pktshift = G_PKTSHIFT(sge_control);
- s->fl_align = t4vf_fl_pkt_align(adap, sge_control, sge_control2);
/*
* A FL with <= fl_starve_thres buffers is starving and a periodic