Lines Matching +full:0 +full:- +full:dev

4  * PAPR Inter-VM Logical Lan, aka ibmveth
35 #include "hw/qdev-properties.h"
46 #define SPAPRVLAN_FLAG_RX_BUF_POOLS_BIT 0
55 #define VLAN_BD_VALID 0x8000000000000000ULL
56 #define VLAN_BD_TOGGLE 0x4000000000000000ULL
57 #define VLAN_BD_NO_CSUM 0x0200000000000000ULL
58 #define VLAN_BD_CSUM_GOOD 0x0100000000000000ULL
59 #define VLAN_BD_LEN_MASK 0x00ffffff00000000ULL
61 #define VLAN_BD_ADDR_MASK 0x00000000ffffffffULL
68 #define VLAN_RXQC_TOGGLE 0x80
69 #define VLAN_RXQC_VALID 0x40
70 #define VLAN_RXQC_NO_CSUM 0x02
71 #define VLAN_RXQC_CSUM_GOOD 0x01
74 #define VLAN_RXQ_BD_OFF 0
83 #define VLAN_RX_BDS_LEN (SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF - 8)
86 #define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
114 SpaprVioVlan *dev = qemu_get_nic_opaque(nc); in spapr_vlan_can_receive() local
116 return dev->isopen && dev->rx_bufs > 0; in spapr_vlan_can_receive()
126 static void spapr_vlan_record_dropped_rx_frame(SpaprVioVlan *dev) in spapr_vlan_record_dropped_rx_frame() argument
130 cnt = vio_ldq(&dev->sdev, dev->buf_list + 4096 - 8); in spapr_vlan_record_dropped_rx_frame()
131 vio_stq(&dev->sdev, dev->buf_list + 4096 - 8, cnt + 1); in spapr_vlan_record_dropped_rx_frame()
137 static vlan_bd_t spapr_vlan_get_rx_bd_from_pool(SpaprVioVlan *dev, in spapr_vlan_get_rx_bd_from_pool() argument
143 for (pool = 0; pool < RX_MAX_POOLS; pool++) { in spapr_vlan_get_rx_bd_from_pool()
144 if (dev->rx_pool[pool]->count > 0 && in spapr_vlan_get_rx_bd_from_pool()
145 dev->rx_pool[pool]->bufsize >= size + 8) { in spapr_vlan_get_rx_bd_from_pool()
151 return 0; in spapr_vlan_get_rx_bd_from_pool()
156 dev->rx_pool[pool]->count, in spapr_vlan_get_rx_bd_from_pool()
157 dev->rx_bufs); in spapr_vlan_get_rx_bd_from_pool()
160 dev->rx_pool[pool]->count--; in spapr_vlan_get_rx_bd_from_pool()
161 bd = dev->rx_pool[pool]->bds[dev->rx_pool[pool]->count]; in spapr_vlan_get_rx_bd_from_pool()
162 dev->rx_pool[pool]->bds[dev->rx_pool[pool]->count] = 0; in spapr_vlan_get_rx_bd_from_pool()
171 static vlan_bd_t spapr_vlan_get_rx_bd_from_page(SpaprVioVlan *dev, in spapr_vlan_get_rx_bd_from_page() argument
174 int buf_ptr = dev->use_buf_ptr; in spapr_vlan_get_rx_bd_from_page()
183 bd = vio_ldq(&dev->sdev, dev->buf_list + buf_ptr); in spapr_vlan_get_rx_bd_from_page()
187 && buf_ptr != dev->use_buf_ptr); in spapr_vlan_get_rx_bd_from_page()
191 return 0; in spapr_vlan_get_rx_bd_from_page()
195 dev->use_buf_ptr = buf_ptr; in spapr_vlan_get_rx_bd_from_page()
196 vio_stq(&dev->sdev, dev->buf_list + dev->use_buf_ptr, 0); in spapr_vlan_get_rx_bd_from_page()
198 trace_spapr_vlan_get_rx_bd_from_page_found(dev->use_buf_ptr, dev->rx_bufs); in spapr_vlan_get_rx_bd_from_page()
206 SpaprVioVlan *dev = qemu_get_nic_opaque(nc); in spapr_vlan_receive() local
207 SpaprVioDevice *sdev = VIO_SPAPR_DEVICE(dev); in spapr_vlan_receive()
208 vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF); in spapr_vlan_receive()
213 trace_spapr_vlan_receive(sdev->qdev.id, dev->rx_bufs); in spapr_vlan_receive()
215 if (!dev->isopen) { in spapr_vlan_receive()
216 return -1; in spapr_vlan_receive()
219 if (!dev->rx_bufs) { in spapr_vlan_receive()
220 spapr_vlan_record_dropped_rx_frame(dev); in spapr_vlan_receive()
221 return 0; in spapr_vlan_receive()
224 if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { in spapr_vlan_receive()
225 bd = spapr_vlan_get_rx_bd_from_pool(dev, size); in spapr_vlan_receive()
227 bd = spapr_vlan_get_rx_bd_from_page(dev, size); in spapr_vlan_receive()
230 spapr_vlan_record_dropped_rx_frame(dev); in spapr_vlan_receive()
231 return 0; in spapr_vlan_receive()
234 dev->rx_bufs--; in spapr_vlan_receive()
237 if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) { in spapr_vlan_receive()
238 return -1; in spapr_vlan_receive()
250 vio_stq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle); in spapr_vlan_receive()
251 vio_stl(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size); in spapr_vlan_receive()
252 vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8); in spapr_vlan_receive()
253 vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control); in spapr_vlan_receive()
255 trace_spapr_vlan_receive_wrote(dev->rxq_ptr, in spapr_vlan_receive()
257 dev->rxq_ptr), in spapr_vlan_receive()
259 dev->rxq_ptr + 8)); in spapr_vlan_receive()
261 dev->rxq_ptr += 16; in spapr_vlan_receive()
262 if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) { in spapr_vlan_receive()
263 dev->rxq_ptr = 0; in spapr_vlan_receive()
264 vio_stq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE); in spapr_vlan_receive()
267 if (sdev->signal_state & 1) { in spapr_vlan_receive()
283 SpaprVioVlan *dev = opaque; in spapr_vlan_flush_rx_queue() local
285 qemu_flush_queued_packets(qemu_get_queue(dev->nic)); in spapr_vlan_flush_rx_queue()
294 rxp->bufsize = INT_MAX; in spapr_vlan_reset_rx_pool()
295 rxp->count = 0; in spapr_vlan_reset_rx_pool()
296 memset(rxp->bds, 0, sizeof(rxp->bds)); in spapr_vlan_reset_rx_pool()
301 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in spapr_vlan_reset() local
304 dev->buf_list = 0; in spapr_vlan_reset()
305 dev->rx_bufs = 0; in spapr_vlan_reset()
306 dev->isopen = 0; in spapr_vlan_reset()
308 if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { in spapr_vlan_reset()
309 for (i = 0; i < RX_MAX_POOLS; i++) { in spapr_vlan_reset()
310 spapr_vlan_reset_rx_pool(dev->rx_pool[i]); in spapr_vlan_reset()
314 memcpy(&dev->nicconf.macaddr.a, &dev->perm_mac.a, in spapr_vlan_reset()
315 sizeof(dev->nicconf.macaddr.a)); in spapr_vlan_reset()
316 qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); in spapr_vlan_reset()
321 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in spapr_vlan_realize() local
323 qemu_macaddr_default_if_unset(&dev->nicconf.macaddr); in spapr_vlan_realize()
325 memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a)); in spapr_vlan_realize()
327 dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, in spapr_vlan_realize()
328 object_get_typename(OBJECT(sdev)), sdev->qdev.id, in spapr_vlan_realize()
329 &sdev->qdev.mem_reentrancy_guard, dev); in spapr_vlan_realize()
330 qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); in spapr_vlan_realize()
332 dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue, in spapr_vlan_realize()
333 dev); in spapr_vlan_realize()
338 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(obj); in spapr_vlan_instance_init() local
341 device_add_bootindex_property(obj, &dev->nicconf.bootindex, in spapr_vlan_instance_init()
343 DEVICE(dev)); in spapr_vlan_instance_init()
345 if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { in spapr_vlan_instance_init()
346 for (i = 0; i < RX_MAX_POOLS; i++) { in spapr_vlan_instance_init()
347 dev->rx_pool[i] = g_new(RxBufPool, 1); in spapr_vlan_instance_init()
348 spapr_vlan_reset_rx_pool(dev->rx_pool[i]); in spapr_vlan_instance_init()
355 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(obj); in spapr_vlan_instance_finalize() local
358 if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { in spapr_vlan_instance_finalize()
359 for (i = 0; i < RX_MAX_POOLS; i++) { in spapr_vlan_instance_finalize()
360 g_free(dev->rx_pool[i]); in spapr_vlan_instance_finalize()
361 dev->rx_pool[i] = NULL; in spapr_vlan_instance_finalize()
365 if (dev->rxp_timer) { in spapr_vlan_instance_finalize()
366 timer_free(dev->rxp_timer); in spapr_vlan_instance_finalize()
372 DeviceState *dev; in spapr_vlan_create() local
374 dev = qdev_new("spapr-vlan"); in spapr_vlan_create()
376 qdev_set_nic_properties(dev, nd); in spapr_vlan_create()
378 qdev_realize_and_unref(dev, &bus->bus, &error_fatal); in spapr_vlan_create()
381 static int spapr_vlan_devnode(SpaprVioDevice *dev, void *fdt, int node_off) in spapr_vlan_devnode() argument
383 SpaprVioVlan *vdev = VIO_SPAPR_VLAN_DEVICE(dev); in spapr_vlan_devnode()
384 uint8_t padded_mac[8] = {0, 0}; in spapr_vlan_devnode()
387 /* Some old phyp versions give the mac address in an 8-byte in spapr_vlan_devnode()
390 * length, it checks whether the first byte has 0b10 in the low in spapr_vlan_devnode()
391 * bits. If a correct 6-byte property has a different first byte in spapr_vlan_devnode()
395 * Here we return a 6-byte address unless that would break a pre-3.10 in spapr_vlan_devnode()
396 * driver. In that case we return a padded 8-byte address to allow the old in spapr_vlan_devnode()
398 if ((vdev->nicconf.macaddr.a[0] & 0x3) == 0x2) { in spapr_vlan_devnode()
399 ret = fdt_setprop(fdt, node_off, "local-mac-address", in spapr_vlan_devnode()
400 &vdev->nicconf.macaddr, ETH_ALEN); in spapr_vlan_devnode()
402 memcpy(&padded_mac[2], &vdev->nicconf.macaddr, ETH_ALEN); in spapr_vlan_devnode()
403 ret = fdt_setprop(fdt, node_off, "local-mac-address", in spapr_vlan_devnode()
406 if (ret < 0) { in spapr_vlan_devnode()
410 ret = fdt_setprop_cell(fdt, node_off, "ibm,mac-address-filters", 0); in spapr_vlan_devnode()
411 if (ret < 0) { in spapr_vlan_devnode()
415 return 0; in spapr_vlan_devnode()
418 static int check_bd(SpaprVioVlan *dev, vlan_bd_t bd, in check_bd() argument
423 return -1; in check_bd()
426 if (!spapr_vio_dma_valid(&dev->sdev, VLAN_BD_ADDR(bd), in check_bd()
428 || !spapr_vio_dma_valid(&dev->sdev, VLAN_BD_ADDR(bd), in check_bd()
430 return -1; in check_bd()
433 return 0; in check_bd()
441 target_ulong reg = args[0]; in h_register_logical_lan()
445 SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_register_logical_lan()
446 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in h_register_logical_lan() local
449 if (!dev) { in h_register_logical_lan()
453 if (dev->isopen) { in h_register_logical_lan()
459 if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_TCE_PAGE_SIZE), in h_register_logical_lan()
460 SPAPR_TCE_PAGE_SIZE) < 0) { in h_register_logical_lan()
461 hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx "\n", buf_list); in h_register_logical_lan()
466 if (check_bd(dev, filter_list_bd, SPAPR_TCE_PAGE_SIZE) < 0) { in h_register_logical_lan()
467 hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx "\n", filter_list); in h_register_logical_lan()
472 || (check_bd(dev, rec_queue, VLAN_RQ_ALIGNMENT) < 0)) { in h_register_logical_lan()
477 dev->buf_list = buf_list; in h_register_logical_lan()
478 sdev->signal_state = 0; in h_register_logical_lan()
485 spapr_vio_dma_set(sdev, buf_list + VLAN_RX_BDS_OFF, 0, in h_register_logical_lan()
486 SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF); in h_register_logical_lan()
487 dev->add_buf_ptr = VLAN_RX_BDS_OFF - 8; in h_register_logical_lan()
488 dev->use_buf_ptr = VLAN_RX_BDS_OFF - 8; in h_register_logical_lan()
489 dev->rx_bufs = 0; in h_register_logical_lan()
490 dev->rxq_ptr = 0; in h_register_logical_lan()
493 spapr_vio_dma_set(sdev, VLAN_BD_ADDR(rec_queue), 0, VLAN_BD_LEN(rec_queue)); in h_register_logical_lan()
495 dev->isopen = 1; in h_register_logical_lan()
496 qemu_flush_queued_packets(qemu_get_queue(dev->nic)); in h_register_logical_lan()
506 target_ulong reg = args[0]; in h_free_logical_lan()
507 SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_free_logical_lan()
508 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in h_free_logical_lan() local
510 if (!dev) { in h_free_logical_lan()
514 if (!dev->isopen) { in h_free_logical_lan()
532 if (pool1->bufsize < pool2->bufsize) { in rx_pool_size_compare()
533 return -1; in rx_pool_size_compare()
535 return pool1->bufsize > pool2->bufsize; in rx_pool_size_compare()
540 * or return -1 if no matching pool has been found.
542 static int spapr_vlan_get_rx_pool_id(SpaprVioVlan *dev, int size) in spapr_vlan_get_rx_pool_id() argument
546 for (pool = 0; pool < RX_MAX_POOLS; pool++) { in spapr_vlan_get_rx_pool_id()
547 if (dev->rx_pool[pool]->bufsize == size) { in spapr_vlan_get_rx_pool_id()
552 return -1; in spapr_vlan_get_rx_pool_id()
558 static target_long spapr_vlan_add_rxbuf_to_pool(SpaprVioVlan *dev, in spapr_vlan_add_rxbuf_to_pool() argument
564 pool = spapr_vlan_get_rx_pool_id(dev, size); in spapr_vlan_add_rxbuf_to_pool()
565 if (pool < 0) { in spapr_vlan_add_rxbuf_to_pool()
572 for (pool = RX_MAX_POOLS - 1; pool >= 0 ; pool--) { in spapr_vlan_add_rxbuf_to_pool()
573 if (dev->rx_pool[pool]->count == 0) { in spapr_vlan_add_rxbuf_to_pool()
574 dev->rx_pool[pool]->bufsize = size; in spapr_vlan_add_rxbuf_to_pool()
579 qsort(dev->rx_pool, RX_MAX_POOLS, sizeof(dev->rx_pool[0]), in spapr_vlan_add_rxbuf_to_pool()
581 pool = spapr_vlan_get_rx_pool_id(dev, size); in spapr_vlan_add_rxbuf_to_pool()
589 if (pool < 0 || dev->rx_pool[pool]->count >= RX_POOL_MAX_BDS) { in spapr_vlan_add_rxbuf_to_pool()
594 dev->rx_pool[pool]->count); in spapr_vlan_add_rxbuf_to_pool()
596 dev->rx_pool[pool]->bds[dev->rx_pool[pool]->count++] = buf; in spapr_vlan_add_rxbuf_to_pool()
598 return 0; in spapr_vlan_add_rxbuf_to_pool()
605 static target_long spapr_vlan_add_rxbuf_to_page(SpaprVioVlan *dev, in spapr_vlan_add_rxbuf_to_page() argument
610 if (dev->rx_bufs >= VLAN_MAX_BUFS) { in spapr_vlan_add_rxbuf_to_page()
615 dev->add_buf_ptr += 8; in spapr_vlan_add_rxbuf_to_page()
616 if (dev->add_buf_ptr >= VLAN_RX_BDS_LEN + VLAN_RX_BDS_OFF) { in spapr_vlan_add_rxbuf_to_page()
617 dev->add_buf_ptr = VLAN_RX_BDS_OFF; in spapr_vlan_add_rxbuf_to_page()
620 bd = vio_ldq(&dev->sdev, dev->buf_list + dev->add_buf_ptr); in spapr_vlan_add_rxbuf_to_page()
623 vio_stq(&dev->sdev, dev->buf_list + dev->add_buf_ptr, buf); in spapr_vlan_add_rxbuf_to_page()
625 trace_spapr_vlan_add_rxbuf_to_page(dev->add_buf_ptr, dev->rx_bufs, buf); in spapr_vlan_add_rxbuf_to_page()
627 return 0; in spapr_vlan_add_rxbuf_to_page()
635 target_ulong reg = args[0]; in h_add_logical_lan_buffer()
637 SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_add_logical_lan_buffer()
638 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in h_add_logical_lan_buffer() local
648 if ((check_bd(dev, buf, 4) < 0) in h_add_logical_lan_buffer()
654 if (!dev->isopen) { in h_add_logical_lan_buffer()
658 if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { in h_add_logical_lan_buffer()
659 ret = spapr_vlan_add_rxbuf_to_pool(dev, buf); in h_add_logical_lan_buffer()
661 ret = spapr_vlan_add_rxbuf_to_page(dev, buf); in h_add_logical_lan_buffer()
667 dev->rx_bufs++; in h_add_logical_lan_buffer()
675 timer_mod(dev->rxp_timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 500); in h_add_logical_lan_buffer()
684 target_ulong reg = args[0]; in h_send_logical_lan()
687 SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_send_logical_lan()
688 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in h_send_logical_lan() local
701 trace_spapr_vlan_h_send_logical_lan_rxbufs(dev->rx_bufs); in h_send_logical_lan()
703 if (!dev->isopen) { in h_send_logical_lan()
711 total_len = 0; in h_send_logical_lan()
712 for (i = 0; i < 6; i++) { in h_send_logical_lan()
723 if (total_len == 0) { in h_send_logical_lan()
734 for (i = 0; i < nbufs; i++) { in h_send_logical_lan()
737 if (ret < 0) { in h_send_logical_lan()
744 qemu_send_packet(qemu_get_queue(dev->nic), lbuf, total_len); in h_send_logical_lan()
752 target_ulong reg = args[0]; in h_multicast_ctrl()
753 SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_multicast_ctrl() local
755 if (!dev) { in h_multicast_ctrl()
767 target_ulong reg = args[0]; in h_change_logical_lan_mac()
769 SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); in h_change_logical_lan_mac()
770 SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev); in h_change_logical_lan_mac() local
773 if (!dev) { in h_change_logical_lan_mac()
779 for (i = 0; i < ETH_ALEN; i++) { in h_change_logical_lan_mac()
780 dev->nicconf.macaddr.a[ETH_ALEN - i - 1] = macaddr & 0xff; in h_change_logical_lan_mac()
784 qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); in h_change_logical_lan_mac()
792 DEFINE_PROP_BIT("use-rx-buffer-pools", SpaprVioVlan,
798 SpaprVioVlan *dev = opaque; in spapr_vlan_rx_buffer_pools_needed() local
800 return (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) != 0; in spapr_vlan_rx_buffer_pools_needed()
856 k->realize = spapr_vlan_realize; in spapr_vlan_class_init()
857 k->reset = spapr_vlan_reset; in spapr_vlan_class_init()
858 k->devnode = spapr_vlan_devnode; in spapr_vlan_class_init()
859 k->dt_name = "l-lan"; in spapr_vlan_class_init()
860 k->dt_type = "network"; in spapr_vlan_class_init()
861 k->dt_compatible = "IBM,l-lan"; in spapr_vlan_class_init()
862 k->signal_mask = 0x1; in spapr_vlan_class_init()
863 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); in spapr_vlan_class_init()
865 k->rtce_window_size = 0x10000000; in spapr_vlan_class_init()
866 dc->vmsd = &vmstate_spapr_llan; in spapr_vlan_class_init()