1 /* 2 * Copyright 2008 Cisco Systems, Inc. All rights reserved. 3 * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4 * 5 * This program is free software; you may redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; version 2 of the License. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 10 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 11 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 12 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 13 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 14 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 15 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 16 * SOFTWARE. 17 */ 18 #ifndef _VNIC_WQ_H_ 19 #define _VNIC_WQ_H_ 20 21 #include <linux/pci.h> 22 #include "vnic_dev.h" 23 #include "vnic_cq.h" 24 25 /* 26 * These defines avoid symbol clash between fnic and enic (Cisco 10G Eth 27 * Driver) when both are built with CONFIG options =y 28 */ 29 #define vnic_wq_desc_avail fnic_wq_desc_avail 30 #define vnic_wq_desc_used fnic_wq_desc_used 31 #define vnic_wq_next_desc fni_cwq_next_desc 32 #define vnic_wq_post fnic_wq_post 33 #define vnic_wq_service fnic_wq_service 34 #define vnic_wq_free fnic_wq_free 35 #define vnic_wq_alloc fnic_wq_alloc 36 #define vnic_wq_devcmd2_alloc fnic_wq_devcmd2_alloc 37 #define vnic_wq_init_start fnic_wq_init_start 38 #define vnic_wq_init fnic_wq_init 39 #define vnic_wq_error_status fnic_wq_error_status 40 #define vnic_wq_enable fnic_wq_enable 41 #define vnic_wq_disable fnic_wq_disable 42 #define vnic_wq_clean fnic_wq_clean 43 44 /* Work queue control */ 45 struct vnic_wq_ctrl { 46 u64 ring_base; /* 0x00 */ 47 u32 ring_size; /* 0x08 */ 48 u32 pad0; 49 u32 posted_index; /* 0x10 */ 50 u32 pad1; 51 u32 cq_index; /* 0x18 */ 52 u32 pad2; 53 u32 enable; /* 0x20 */ 54 u32 pad3; 55 u32 running; /* 0x28 */ 56 u32 pad4; 57 u32 fetch_index; /* 0x30 */ 58 u32 pad5; 59 u32 dca_value; /* 0x38 */ 60 u32 pad6; 61 u32 error_interrupt_enable; /* 0x40 */ 62 u32 pad7; 63 u32 error_interrupt_offset; /* 0x48 */ 64 u32 pad8; 65 u32 error_status; /* 0x50 */ 66 u32 pad9; 67 }; 68 69 struct vnic_wq_buf { 70 struct vnic_wq_buf *next; 71 dma_addr_t dma_addr; 72 void *os_buf; 73 unsigned int len; 74 unsigned int index; 75 int sop; 76 void *desc; 77 }; 78 79 /* Break the vnic_wq_buf allocations into blocks of 64 entries */ 80 #define VNIC_WQ_BUF_BLK_ENTRIES 64 81 #define VNIC_WQ_BUF_BLK_SZ \ 82 (VNIC_WQ_BUF_BLK_ENTRIES * sizeof(struct vnic_wq_buf)) 83 #define VNIC_WQ_BUF_BLKS_NEEDED(entries) \ 84 DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES) 85 #define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096) 86 87 struct vnic_wq { 88 unsigned int index; 89 struct vnic_dev *vdev; 90 struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */ 91 struct vnic_dev_ring ring; 92 struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX]; 93 struct vnic_wq_buf *to_use; 94 struct vnic_wq_buf *to_clean; 95 unsigned int pkts_outstanding; 96 }; 97 98 static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq) 99 { 100 /* how many does SW own? */ 101 return wq->ring.desc_avail; 102 } 103 104 static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq) 105 { 106 /* how many does HW own? */ 107 return wq->ring.desc_count - wq->ring.desc_avail - 1; 108 } 109 110 static inline void *vnic_wq_next_desc(struct vnic_wq *wq) 111 { 112 return wq->to_use->desc; 113 } 114 115 static inline void vnic_wq_post(struct vnic_wq *wq, 116 void *os_buf, dma_addr_t dma_addr, 117 unsigned int len, int sop, int eop) 118 { 119 struct vnic_wq_buf *buf = wq->to_use; 120 121 buf->sop = sop; 122 buf->os_buf = eop ? os_buf : NULL; 123 buf->dma_addr = dma_addr; 124 buf->len = len; 125 126 buf = buf->next; 127 if (eop) { 128 /* Adding write memory barrier prevents compiler and/or CPU 129 * reordering, thus avoiding descriptor posting before 130 * descriptor is initialized. Otherwise, hardware can read 131 * stale descriptor fields. 132 */ 133 wmb(); 134 iowrite32(buf->index, &wq->ctrl->posted_index); 135 } 136 wq->to_use = buf; 137 138 wq->ring.desc_avail--; 139 } 140 141 static inline void vnic_wq_service(struct vnic_wq *wq, 142 struct cq_desc *cq_desc, u16 completed_index, 143 void (*buf_service)(struct vnic_wq *wq, 144 struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque), 145 void *opaque) 146 { 147 struct vnic_wq_buf *buf; 148 149 buf = wq->to_clean; 150 while (1) { 151 152 (*buf_service)(wq, cq_desc, buf, opaque); 153 154 wq->ring.desc_avail++; 155 156 wq->to_clean = buf->next; 157 158 if (buf->index == completed_index) 159 break; 160 161 buf = wq->to_clean; 162 } 163 } 164 165 void vnic_wq_free(struct vnic_wq *wq); 166 int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, 167 unsigned int desc_count, unsigned int desc_size); 168 int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, 169 unsigned int desc_count, unsigned int desc_size); 170 void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, 171 unsigned int fetch_index, unsigned int posted_index, 172 unsigned int error_interrupt_enable, 173 unsigned int error_interrupt_offset); 174 void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, 175 unsigned int error_interrupt_enable, 176 unsigned int error_interrupt_offset); 177 unsigned int vnic_wq_error_status(struct vnic_wq *wq); 178 void vnic_wq_enable(struct vnic_wq *wq); 179 int vnic_wq_disable(struct vnic_wq *wq); 180 void vnic_wq_clean(struct vnic_wq *wq, 181 void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)); 182 183 #endif /* _VNIC_WQ_H_ */ 184