Commit | Line | Data |
---|---|---|
f21fb3ed RV |
1 | /********************************************************************** |
2 | * Author: Cavium, Inc. | |
3 | * | |
4 | * Contact: support@cavium.com | |
5 | * Please include "LiquidIO" in the subject. | |
6 | * | |
7 | * Copyright (c) 2003-2015 Cavium, Inc. | |
8 | * | |
9 | * This file is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License, Version 2, as | |
11 | * published by the Free Software Foundation. | |
12 | * | |
13 | * This file is distributed in the hope that it will be useful, but | |
14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty | |
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or | |
16 | * NONINFRINGEMENT. See the GNU General Public License for more | |
17 | * details. | |
18 | * | |
19 | * This file may also be available under a different license from Cavium. | |
20 | * Contact Cavium, Inc. for more information | |
21 | **********************************************************************/ | |
22 | ||
23 | /*! \file octeon_network.h | |
24 | * \brief Host NIC Driver: Structure and Macro definitions used by NIC Module. | |
25 | */ | |
26 | ||
27 | #ifndef __OCTEON_NETWORK_H__ | |
28 | #define __OCTEON_NETWORK_H__ | |
29 | #include <linux/version.h> | |
30 | #include <linux/dma-mapping.h> | |
31 | #include <linux/ptp_clock_kernel.h> | |
32 | ||
33 | /** LiquidIO per-interface network private data */ | |
34 | struct lio { | |
35 | /** State of the interface. Rx/Tx happens only in the RUNNING state. */ | |
36 | atomic_t ifstate; | |
37 | ||
38 | /** Octeon Interface index number. This device will be represented as | |
39 | * oct<ifidx> in the system. | |
40 | */ | |
41 | int ifidx; | |
42 | ||
43 | /** Octeon Input queue to use to transmit for this network interface. */ | |
44 | int txq; | |
45 | ||
46 | /** Octeon Output queue from which pkts arrive | |
47 | * for this network interface. | |
48 | */ | |
49 | int rxq; | |
50 | ||
fcd2b5e3 RV |
51 | /** Guards each glist */ |
52 | spinlock_t *glist_lock; | |
f21fb3ed | 53 | |
fcd2b5e3 RV |
54 | /** Array of gather component linked lists */ |
55 | struct list_head *glist; | |
f21fb3ed RV |
56 | |
57 | /** Pointer to the NIC properties for the Octeon device this network | |
58 | * interface is associated with. | |
59 | */ | |
60 | struct octdev_props *octprops; | |
61 | ||
62 | /** Pointer to the octeon device structure. */ | |
63 | struct octeon_device *oct_dev; | |
64 | ||
65 | struct net_device *netdev; | |
66 | ||
67 | /** Link information sent by the core application for this interface. */ | |
68 | struct oct_link_info linfo; | |
69 | ||
70 | /** Size of Tx queue for this octeon device. */ | |
71 | u32 tx_qsize; | |
72 | ||
73 | /** Size of Rx queue for this octeon device. */ | |
74 | u32 rx_qsize; | |
75 | ||
76 | /** Size of MTU this octeon device. */ | |
77 | u32 mtu; | |
78 | ||
79 | /** msg level flag per interface. */ | |
80 | u32 msg_enable; | |
81 | ||
82 | /** Copy of Interface capabilities: TSO, TSO6, LRO, Chescksums . */ | |
83 | u64 dev_capability; | |
84 | ||
85 | /** Copy of beacaon reg in phy */ | |
86 | u32 phy_beacon_val; | |
87 | ||
88 | /** Copy of ctrl reg in phy */ | |
89 | u32 led_ctrl_val; | |
90 | ||
91 | /* PTP clock information */ | |
92 | struct ptp_clock_info ptp_info; | |
93 | struct ptp_clock *ptp_clock; | |
94 | s64 ptp_adjust; | |
95 | ||
96 | /* for atomic access to Octeon PTP reg and data struct */ | |
97 | spinlock_t ptp_lock; | |
98 | ||
99 | /* Interface info */ | |
100 | u32 intf_open; | |
101 | ||
102 | /* work queue for txq status */ | |
103 | struct cavium_wq txq_status_wq; | |
104 | ||
105 | }; | |
106 | ||
107 | #define LIO_SIZE (sizeof(struct lio)) | |
108 | #define GET_LIO(netdev) ((struct lio *)netdev_priv(netdev)) | |
109 | ||
110 | /** | |
111 | * \brief Enable or disable feature | |
112 | * @param netdev pointer to network device | |
113 | * @param cmd Command that just requires acknowledgment | |
114 | */ | |
115 | int liquidio_set_feature(struct net_device *netdev, int cmd); | |
116 | ||
117 | /** | |
118 | * \brief Link control command completion callback | |
119 | * @param nctrl_ptr pointer to control packet structure | |
120 | * | |
121 | * This routine is called by the callback function when a ctrl pkt sent to | |
122 | * core app completes. The nctrl_ptr contains a copy of the command type | |
123 | * and data sent to the core app. This routine is only called if the ctrl | |
124 | * pkt was sent successfully to the core app. | |
125 | */ | |
126 | void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr); | |
127 | ||
128 | /** | |
129 | * \brief Register ethtool operations | |
130 | * @param netdev pointer to network device | |
131 | */ | |
132 | void liquidio_set_ethtool_ops(struct net_device *netdev); | |
133 | ||
f21fb3ed RV |
134 | #define SKB_ADJ_MASK 0x3F |
135 | #define SKB_ADJ (SKB_ADJ_MASK + 1) | |
136 | ||
cabeb13b RV |
137 | #define MIN_SKB_SIZE 256 /* 8 bytes and more - 8 bytes for PTP */ |
138 | #define LIO_RXBUFFER_SZ 2048 | |
139 | ||
140 | static inline void | |
141 | *recv_buffer_alloc(struct octeon_device *oct, | |
142 | struct octeon_skb_page_info *pg_info) | |
143 | { | |
144 | struct page *page; | |
145 | struct sk_buff *skb; | |
146 | struct octeon_skb_page_info *skb_pg_info; | |
147 | ||
148 | page = alloc_page(GFP_ATOMIC | __GFP_COLD); | |
149 | if (unlikely(!page)) | |
150 | return NULL; | |
151 | ||
152 | skb = dev_alloc_skb(MIN_SKB_SIZE + SKB_ADJ); | |
153 | if (unlikely(!skb)) { | |
154 | __free_page(page); | |
155 | pg_info->page = NULL; | |
156 | return NULL; | |
157 | } | |
f21fb3ed RV |
158 | |
159 | if ((unsigned long)skb->data & SKB_ADJ_MASK) { | |
160 | u32 r = SKB_ADJ - ((unsigned long)skb->data & SKB_ADJ_MASK); | |
161 | ||
162 | skb_reserve(skb, r); | |
163 | } | |
164 | ||
cabeb13b RV |
165 | skb_pg_info = ((struct octeon_skb_page_info *)(skb->cb)); |
166 | /* Get DMA info */ | |
167 | pg_info->dma = dma_map_page(&oct->pci_dev->dev, page, 0, | |
168 | PAGE_SIZE, DMA_FROM_DEVICE); | |
169 | ||
170 | /* Mapping failed!! */ | |
171 | if (dma_mapping_error(&oct->pci_dev->dev, pg_info->dma)) { | |
172 | __free_page(page); | |
173 | dev_kfree_skb_any((struct sk_buff *)skb); | |
174 | pg_info->page = NULL; | |
175 | return NULL; | |
176 | } | |
177 | ||
178 | pg_info->page = page; | |
179 | pg_info->page_offset = 0; | |
180 | skb_pg_info->page = page; | |
181 | skb_pg_info->page_offset = 0; | |
182 | skb_pg_info->dma = pg_info->dma; | |
183 | ||
f21fb3ed RV |
184 | return (void *)skb; |
185 | } | |
186 | ||
cabeb13b RV |
187 | static inline void |
188 | *recv_buffer_fast_alloc(u32 size) | |
189 | { | |
190 | struct sk_buff *skb; | |
191 | struct octeon_skb_page_info *skb_pg_info; | |
192 | ||
193 | skb = dev_alloc_skb(size + SKB_ADJ); | |
194 | if (unlikely(!skb)) | |
195 | return NULL; | |
196 | ||
197 | if ((unsigned long)skb->data & SKB_ADJ_MASK) { | |
198 | u32 r = SKB_ADJ - ((unsigned long)skb->data & SKB_ADJ_MASK); | |
199 | ||
200 | skb_reserve(skb, r); | |
201 | } | |
202 | ||
203 | skb_pg_info = ((struct octeon_skb_page_info *)(skb->cb)); | |
204 | skb_pg_info->page = NULL; | |
205 | skb_pg_info->page_offset = 0; | |
206 | skb_pg_info->dma = 0; | |
207 | ||
208 | return skb; | |
209 | } | |
210 | ||
211 | static inline int | |
212 | recv_buffer_recycle(struct octeon_device *oct, void *buf) | |
213 | { | |
214 | struct octeon_skb_page_info *pg_info = buf; | |
215 | ||
216 | if (!pg_info->page) { | |
217 | dev_err(&oct->pci_dev->dev, "%s: pg_info->page NULL\n", | |
218 | __func__); | |
219 | return -ENOMEM; | |
220 | } | |
221 | ||
222 | if (unlikely(page_count(pg_info->page) != 1) || | |
223 | unlikely(page_to_nid(pg_info->page) != numa_node_id())) { | |
224 | dma_unmap_page(&oct->pci_dev->dev, | |
225 | pg_info->dma, (PAGE_SIZE << 0), | |
226 | DMA_FROM_DEVICE); | |
227 | pg_info->dma = 0; | |
228 | pg_info->page = NULL; | |
229 | pg_info->page_offset = 0; | |
230 | return -ENOMEM; | |
231 | } | |
232 | ||
233 | /* Flip to other half of the buffer */ | |
234 | if (pg_info->page_offset == 0) | |
235 | pg_info->page_offset = LIO_RXBUFFER_SZ; | |
236 | else | |
237 | pg_info->page_offset = 0; | |
238 | page_ref_inc(pg_info->page); | |
239 | ||
240 | return 0; | |
241 | } | |
242 | ||
243 | static inline void | |
244 | *recv_buffer_reuse(struct octeon_device *oct, void *buf) | |
245 | { | |
246 | struct octeon_skb_page_info *pg_info = buf, *skb_pg_info; | |
247 | struct sk_buff *skb; | |
248 | ||
249 | skb = dev_alloc_skb(MIN_SKB_SIZE + SKB_ADJ); | |
250 | if (unlikely(!skb)) { | |
251 | dma_unmap_page(&oct->pci_dev->dev, | |
252 | pg_info->dma, (PAGE_SIZE << 0), | |
253 | DMA_FROM_DEVICE); | |
254 | return NULL; | |
255 | } | |
256 | ||
257 | if ((unsigned long)skb->data & SKB_ADJ_MASK) { | |
258 | u32 r = SKB_ADJ - ((unsigned long)skb->data & SKB_ADJ_MASK); | |
259 | ||
260 | skb_reserve(skb, r); | |
261 | } | |
262 | ||
263 | skb_pg_info = ((struct octeon_skb_page_info *)(skb->cb)); | |
264 | skb_pg_info->page = pg_info->page; | |
265 | skb_pg_info->page_offset = pg_info->page_offset; | |
266 | skb_pg_info->dma = pg_info->dma; | |
267 | ||
268 | return skb; | |
269 | } | |
270 | ||
271 | static inline void | |
272 | recv_buffer_destroy(void *buffer, struct octeon_skb_page_info *pg_info) | |
273 | { | |
274 | struct sk_buff *skb = (struct sk_buff *)buffer; | |
275 | ||
276 | put_page(pg_info->page); | |
277 | pg_info->dma = 0; | |
278 | pg_info->page = NULL; | |
279 | pg_info->page_offset = 0; | |
280 | ||
281 | if (skb) | |
282 | dev_kfree_skb_any(skb); | |
283 | } | |
284 | ||
f21fb3ed | 285 | static inline void recv_buffer_free(void *buffer) |
cabeb13b RV |
286 | { |
287 | struct sk_buff *skb = (struct sk_buff *)buffer; | |
288 | struct octeon_skb_page_info *pg_info; | |
289 | ||
290 | pg_info = ((struct octeon_skb_page_info *)(skb->cb)); | |
291 | ||
292 | if (pg_info->page) { | |
293 | put_page(pg_info->page); | |
294 | pg_info->dma = 0; | |
295 | pg_info->page = NULL; | |
296 | pg_info->page_offset = 0; | |
297 | } | |
298 | ||
299 | dev_kfree_skb_any((struct sk_buff *)buffer); | |
300 | } | |
301 | ||
302 | static inline void | |
303 | recv_buffer_fast_free(void *buffer) | |
304 | { | |
305 | dev_kfree_skb_any((struct sk_buff *)buffer); | |
306 | } | |
307 | ||
308 | static inline void tx_buffer_free(void *buffer) | |
f21fb3ed RV |
309 | { |
310 | dev_kfree_skb_any((struct sk_buff *)buffer); | |
311 | } | |
312 | ||
313 | #define lio_dma_alloc(oct, size, dma_addr) \ | |
314 | dma_alloc_coherent(&oct->pci_dev->dev, size, dma_addr, GFP_KERNEL) | |
315 | #define lio_dma_free(oct, size, virt_addr, dma_addr) \ | |
316 | dma_free_coherent(&oct->pci_dev->dev, size, virt_addr, dma_addr) | |
317 | ||
cabeb13b RV |
318 | static inline |
319 | void *get_rbd(struct sk_buff *skb) | |
320 | { | |
321 | struct octeon_skb_page_info *pg_info; | |
322 | unsigned char *va; | |
323 | ||
324 | pg_info = ((struct octeon_skb_page_info *)(skb->cb)); | |
325 | va = page_address(pg_info->page) + pg_info->page_offset; | |
326 | ||
327 | return va; | |
328 | } | |
f21fb3ed RV |
329 | |
330 | static inline u64 | |
331 | lio_map_ring_info(struct octeon_droq *droq, u32 i) | |
332 | { | |
333 | dma_addr_t dma_addr; | |
334 | struct octeon_device *oct = droq->oct_dev; | |
335 | ||
336 | dma_addr = dma_map_single(&oct->pci_dev->dev, &droq->info_list[i], | |
337 | OCT_DROQ_INFO_SIZE, DMA_FROM_DEVICE); | |
338 | ||
339 | BUG_ON(dma_mapping_error(&oct->pci_dev->dev, dma_addr)); | |
340 | ||
341 | return (u64)dma_addr; | |
342 | } | |
343 | ||
344 | static inline void | |
345 | lio_unmap_ring_info(struct pci_dev *pci_dev, | |
346 | u64 info_ptr, u32 size) | |
347 | { | |
348 | dma_unmap_single(&pci_dev->dev, info_ptr, size, DMA_FROM_DEVICE); | |
349 | } | |
350 | ||
351 | static inline u64 | |
cabeb13b | 352 | lio_map_ring(void *buf) |
f21fb3ed RV |
353 | { |
354 | dma_addr_t dma_addr; | |
355 | ||
cabeb13b RV |
356 | struct sk_buff *skb = (struct sk_buff *)buf; |
357 | struct octeon_skb_page_info *pg_info; | |
f21fb3ed | 358 | |
cabeb13b RV |
359 | pg_info = ((struct octeon_skb_page_info *)(skb->cb)); |
360 | if (!pg_info->page) { | |
361 | pr_err("%s: pg_info->page NULL\n", __func__); | |
362 | WARN_ON(1); | |
363 | } | |
364 | ||
365 | /* Get DMA info */ | |
366 | dma_addr = pg_info->dma; | |
367 | if (!pg_info->dma) { | |
368 | pr_err("%s: ERROR it should be already available\n", | |
369 | __func__); | |
370 | WARN_ON(1); | |
371 | } | |
372 | dma_addr += pg_info->page_offset; | |
f21fb3ed RV |
373 | |
374 | return (u64)dma_addr; | |
375 | } | |
376 | ||
377 | static inline void | |
378 | lio_unmap_ring(struct pci_dev *pci_dev, | |
cabeb13b RV |
379 | u64 buf_ptr) |
380 | ||
f21fb3ed | 381 | { |
cabeb13b RV |
382 | dma_unmap_page(&pci_dev->dev, |
383 | buf_ptr, (PAGE_SIZE << 0), | |
384 | DMA_FROM_DEVICE); | |
f21fb3ed RV |
385 | } |
386 | ||
cabeb13b | 387 | static inline void *octeon_fast_packet_alloc(u32 size) |
f21fb3ed | 388 | { |
cabeb13b | 389 | return recv_buffer_fast_alloc(size); |
f21fb3ed RV |
390 | } |
391 | ||
392 | static inline void octeon_fast_packet_next(struct octeon_droq *droq, | |
393 | struct sk_buff *nicbuf, | |
394 | int copy_len, | |
395 | int idx) | |
396 | { | |
397 | memcpy(skb_put(nicbuf, copy_len), | |
398 | get_rbd(droq->recv_buf_list[idx].buffer), copy_len); | |
399 | } | |
400 | ||
401 | #endif |