15df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar/* 25df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * Copyright 2008 Cisco Systems, Inc. All rights reserved. 35df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * Copyright 2007 Nuova Systems, Inc. All rights reserved. 45df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * 55df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * This program is free software; you may redistribute it and/or modify 65df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * it under the terms of the GNU General Public License as published by 75df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * the Free Software Foundation; version 2 of the License. 85df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * 95df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * SOFTWARE. 175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar */ 185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#ifndef _VNIC_WQ_H_ 195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define _VNIC_WQ_H_ 205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/pci.h> 225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_dev.h" 235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_cq.h" 245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar/* 265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * These defines avoid symbol clash between fnic and enic (Cisco 10G Eth 275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * Driver) when both are built with CONFIG options =y 285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar */ 295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_desc_avail fnic_wq_desc_avail 305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_desc_used fnic_wq_desc_used 315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_next_desc fni_cwq_next_desc 325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_post fnic_wq_post 335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_service fnic_wq_service 345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_free fnic_wq_free 355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_alloc fnic_wq_alloc 365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_init fnic_wq_init 375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_error_status fnic_wq_error_status 385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_enable fnic_wq_enable 395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_disable fnic_wq_disable 405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define vnic_wq_clean fnic_wq_clean 415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar/* Work queue control */ 435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_wq_ctrl { 445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u64 ring_base; /* 0x00 */ 455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 ring_size; /* 0x08 */ 465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad0; 475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 posted_index; /* 0x10 */ 485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad1; 495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 cq_index; /* 0x18 */ 505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad2; 515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 enable; /* 0x20 */ 525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad3; 535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 running; /* 0x28 */ 545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad4; 555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 fetch_index; /* 0x30 */ 565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad5; 575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 dca_value; /* 0x38 */ 585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad6; 595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 error_interrupt_enable; /* 0x40 */ 605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad7; 615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 error_interrupt_offset; /* 0x48 */ 625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad8; 635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 error_status; /* 0x50 */ 645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar u32 pad9; 655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}; 665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_wq_buf { 685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *next; 695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar dma_addr_t dma_addr; 705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void *os_buf; 715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int len; 725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int index; 735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar int sop; 745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void *desc; 755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}; 765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar/* Break the vnic_wq_buf allocations into blocks of 64 entries */ 785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_WQ_BUF_BLK_ENTRIES 64 795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_WQ_BUF_BLK_SZ \ 805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar (VNIC_WQ_BUF_BLK_ENTRIES * sizeof(struct vnic_wq_buf)) 815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \ 825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES) 835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096) 845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_wq { 865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int index; 875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_dev *vdev; 885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */ 895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_dev_ring ring; 905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX]; 915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *to_use; 925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *to_clean; 935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int pkts_outstanding; 945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}; 955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq) 975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{ 985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar /* how many does SW own? */ 995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar return wq->ring.desc_avail; 1005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar} 1015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq) 1035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{ 1045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar /* how many does HW own? */ 1055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar return wq->ring.desc_count - wq->ring.desc_avail - 1; 1065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar} 1075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic inline void *vnic_wq_next_desc(struct vnic_wq *wq) 1095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{ 1105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar return wq->to_use->desc; 1115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar} 1125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic inline void vnic_wq_post(struct vnic_wq *wq, 1145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void *os_buf, dma_addr_t dma_addr, 1155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int len, int sop, int eop) 1165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{ 1175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *buf = wq->to_use; 1185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf->sop = sop; 1205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf->os_buf = eop ? os_buf : NULL; 1215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf->dma_addr = dma_addr; 1225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf->len = len; 1235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf = buf->next; 1255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar if (eop) { 1265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar /* Adding write memory barrier prevents compiler and/or CPU 1275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * reordering, thus avoiding descriptor posting before 1285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * descriptor is initialized. Otherwise, hardware can read 1295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * stale descriptor fields. 1305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar */ 1315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar wmb(); 1325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar iowrite32(buf->index, &wq->ctrl->posted_index); 1335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar } 1345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar wq->to_use = buf; 1355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar wq->ring.desc_avail--; 1375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar} 1385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic inline void vnic_wq_service(struct vnic_wq *wq, 1405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct cq_desc *cq_desc, u16 completed_index, 1415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void (*buf_service)(struct vnic_wq *wq, 1425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque), 1435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void *opaque) 1445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{ 1455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar struct vnic_wq_buf *buf; 1465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf = wq->to_clean; 1485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar while (1) { 1495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar (*buf_service)(wq, cq_desc, buf, opaque); 1515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar wq->ring.desc_avail++; 1535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar wq->to_clean = buf->next; 1555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar if (buf->index == completed_index) 1575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar break; 1585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar buf = wq->to_clean; 1605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar } 1615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar} 1625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_wq_free(struct vnic_wq *wq); 1645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, 1655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int desc_count, unsigned int desc_size); 1665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, 1675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int error_interrupt_enable, 1685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar unsigned int error_interrupt_offset); 1695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarunsigned int vnic_wq_error_status(struct vnic_wq *wq); 1705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_wq_enable(struct vnic_wq *wq); 1715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_wq_disable(struct vnic_wq *wq); 1725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_wq_clean(struct vnic_wq *wq, 1735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)); 1745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar 1755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#endif /* _VNIC_WQ_H_ */ 176