1 /****************************************************************************
2 * Copyright 2002-2005: Level 5 Networks Inc.
3 * Copyright 2005-2008: Solarflare Communications Inc,
4 * 9501 Jeronimo Road, Suite 250,
5 * Irvine, CA 92618, USA
7 * Maintained by Solarflare Communications
8 * <linux-xen-drivers@solarflare.com>
9 * <onload-dev@solarflare.com>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation, incorporated herein by reference.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 ****************************************************************************
28 * \brief Falcon-specific VI
32 #include "ef_vi_internal.h"
35 #define EFVI_FALCON_DMA_TX_FRAG 1
38 /* TX descriptor for both physical and virtual packet transfers */
41 } ef_vi_falcon_dma_tx_buf_desc;
42 typedef ef_vi_falcon_dma_tx_buf_desc ef_vi_falcon_dma_tx_phys_desc;
45 /* RX descriptor for physical addressed transfers */
48 } ef_vi_falcon_dma_rx_phys_desc;
51 /* RX descriptor for virtual packet transfers */
54 } ef_vi_falcon_dma_rx_buf_desc;
56 /* Buffer table index */
57 typedef uint32_t ef_vi_buffer_addr_t;
59 ef_vi_inline int64_t dma_addr_to_u46(int64_t src_dma_addr)
61 return (src_dma_addr & __FALCON_MASK(46, int64_t));
64 /*! Setup a physical address based descriptor with a specified length */
66 __falcon_dma_rx_calc_ip_phys(ef_vi_dma_addr_t dest_pa,
67 ef_vi_falcon_dma_rx_phys_desc *desc,
70 int region = 0; /* TODO fixme */
71 int64_t dest = dma_addr_to_u46(dest_pa); /* lower 46 bits */
73 DWCHCK(__DW2(RX_KER_BUF_SIZE_LBN), RX_KER_BUF_SIZE_WIDTH);
74 DWCHCK(__DW2(RX_KER_BUF_REGION_LBN),RX_KER_BUF_REGION_WIDTH);
76 LWCHK(RX_KER_BUF_ADR_LBN, RX_KER_BUF_ADR_WIDTH);
78 RANGECHCK(bytes, RX_KER_BUF_SIZE_WIDTH);
79 RANGECHCK(region, RX_KER_BUF_REGION_WIDTH);
83 desc->dword[1] = ((bytes << __DW2(RX_KER_BUF_SIZE_LBN)) |
84 (region << __DW2(RX_KER_BUF_REGION_LBN)) |
87 RX_KER_BUF_ADR_WIDTH)));
89 desc->dword[0] = LOW(dest,
91 RX_KER_BUF_ADR_WIDTH);
94 /*! Setup a virtual buffer descriptor for an IPMODE transfer */
96 __falcon_dma_tx_calc_ip_buf(unsigned buf_id, unsigned buf_ofs, unsigned bytes,
98 ef_vi_falcon_dma_tx_buf_desc *desc)
100 DWCHCK(__DW2(TX_USR_PORT_LBN), TX_USR_PORT_WIDTH);
101 DWCHCK(__DW2(TX_USR_CONT_LBN), TX_USR_CONT_WIDTH);
102 DWCHCK(__DW2(TX_USR_BYTE_CNT_LBN), TX_USR_BYTE_CNT_WIDTH);
103 LWCHK(RX_KER_BUF_ADR_LBN, RX_KER_BUF_ADR_WIDTH);
104 DWCHCK(TX_USR_BYTE_OFS_LBN, TX_USR_BYTE_OFS_WIDTH);
106 RANGECHCK(bytes, TX_USR_BYTE_CNT_WIDTH);
107 RANGECHCK(port, TX_USR_PORT_WIDTH);
108 RANGECHCK(frag, TX_USR_CONT_WIDTH);
109 RANGECHCK(buf_id, TX_USR_BUF_ID_WIDTH);
110 RANGECHCK(buf_ofs, TX_USR_BYTE_OFS_WIDTH);
114 desc->dword[1] = ((port << __DW2(TX_USR_PORT_LBN)) |
115 (frag << __DW2(TX_USR_CONT_LBN)) |
116 (bytes << __DW2(TX_USR_BYTE_CNT_LBN)) |
119 TX_USR_BUF_ID_WIDTH)));
121 desc->dword[0] = ((LOW(buf_id,
123 (TX_USR_BUF_ID_WIDTH))) |
124 (buf_ofs << TX_USR_BYTE_OFS_LBN));
128 falcon_dma_tx_calc_ip_buf_4k(unsigned buf_vaddr, unsigned bytes,
130 ef_vi_falcon_dma_tx_buf_desc *desc)
132 /* TODO FIXME [buf_vaddr] consists of the buffer index in the
133 ** high bits, and an offset in the low bits. Assumptions
134 ** permate the code that these can be rolled into one 32bit
135 ** value, so this is currently preserved for Falcon. But we
136 ** should change to support 8K pages
138 unsigned buf_id = EFVI_FALCON_BUFFER_4K_PAGE(buf_vaddr);
139 unsigned buf_ofs = EFVI_FALCON_BUFFER_4K_OFF(buf_vaddr);
141 __falcon_dma_tx_calc_ip_buf( buf_id, buf_ofs, bytes, port, frag, desc);
145 falcon_dma_tx_calc_ip_buf(unsigned buf_vaddr, unsigned bytes, int port,
146 int frag, ef_vi_falcon_dma_tx_buf_desc *desc)
148 falcon_dma_tx_calc_ip_buf_4k(buf_vaddr, bytes, port, frag, desc);
151 /*! Setup a virtual buffer based descriptor */
153 __falcon_dma_rx_calc_ip_buf(unsigned buf_id, unsigned buf_ofs,
154 ef_vi_falcon_dma_rx_buf_desc *desc)
156 /* check alignment of buffer offset and pack */
157 ef_assert((buf_ofs & 0x1) == 0);
161 DWCHCK(RX_USR_2BYTE_OFS_LBN, RX_USR_2BYTE_OFS_WIDTH);
162 DWCHCK(RX_USR_BUF_ID_LBN, RX_USR_BUF_ID_WIDTH);
164 RANGECHCK(buf_ofs, RX_USR_2BYTE_OFS_WIDTH);
165 RANGECHCK(buf_id, RX_USR_BUF_ID_WIDTH);
169 desc->dword[0] = ((buf_ofs << RX_USR_2BYTE_OFS_LBN) |
170 (buf_id << RX_USR_BUF_ID_LBN));
174 falcon_dma_rx_calc_ip_buf_4k(unsigned buf_vaddr,
175 ef_vi_falcon_dma_rx_buf_desc *desc)
177 /* TODO FIXME [buf_vaddr] consists of the buffer index in the
178 ** high bits, and an offset in the low bits. Assumptions
179 ** permeate the code that these can be rolled into one 32bit
180 ** value, so this is currently preserved for Falcon. But we
181 ** should change to support 8K pages
183 unsigned buf_id = EFVI_FALCON_BUFFER_4K_PAGE(buf_vaddr);
184 unsigned buf_ofs = EFVI_FALCON_BUFFER_4K_OFF(buf_vaddr);
186 __falcon_dma_rx_calc_ip_buf(buf_id, buf_ofs, desc);
190 falcon_dma_rx_calc_ip_buf(unsigned buf_vaddr,
191 ef_vi_falcon_dma_rx_buf_desc *desc)
193 falcon_dma_rx_calc_ip_buf_4k(buf_vaddr, desc);
197 ef_vi_inline ef_vi_dma_addr_t ef_physaddr(ef_addr efaddr)
199 return (ef_vi_dma_addr_t) efaddr;
203 /*! Convert between an ef_addr and a buffer table index
204 ** Assert that this was not a physical address
206 ef_vi_inline ef_vi_buffer_addr_t ef_bufaddr(ef_addr efaddr)
208 ef_assert(efaddr < ((uint64_t)1 << 32) );
210 return (ef_vi_buffer_addr_t) efaddr;
214 /*! Setup an physical address based descriptor for an IPMODE transfer */
216 falcon_dma_tx_calc_ip_phys(ef_vi_dma_addr_t src_dma_addr, unsigned bytes,
218 ef_vi_falcon_dma_tx_phys_desc *desc)
221 int region = 0; /* FIXME */
222 int64_t src = dma_addr_to_u46(src_dma_addr); /* lower 46 bits */
224 DWCHCK(__DW2(TX_KER_PORT_LBN), TX_KER_PORT_WIDTH);
225 DWCHCK(__DW2(TX_KER_CONT_LBN), TX_KER_CONT_WIDTH);
226 DWCHCK(__DW2(TX_KER_BYTE_CNT_LBN), TX_KER_BYTE_CNT_WIDTH);
227 DWCHCK(__DW2(TX_KER_BUF_REGION_LBN),TX_KER_BUF_REGION_WIDTH);
229 LWCHK(TX_KER_BUF_ADR_LBN, TX_KER_BUF_ADR_WIDTH);
231 RANGECHCK(port, TX_KER_PORT_WIDTH);
232 RANGECHCK(frag, TX_KER_CONT_WIDTH);
233 RANGECHCK(bytes, TX_KER_BYTE_CNT_WIDTH);
234 RANGECHCK(region, TX_KER_BUF_REGION_WIDTH);
236 desc->dword[1] = ((port << __DW2(TX_KER_PORT_LBN)) |
237 (frag << __DW2(TX_KER_CONT_LBN)) |
238 (bytes << __DW2(TX_KER_BYTE_CNT_LBN)) |
239 (region << __DW2(TX_KER_BUF_REGION_LBN)) |
242 TX_KER_BUF_ADR_WIDTH)));
244 ef_assert_equal(TX_KER_BUF_ADR_LBN, 0);
245 desc->dword[0] = (uint32_t) src_dma_addr;
249 void falcon_vi_init(ef_vi* vi, void* vvis)
251 struct vi_mappings *vm = (struct vi_mappings*)vvis;
256 ef_assert_equal(vm->signature, VI_MAPPING_SIGNATURE);
257 ef_assert_equal(vm->nic_type.arch, EF_VI_ARCH_FALCON);
259 /* Initialise masks to zero, so that ef_vi_state_init() will
260 ** not do any harm when we don't have DMA queues. */
261 vi->vi_rxq.mask = vi->vi_txq.mask = 0;
263 /* Used for BUG5391_WORKAROUND. */
264 vi->vi_txq.misalign_mask = 0;
266 /* Initialise doorbell addresses to a distinctive small value
267 ** which will cause a segfault, to trap doorbell pushes to VIs
268 ** without DMA queues. */
269 vi->vi_rxq.doorbell = vi->vi_txq.doorbell = (ef_vi_ioaddr_t)0xdb;
271 ids = (uint16_t*) (vi->ep_state + 1);
273 if( vm->tx_queue_capacity ) {
274 vi->vi_txq.mask = vm->tx_queue_capacity - 1;
275 vi->vi_txq.doorbell = vm->tx_bell + 12;
276 vi->vi_txq.descriptors = vm->tx_dma_falcon;
277 vi->vi_txq.ids = ids;
278 ids += vi->vi_txq.mask + 1;
279 /* Check that the id fifo fits in the space allocated. */
280 ef_assert_le((char*) (vi->vi_txq.ids + vm->tx_queue_capacity),
282 + ef_vi_calc_state_bytes(vm->rx_queue_capacity,
283 vm->tx_queue_capacity));
285 if( vm->rx_queue_capacity ) {
286 vi->vi_rxq.mask = vm->rx_queue_capacity - 1;
287 vi->vi_rxq.doorbell = vm->rx_bell + 12;
288 vi->vi_rxq.descriptors = vm->rx_dma_falcon;
289 vi->vi_rxq.ids = ids;
290 /* Check that the id fifo fits in the space allocated. */
291 ef_assert_le((char*) (vi->vi_rxq.ids + vm->rx_queue_capacity),
293 + ef_vi_calc_state_bytes(vm->rx_queue_capacity,
294 vm->tx_queue_capacity));
297 if( vm->nic_type.variant == 'A' ) {
298 vi->vi_txq.misalign_mask = 15; /* BUG5391_WORKAROUND */
299 vi->vi_flags |= EF_VI_BUG5692_WORKAROUND;
304 int ef_vi_transmitv_init(ef_vi* vi, const ef_iovec* iov, int iov_len,
305 ef_request_id dma_id)
307 ef_vi_txq* q = &vi->vi_txq;
308 ef_vi_txq_state* qs = &vi->ep_state->txq;
309 ef_vi_falcon_dma_tx_buf_desc* dp;
310 unsigned len, dma_len, di;
311 unsigned added_save = qs->added;
313 unsigned last_len = 0;
315 ef_assert(iov_len > 0);
317 ef_assert_equal((dma_id & EF_REQUEST_ID_MASK), dma_id);
318 ef_assert_nequal(dma_id, 0xffff);
320 dma_addr = iov->iov_base;
323 if( vi->vi_flags & EF_VI_ISCSI_TX_DDIG ) {
324 /* Last 4 bytes of placeholder for digest must be
327 last_len = iov[iov_len - 1].iov_len;
328 if( last_len <= 4 ) {
329 ef_assert(iov_len > 1);
331 last_len = iov[iov_len - 1].iov_len - (4 - last_len);
334 last_len = iov[iov_len - 1].iov_len - 4;
341 if( qs->added - qs->removed >= q->mask ) {
342 qs->added = added_save;
346 dma_len = (~((unsigned) dma_addr) & 0xfff) + 1;
347 if( dma_len > len ) dma_len = len;
348 { /* BUG5391_WORKAROUND */
350 (unsigned) dma_addr & q->misalign_mask;
351 if( misalign && dma_len + misalign > 512 )
352 dma_len = 512 - misalign;
355 di = qs->added++ & q->mask;
356 dp = (ef_vi_falcon_dma_tx_buf_desc*) q->descriptors + di;
357 if( vi->vi_flags & EF_VI_TX_PHYS_ADDR )
358 falcon_dma_tx_calc_ip_phys
359 (ef_physaddr(dma_addr), dma_len, /*port*/ 0,
360 (iov_len == 1 && dma_len == len) ? 0 :
361 EFVI_FALCON_DMA_TX_FRAG, dp);
363 falcon_dma_tx_calc_ip_buf
364 (ef_bufaddr(dma_addr), dma_len, /*port*/ 0,
365 (iov_len == 1 && dma_len == len) ? 0 :
366 EFVI_FALCON_DMA_TX_FRAG, dp);
372 if( --iov_len == 0 ) break;
374 dma_addr = iov->iov_base;
376 if( (vi->vi_flags & EF_VI_ISCSI_TX_DDIG) &&
382 q->ids[di] = (uint16_t) dma_id;
387 void ef_vi_transmit_push(ef_vi* vi)
390 writel((vi->ep_state->txq.added & vi->vi_txq.mask) <<
391 __DW4(TX_DESC_WPTR_LBN),
392 vi->vi_txq.doorbell);
396 /*! The value of initial_rx_bytes is used to set RX_KER_BUF_SIZE in an initial
397 ** receive descriptor here if physical addressing is being used. A value of
398 ** zero represents 16384 bytes. This is okay, because caller must provide a
399 ** buffer than is > MTU, and mac should filter anything bigger than that.
401 int ef_vi_receive_init(ef_vi* vi, ef_addr addr, ef_request_id dma_id,
402 int initial_rx_bytes)
404 ef_vi_rxq* q = &vi->vi_rxq;
405 ef_vi_rxq_state* qs = &vi->ep_state->rxq;
408 if( ef_vi_receive_space(vi) ) {
409 di = qs->added++ & q->mask;
410 ef_assert_equal(q->ids[di], 0xffff);
411 q->ids[di] = (uint16_t) dma_id;
413 if( ! (vi->vi_flags & EF_VI_RX_PHYS_ADDR) ) {
414 ef_vi_falcon_dma_rx_buf_desc* dp;
415 dp = (ef_vi_falcon_dma_rx_buf_desc*)
417 falcon_dma_rx_calc_ip_buf(ef_bufaddr(addr), dp);
420 ef_vi_falcon_dma_rx_phys_desc* dp;
421 dp = (ef_vi_falcon_dma_rx_phys_desc*)
423 __falcon_dma_rx_calc_ip_phys(addr, dp,
434 int ef_vi_receive_post(ef_vi* vi, ef_addr addr, ef_request_id dma_id)
436 int rc = ef_vi_receive_init(vi, addr, dma_id, 0);
437 if( rc == 0 ) ef_vi_receive_push(vi);
442 void ef_vi_receive_push(ef_vi* vi)
445 writel ((vi->ep_state->rxq.added & vi->vi_rxq.mask) <<
446 __DW4(RX_DESC_WPTR_LBN),
447 vi->vi_rxq.doorbell);
451 ef_request_id ef_vi_receive_done(const ef_vi* vi, const ef_event* ef_ev)
453 const ef_vi_qword* ev = EF_GET_HW_EV_PTR(*ef_ev);
454 unsigned di = ev->u32[0] & vi->vi_rxq.mask;
457 ef_assert(EF_EVENT_TYPE(*ef_ev) == EF_EVENT_TYPE_RX ||
458 EF_EVENT_TYPE(*ef_ev) == EF_EVENT_TYPE_RX_DISCARD);
460 /* Detect spurious / duplicate RX events. We may need to modify this
461 ** code so that we are robust if they happen. */
462 ef_assert_equal(di, vi->ep_state->rxq.removed & vi->vi_rxq.mask);
464 /* We only support 1 port: so events should be in order. */
465 ef_assert(vi->vi_rxq.ids[di] != 0xffff);
467 rq_id = vi->vi_rxq.ids[di];
468 vi->vi_rxq.ids[di] = 0xffff;
469 ++vi->ep_state->rxq.removed;