|
|
1.1 root 1: /******************************************************************************
2: * Copyright (c) 2011 IBM Corporation
3: * All rights reserved.
4: * This program and the accompanying materials
5: * are made available under the terms of the BSD License
6: * which accompanies this distribution, and is available at
7: * http://www.opensource.org/licenses/bsd-license.php
8: *
9: * Contributors:
10: * IBM Corporation - initial implementation
11: *****************************************************************************/
12:
1.1.1.2 root 13: #include <stdint.h>
1.1 root 14: #include "netdriver_int.h"
15: #include "libhvcall.h"
16:
17: static snk_kernel_t *snk_kernel_interface;
18: static snk_module_t *snk_module_interface;
19: static unsigned int g_reg;
20:
21: #define printk(fmt...) do { snk_kernel_interface->print(fmt); } while(0)
22: #define malloc(args...) snk_kernel_interface->k_malloc(args)
23: #define malloc_aligned(args...) snk_kernel_interface->k_malloc_aligned(args)
24: #define free(args...) do { snk_kernel_interface->k_free(args); } while(0)
25:
26: #define dprintk(fmt...)
27: //#define dprintk(fmt...) printk(fmt)
28:
29: /* *** WARNING: We pass our addresses as-is as DMA addresses,
30: * we -do- rely on the forth code to have enabled TCE bypass
31: * on our device !
32: */
1.1.1.2 root 33: #define vaddr_to_dma(vaddr) ((uint64_t)vaddr)
1.1 root 34:
35: struct ibmveth_buf_desc_fields {
1.1.1.2 root 36: uint32_t flags_len;
1.1 root 37: #define IBMVETH_BUF_VALID 0x80000000
38: #define IBMVETH_BUF_TOGGLE 0x40000000
39: #define IBMVETH_BUF_NO_CSUM 0x02000000
40: #define IBMVETH_BUF_CSUM_GOOD 0x01000000
41: #define IBMVETH_BUF_LEN_MASK 0x00FFFFFF
1.1.1.2 root 42: uint32_t address;
1.1 root 43: };
44:
45: union ibmveth_buf_desc {
1.1.1.2 root 46: uint64_t desc;
1.1 root 47: struct ibmveth_buf_desc_fields fields;
48: };
49:
50: struct ibmveth_rx_q_entry {
1.1.1.2 root 51: uint32_t flags_off;
1.1 root 52: #define IBMVETH_RXQ_TOGGLE 0x80000000
53: #define IBMVETH_RXQ_TOGGLE_SHIFT 31
54: #define IBMVETH_RXQ_VALID 0x40000000
55: #define IBMVETH_RXQ_NO_CSUM 0x02000000
56: #define IBMVETH_RXQ_CSUM_GOOD 0x01000000
57: #define IBMVETH_RXQ_OFF_MASK 0x0000FFFF
58:
1.1.1.2 root 59: uint32_t length;
60: uint64_t correlator;
1.1 root 61: };
62:
63: static void *buffer_list;
64: static void *filter_list;
1.1.1.2 root 65: static uint64_t *rx_bufs;
66: static uint64_t *rx_bufs_aligned;
67: static uint32_t cur_rx_toggle;
68: static uint32_t cur_rx_index;
1.1 root 69:
70: #define RX_QUEUE_SIZE 16
71: #define RX_BUF_SIZE 2048
72: #define RX_BUF_MULT (RX_BUF_SIZE >> 3)
73:
74: static struct ibmveth_rx_q_entry *rx_queue;
75:
76: static char * memcpy( char *dest, const char *src, size_t n )
77: {
78: char *ret = dest;
79: while( n-- ) {
80: *dest++ = *src++;
81: }
82:
83: return( ret );
84: }
85:
1.1.1.2 root 86: static inline uint64_t *veth_get_rx_buf(unsigned int i)
1.1 root 87: {
88: return &rx_bufs_aligned[i * RX_BUF_MULT];
89: }
90:
91: static int veth_init(void)
92: {
93: char *mac_addr = snk_module_interface->mac_addr;
94: union ibmveth_buf_desc rxq_desc;
95: unsigned long rx_queue_len = sizeof(struct ibmveth_rx_q_entry) *
96: RX_QUEUE_SIZE;
97: unsigned int i;
98: long rc;
99:
100: dprintk("veth_init(%02x:%02x:%02x:%02x:%02x:%02x)\n",
101: mac_addr[0], mac_addr[1], mac_addr[2],
102: mac_addr[3], mac_addr[4], mac_addr[5]);
103:
104: if (snk_module_interface->running != 0)
105: return 0;
106:
107: cur_rx_toggle = IBMVETH_RXQ_TOGGLE;
108: cur_rx_index = 0;
109: buffer_list = malloc_aligned(8192, 4096);
110: filter_list = buffer_list + 4096;
111: rx_queue = malloc_aligned(rx_queue_len, 16);
112: rx_bufs = malloc(2048 * RX_QUEUE_SIZE + 4);
113: if (!buffer_list || !filter_list || !rx_queue || !rx_bufs) {
114: printk("veth: Failed to allocate memory !\n");
115: goto fail;
116: }
1.1.1.2 root 117: rx_bufs_aligned = (uint64_t *)(((uint64_t)rx_bufs | 3) + 1);
1.1 root 118: rxq_desc.fields.address = vaddr_to_dma(rx_queue);
119: rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | rx_queue_len;
120:
121: rc = h_register_logical_lan(g_reg,
122: vaddr_to_dma(buffer_list),
123: rxq_desc.desc,
124: vaddr_to_dma(filter_list),
1.1.1.2 root 125: (*(uint64_t *)mac_addr) >> 16);
1.1 root 126: if (rc != H_SUCCESS) {
127: printk("veth: Error %ld registering interface !\n", rc);
128: goto fail;
129: }
130: for (i = 0; i < RX_QUEUE_SIZE; i++) {
1.1.1.2 root 131: uint64_t *buf = veth_get_rx_buf(i);
1.1 root 132: union ibmveth_buf_desc desc;
1.1.1.2 root 133: *buf = (uint64_t)buf;
1.1 root 134: desc.fields.address = vaddr_to_dma(buf);
135: desc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
136: h_add_logical_lan_buffer(g_reg, desc.desc);
137: }
138:
139: snk_module_interface->running = 1;
140:
141: return 0;
142: fail:
143: if (filter_list)
144: free(filter_list);
145: if (buffer_list)
146: free(buffer_list);
147: if (rx_queue)
148: free(rx_queue);
149: if (rx_bufs)
150: free(rx_bufs);
151: return -1;
152: }
153:
154: static int veth_term(void)
155: {
156: dprintk("veth_term()\n");
157:
158: if (snk_module_interface->running == 0)
159: return 0;
160:
161: h_free_logical_lan(g_reg);
162:
163: if (filter_list)
164: free(filter_list);
165: if (buffer_list)
166: free(buffer_list);
167: if (rx_queue)
168: free(rx_queue);
169: if (rx_bufs)
170: free(rx_bufs);
171:
172: snk_module_interface->running = 0;
173:
174: return 0;
175: }
176:
177: static int veth_xmit(char *f_buffer_pc, int f_len_i)
178: {
179: union ibmveth_buf_desc tx_desc;
180: long rc;
181:
182: dprintk("veth_xmit(packet at %p, %d bytes)\n", f_buffer_pc, f_len_i);
183:
184: tx_desc.fields.address = vaddr_to_dma(f_buffer_pc);
185: tx_desc.fields.flags_len = IBMVETH_BUF_VALID | f_len_i;
186:
187: rc = hv_send_logical_lan(g_reg, tx_desc.desc, 0, 0, 0, 0, 0);
188: if (rc != H_SUCCESS) {
189: printk("veth: Error %ld sending packet !\n", rc);
190: return -1;
191: }
192:
193: return f_len_i;
194: }
195:
196: static int veth_receive(char *f_buffer_pc, int f_len_i)
197: {
198: int packet = 0;
199:
200: dprintk("veth_receive()\n");
201:
202: while(!packet) {
203: struct ibmveth_rx_q_entry *desc = &rx_queue[cur_rx_index];
204: union ibmveth_buf_desc bdesc;
205: void *buf;
206:
1.1.1.2 root 207: buf = (void *)desc->correlator;
208:
1.1 root 209: if ((desc->flags_off & IBMVETH_RXQ_TOGGLE) != cur_rx_toggle)
210: break;
211:
212: if (!(desc->flags_off & IBMVETH_RXQ_VALID))
213: goto recycle;
214: if (desc->length > f_len_i) {
215: printk("veth: Dropping too big packet [%d bytes]\n",
216: desc->length);
217: goto recycle;
218: }
219:
220: packet = desc->length;
221: memcpy(f_buffer_pc,
222: buf + (desc->flags_off & IBMVETH_RXQ_OFF_MASK), packet);
223: recycle:
224: bdesc.fields.address = vaddr_to_dma(buf);
225: bdesc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
226: h_add_logical_lan_buffer(g_reg, bdesc.desc);
227:
228: cur_rx_index = (cur_rx_index + 1) % RX_QUEUE_SIZE;
229: if (cur_rx_index == 0)
230: cur_rx_toggle ^= IBMVETH_RXQ_TOGGLE;
231: }
232:
233: return packet;
234: }
235:
236: static int veth_ioctl(int request, void* data)
237: {
238: dprintk("veth_ioctl()\n");
239:
240: return 0;
241: }
242:
243: static snk_module_t veth_interface = {
244: .version = 1,
245: .type = MOD_TYPE_NETWORK,
246: .running = 0,
247: .init = veth_init,
248: .term = veth_term,
249: .write = veth_xmit,
250: .read = veth_receive,
251: .ioctl = veth_ioctl
252: };
253:
254:
255: static int check_driver(vio_config_t *conf)
256: {
1.1.1.3 ! root 257: if (snk_kernel_interface->strcmp(conf->compat, "IBM,l-lan")) {
! 258: dprintk( "veth: netdevice not supported\n" );
1.1 root 259: return -1;
260: }
1.1.1.3 ! root 261:
! 262: g_reg = conf->reg[0];
! 263:
1.1 root 264: return 0;
265: }
266:
267: snk_module_t* veth_module_init(snk_kernel_t *snk_kernel_int, vio_config_t *conf)
268: {
269: snk_kernel_interface = snk_kernel_int;
270: snk_module_interface = &veth_interface;
271:
272: if (snk_kernel_int->version != snk_module_interface->version)
273: return 0;
274:
275: /* Check if this is the right driver */
276: if (check_driver(conf) < 0)
277: return 0;
278:
279: snk_module_interface->link_addr = module_init;
280: return snk_module_interface;
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.