|
|
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: ! 13: #include "types.h" ! 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: */ ! 33: #define vaddr_to_dma(vaddr) ((u64)vaddr) ! 34: ! 35: struct ibmveth_buf_desc_fields { ! 36: u32 flags_len; ! 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 ! 42: u32 address; ! 43: }; ! 44: ! 45: union ibmveth_buf_desc { ! 46: u64 desc; ! 47: struct ibmveth_buf_desc_fields fields; ! 48: }; ! 49: ! 50: struct ibmveth_rx_q_entry { ! 51: u32 flags_off; ! 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: ! 59: u32 length; ! 60: u64 correlator; ! 61: }; ! 62: ! 63: static void *buffer_list; ! 64: static void *filter_list; ! 65: static u64 *rx_bufs; ! 66: static u64 *rx_bufs_aligned; ! 67: static u32 cur_rx_toggle; ! 68: static u32 cur_rx_index; ! 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: ! 86: static inline u64 *veth_get_rx_buf(unsigned int i) ! 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: } ! 117: rx_bufs_aligned = (u64 *)(((u64)rx_bufs | 3) + 1); ! 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), ! 125: (*(u64 *)mac_addr) >> 16); ! 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++) { ! 131: u64 *buf = veth_get_rx_buf(i); ! 132: union ibmveth_buf_desc desc; ! 133: *buf = (u64)buf; ! 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: ! 207: if ((desc->flags_off & IBMVETH_RXQ_TOGGLE) != cur_rx_toggle) ! 208: break; ! 209: ! 210: if (!(desc->flags_off & IBMVETH_RXQ_VALID)) ! 211: goto recycle; ! 212: if (desc->length > f_len_i) { ! 213: printk("veth: Dropping too big packet [%d bytes]\n", ! 214: desc->length); ! 215: goto recycle; ! 216: } ! 217: ! 218: buf = (void *)desc->correlator; ! 219: packet = desc->length; ! 220: memcpy(f_buffer_pc, ! 221: buf + (desc->flags_off & IBMVETH_RXQ_OFF_MASK), packet); ! 222: recycle: ! 223: bdesc.fields.address = vaddr_to_dma(buf); ! 224: bdesc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE; ! 225: h_add_logical_lan_buffer(g_reg, bdesc.desc); ! 226: ! 227: cur_rx_index = (cur_rx_index + 1) % RX_QUEUE_SIZE; ! 228: if (cur_rx_index == 0) ! 229: cur_rx_toggle ^= IBMVETH_RXQ_TOGGLE; ! 230: } ! 231: ! 232: return packet; ! 233: } ! 234: ! 235: static int veth_ioctl(int request, void* data) ! 236: { ! 237: dprintk("veth_ioctl()\n"); ! 238: ! 239: return 0; ! 240: } ! 241: ! 242: static snk_module_t veth_interface = { ! 243: .version = 1, ! 244: .type = MOD_TYPE_NETWORK, ! 245: .running = 0, ! 246: .init = veth_init, ! 247: .term = veth_term, ! 248: .write = veth_xmit, ! 249: .read = veth_receive, ! 250: .ioctl = veth_ioctl ! 251: }; ! 252: ! 253: ! 254: static int check_driver(vio_config_t *conf) ! 255: { ! 256: ! 257: if (snk_kernel_interface->strcmp(conf->compat, "IBM,l-lan")) { ! 258: printk( "veth: netdevice not supported\n" ); ! 259: return -1; ! 260: } ! 261: g_reg = conf->reg; ! 262: ! 263: return 0; ! 264: } ! 265: ! 266: snk_module_t* veth_module_init(snk_kernel_t *snk_kernel_int, vio_config_t *conf) ! 267: { ! 268: snk_kernel_interface = snk_kernel_int; ! 269: snk_module_interface = &veth_interface; ! 270: ! 271: if (snk_kernel_int->version != snk_module_interface->version) ! 272: return 0; ! 273: ! 274: /* Check if this is the right driver */ ! 275: if (check_driver(conf) < 0) ! 276: return 0; ! 277: ! 278: snk_module_interface->link_addr = module_init; ! 279: return snk_module_interface; ! 280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.