4 * Copyright(c) 2017 Cavium, Inc.. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Cavium, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "lio_common.h"
38 #include "lio_response_manager.h"
39 #include "lio_device.h"
42 #include "lio_network.h"
46 lio_xmit(struct lio *lio, struct lio_instr_queue *iq,
47 struct mbuf **m_headp)
49 struct lio_data_pkt ndata;
50 union lio_cmd_setup cmdsetup;
51 struct lio_mbuf_free_info *finfo = NULL;
52 struct octeon_device *oct = iq->oct_dev;
53 struct lio_iq_stats *stats;
54 struct octeon_instr_irh *irh;
55 struct lio_request_list *tx_buf;
56 union lio_tx_info *tx_info;
58 bus_dma_segment_t segs[LIO_MAX_SG];
66 iq_no = iq->txpciq.s.q_no;
68 stats = &oct->instr_queue[iq_no]->stats;
69 tx_buf = iq->request_list + iq->host_write_index;
72 * Check for all conditions in which the current packet cannot be
75 if (!(atomic_load_acq_int(&lio->ifstate) & LIO_IFSTATE_RUNNING) ||
76 (!lio->linfo.link.s.link_up)) {
77 lio_dev_info(oct, "Transmit failed link_status : %d\n",
78 lio->linfo.link.s.link_up);
83 if (lio_iq_is_full(oct, iq_no)) {
84 /* Defer sending if queue is full */
85 lio_dev_dbg(oct, "Transmit failed iq:%d full\n", iq_no);
91 status = bus_dmamap_load_mbuf_sg(iq->txtag, map, *m_headp, segs, &nsegs,
93 if (status == EFBIG) {
96 m = m_defrag(*m_headp, M_NOWAIT);
98 stats->mbuf_defrag_failed++;
103 status = bus_dmamap_load_mbuf_sg(iq->txtag, map,
104 *m_headp, segs, &nsegs,
108 if (status == ENOMEM) {
111 stats->tx_dmamap_fail++;
112 lio_dev_dbg(oct, "bus_dmamap_load_mbuf_sg failed with error %d. iq:%d",
119 /* Info used to unmap and free the buffers. */
120 finfo = &tx_buf->finfo;
124 /* Prepare the attributes for the data to be passed to OSI. */
125 bzero(&ndata, sizeof(struct lio_data_pkt));
127 ndata.buf = (void *)finfo;
129 ndata.datasize = m_head->m_pkthdr.len;
131 cmdsetup.cmd_setup64 = 0;
132 cmdsetup.s.iq_no = iq_no;
134 if (m_head->m_pkthdr.csum_flags & CSUM_IP)
135 cmdsetup.s.ip_csum = 1;
137 if ((m_head->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) ||
138 (m_head->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)))
139 cmdsetup.s.transport_csum = 1;
142 cmdsetup.s.u.datasize = segs[0].ds_len;
143 lio_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
145 dptr = segs[0].ds_addr;
146 ndata.cmd.cmd3.dptr = dptr;
147 ndata.reqtype = LIO_REQTYPE_NORESP_NET;
150 struct lio_gather *g;
153 mtx_lock(&lio->glist_lock[iq_no]);
154 g = (struct lio_gather *)
155 lio_delete_first_node(&lio->ghead[iq_no]);
156 mtx_unlock(&lio->glist_lock[iq_no]);
160 "Transmit scatter gather: glist null!\n");
164 cmdsetup.s.gather = 1;
165 cmdsetup.s.u.gatherptrs = nsegs;
166 lio_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
168 bzero(g->sg, g->sg_size);
172 g->sg[(i >> 2)].ptr[(i & 3)] = segs[i].ds_addr;
173 lio_add_sg_size(&g->sg[(i >> 2)], segs[i].ds_len,
178 dptr = g->sg_dma_ptr;
180 ndata.cmd.cmd3.dptr = dptr;
183 ndata.reqtype = LIO_REQTYPE_NORESP_NET_SG;
186 irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh;
187 tx_info = (union lio_tx_info *)&ndata.cmd.cmd3.ossp[0];
189 if (m_head->m_pkthdr.csum_flags & (CSUM_IP_TSO | CSUM_IP6_TSO)) {
190 tx_info->s.gso_size = m_head->m_pkthdr.tso_segsz;
191 tx_info->s.gso_segs = howmany(m_head->m_pkthdr.len,
192 m_head->m_pkthdr.tso_segsz);
196 /* HW insert VLAN tag */
197 if (m_head->m_flags & M_VLANTAG) {
198 irh->priority = m_head->m_pkthdr.ether_vtag >> 13;
199 irh->vlan = m_head->m_pkthdr.ether_vtag & 0xfff;
202 status = lio_send_data_pkt(oct, &ndata);
203 if (status == LIO_IQ_SEND_FAILED)
206 if (tx_info->s.gso_segs)
207 stats->tx_done += tx_info->s.gso_segs;
211 stats->tx_tot_bytes += ndata.datasize;
220 lio_dev_err(oct, "IQ%d Transmit dropped: %llu\n", iq_no,
221 LIO_CAST64(stats->tx_dropped));
230 lio_mq_start_locked(if_t ifp, struct lio_instr_queue *iq)
232 struct lio *lio = if_getsoftc(ifp);
236 if (((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) ||
237 (!lio->linfo.link.s.link_up))
240 /* Process the queue */
241 while ((next = drbr_peek(ifp, iq->br)) != NULL) {
242 err = lio_xmit(lio, iq, &next);
245 drbr_advance(ifp, iq->br);
247 drbr_putback(ifp, iq->br, next);
250 drbr_advance(ifp, iq->br);
251 /* Send a copy of the frame to the BPF listener */
252 ETHER_BPF_MTAP(ifp, next);
253 if (((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) ||
254 (!lio->linfo.link.s.link_up))
262 lio_mq_start(if_t ifp, struct mbuf *m)
264 struct lio *lio = if_getsoftc(ifp);
265 struct octeon_device *oct = lio->oct_dev;
266 struct lio_instr_queue *iq;
272 if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
274 if (rss_hash2bucket(m->m_pkthdr.flowid, M_HASHTYPE_GET(m),
276 i = bucket_id % oct->num_iqs;
277 if (bucket_id > oct->num_iqs)
279 "bucket_id (%d) > num_iqs (%d)\n",
280 bucket_id, oct->num_iqs);
283 i = m->m_pkthdr.flowid % oct->num_iqs;
285 i = curcpu % oct->num_iqs;
287 iq = oct->instr_queue[i];
289 err = drbr_enqueue(ifp, iq->br, m);
293 if (mtx_trylock(&iq->enq_lock)) {
294 lio_mq_start_locked(ifp, iq);
295 mtx_unlock(&iq->enq_lock);
304 struct lio *lio = if_getsoftc(ifp);
305 struct octeon_device *oct = lio->oct_dev;
306 struct lio_instr_queue *iq;
310 for (i = 0; i < LIO_MAX_INSTR_QUEUES(oct); i++) {
311 if (!(oct->io_qmask.iq & BIT_ULL(i)))
314 iq = oct->instr_queue[i];
316 mtx_lock(&iq->enq_lock);
317 while ((m = buf_ring_dequeue_sc(iq->br)) != NULL)
320 mtx_unlock(&iq->enq_lock);