Commit b946a1533209f61a93e34898aebb5b43154b99c3
1 parent
32a8f6ae
Introduce VLANClientState::cleanup() (Mark McLoughlin)
We're currently leaking memory and file descriptors on device hot-unplug. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7150 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
19 changed files
with
347 additions
and
66 deletions
hw/dp8393x.c
... | ... | @@ -156,6 +156,7 @@ typedef struct dp8393xState { |
156 | 156 | QEMUTimer *watchdog; |
157 | 157 | int64_t wt_last_update; |
158 | 158 | VLANClientState *vc; |
159 | + int mmio_index; | |
159 | 160 | |
160 | 161 | /* Registers */ |
161 | 162 | uint8_t cam[16][6]; |
... | ... | @@ -858,12 +859,23 @@ static void nic_reset(void *opaque) |
858 | 859 | dp8393x_update_irq(s); |
859 | 860 | } |
860 | 861 | |
862 | +static void nic_cleanup(VLANClientState *vc) | |
863 | +{ | |
864 | + dp8393xState *s = vc->opaque; | |
865 | + | |
866 | + cpu_unregister_io_memory(s->mmio_index); | |
867 | + | |
868 | + qemu_del_timer(s->watchdog); | |
869 | + qemu_free_timer(s->watchdog); | |
870 | + | |
871 | + qemu_free(s); | |
872 | +} | |
873 | + | |
861 | 874 | void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, |
862 | 875 | qemu_irq irq, void* mem_opaque, |
863 | 876 | void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)) |
864 | 877 | { |
865 | 878 | dp8393xState *s; |
866 | - int io; | |
867 | 879 | |
868 | 880 | qemu_check_nic_model(nd, "dp83932"); |
869 | 881 | |
... | ... | @@ -877,12 +889,12 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, |
877 | 889 | s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ |
878 | 890 | |
879 | 891 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
880 | - nic_receive, nic_can_receive, s); | |
892 | + nic_receive, nic_can_receive, nic_cleanup, s); | |
881 | 893 | |
882 | 894 | qemu_format_nic_info_str(s->vc, nd->macaddr); |
883 | 895 | qemu_register_reset(nic_reset, s); |
884 | 896 | nic_reset(s); |
885 | 897 | |
886 | - io = cpu_register_io_memory(0, dp8393x_read, dp8393x_write, s); | |
887 | - cpu_register_physical_memory(base, 0x40 << it_shift, io); | |
898 | + s->mmio_index = cpu_register_io_memory(0, dp8393x_read, dp8393x_write, s); | |
899 | + cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index); | |
888 | 900 | } | ... | ... |
hw/e1000.c
... | ... | @@ -1033,6 +1033,14 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num, |
1033 | 1033 | excluded_regs[i] - 4); |
1034 | 1034 | } |
1035 | 1035 | |
1036 | +static void | |
1037 | +e1000_cleanup(VLANClientState *vc) | |
1038 | +{ | |
1039 | + E1000State *d = vc->opaque; | |
1040 | + | |
1041 | + unregister_savevm("e1000", d); | |
1042 | +} | |
1043 | + | |
1036 | 1044 | static int |
1037 | 1045 | pci_e1000_uninit(PCIDevice *dev) |
1038 | 1046 | { |
... | ... | @@ -1094,7 +1102,8 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn) |
1094 | 1102 | memset(&d->tx, 0, sizeof d->tx); |
1095 | 1103 | |
1096 | 1104 | d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
1097 | - e1000_receive, e1000_can_receive, d); | |
1105 | + e1000_receive, e1000_can_receive, | |
1106 | + e1000_cleanup, d); | |
1098 | 1107 | d->vc->link_status_changed = e1000_set_link_status; |
1099 | 1108 | |
1100 | 1109 | qemu_format_nic_info_str(d->vc, nd->macaddr); | ... | ... |
hw/eepro100.c
... | ... | @@ -1710,6 +1710,25 @@ static void nic_save(QEMUFile * f, void *opaque) |
1710 | 1710 | qemu_put_buffer(f, s->configuration, sizeof(s->configuration)); |
1711 | 1711 | } |
1712 | 1712 | |
1713 | +static void nic_cleanup(VLANClientState *vc) | |
1714 | +{ | |
1715 | + EEPRO100State *s = vc->opaque; | |
1716 | + | |
1717 | + unregister_savevm(vc->model, s); | |
1718 | + | |
1719 | + eeprom93xx_free(s->eeprom); | |
1720 | +} | |
1721 | + | |
1722 | +static int pci_nic_uninit(PCIDevice *dev) | |
1723 | +{ | |
1724 | + PCIEEPRO100State *d = (PCIEEPRO100State *) dev; | |
1725 | + EEPRO100State *s = &d->eepro100; | |
1726 | + | |
1727 | + cpu_unregister_io_memory(s->mmio_index); | |
1728 | + | |
1729 | + return 0; | |
1730 | +} | |
1731 | + | |
1713 | 1732 | static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) |
1714 | 1733 | { |
1715 | 1734 | PCIEEPRO100State *d; |
... | ... | @@ -1720,6 +1739,7 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) |
1720 | 1739 | d = (PCIEEPRO100State *) pci_register_device(bus, nd->model, |
1721 | 1740 | sizeof(PCIEEPRO100State), -1, |
1722 | 1741 | NULL, NULL); |
1742 | + d->dev.unregister = pci_nic_uninit; | |
1723 | 1743 | |
1724 | 1744 | s = &d->eepro100; |
1725 | 1745 | s->device = device; |
... | ... | @@ -1750,7 +1770,8 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) |
1750 | 1770 | nic_reset(s); |
1751 | 1771 | |
1752 | 1772 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
1753 | - nic_receive, nic_can_receive, s); | |
1773 | + nic_receive, nic_can_receive, | |
1774 | + nic_cleanup, s); | |
1754 | 1775 | |
1755 | 1776 | qemu_format_nic_info_str(s->vc, s->macaddr); |
1756 | 1777 | ... | ... |
hw/etraxfs_eth.c
... | ... | @@ -554,6 +554,16 @@ static CPUWriteMemoryFunc *eth_write[] = { |
554 | 554 | ð_writel, |
555 | 555 | }; |
556 | 556 | |
557 | +static void eth_cleanup(VLANClientState *vc) | |
558 | +{ | |
559 | + struct fs_eth *eth = vc->opaque; | |
560 | + | |
561 | + cpu_unregister_io_memory(eth->ethregs); | |
562 | + | |
563 | + qemu_free(eth->dma_out); | |
564 | + qemu_free(eth); | |
565 | +} | |
566 | + | |
557 | 567 | void *etraxfs_eth_init(NICInfo *nd, CPUState *env, |
558 | 568 | qemu_irq *irq, target_phys_addr_t base, int phyaddr) |
559 | 569 | { |
... | ... | @@ -585,7 +595,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, |
585 | 595 | cpu_register_physical_memory (base, 0x5c, eth->ethregs); |
586 | 596 | |
587 | 597 | eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
588 | - eth_receive, eth_can_receive, eth); | |
598 | + eth_receive, eth_can_receive, | |
599 | + eth_cleanup, eth); | |
589 | 600 | eth->vc->opaque = eth; |
590 | 601 | eth->vc->link_status_changed = eth_set_link; |
591 | 602 | ... | ... |
hw/mcf_fec.c
... | ... | @@ -24,6 +24,7 @@ do { printf("mcf_fec: " fmt , ##args); } while (0) |
24 | 24 | |
25 | 25 | typedef struct { |
26 | 26 | qemu_irq *irq; |
27 | + int mmio_index; | |
27 | 28 | VLANClientState *vc; |
28 | 29 | uint32_t irq_state; |
29 | 30 | uint32_t eir; |
... | ... | @@ -441,21 +442,30 @@ static CPUWriteMemoryFunc *mcf_fec_writefn[] = { |
441 | 442 | mcf_fec_write |
442 | 443 | }; |
443 | 444 | |
445 | +static void mcf_fec_cleanup(VLANClientState *vc) | |
446 | +{ | |
447 | + mcf_fec_state *s = vc->opaque; | |
448 | + | |
449 | + cpu_unregister_io_memory(s->mmio_index); | |
450 | + | |
451 | + qemu_free(s); | |
452 | +} | |
453 | + | |
444 | 454 | void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) |
445 | 455 | { |
446 | 456 | mcf_fec_state *s; |
447 | - int iomemtype; | |
448 | 457 | |
449 | 458 | qemu_check_nic_model(nd, "mcf_fec"); |
450 | 459 | |
451 | 460 | s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state)); |
452 | 461 | s->irq = irq; |
453 | - iomemtype = cpu_register_io_memory(0, mcf_fec_readfn, | |
454 | - mcf_fec_writefn, s); | |
455 | - cpu_register_physical_memory(base, 0x400, iomemtype); | |
462 | + s->mmio_index = cpu_register_io_memory(0, mcf_fec_readfn, | |
463 | + mcf_fec_writefn, s); | |
464 | + cpu_register_physical_memory(base, 0x400, s->mmio_index); | |
456 | 465 | |
457 | 466 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
458 | - mcf_fec_receive, mcf_fec_can_receive, s); | |
467 | + mcf_fec_receive, mcf_fec_can_receive, | |
468 | + mcf_fec_cleanup, s); | |
459 | 469 | memcpy(s->macaddr, nd->macaddr, 6); |
460 | 470 | qemu_format_nic_info_str(s->vc, s->macaddr); |
461 | 471 | } | ... | ... |
hw/mipsnet.c
... | ... | @@ -33,6 +33,7 @@ typedef struct MIPSnetState { |
33 | 33 | uint32_t intctl; |
34 | 34 | uint8_t rx_buffer[MAX_ETH_FRAME_SIZE]; |
35 | 35 | uint8_t tx_buffer[MAX_ETH_FRAME_SIZE]; |
36 | + int io_base; | |
36 | 37 | qemu_irq irq; |
37 | 38 | VLANClientState *vc; |
38 | 39 | } MIPSnetState; |
... | ... | @@ -231,6 +232,17 @@ static int mipsnet_load(QEMUFile *f, void *opaque, int version_id) |
231 | 232 | return 0; |
232 | 233 | } |
233 | 234 | |
235 | +static void mipsnet_cleanup(VLANClientState *vc) | |
236 | +{ | |
237 | + MIPSnetState *s = vc->opaque; | |
238 | + | |
239 | + unregister_savevm("mipsnet", s); | |
240 | + | |
241 | + isa_unassign_ioport(s->io_base, 36); | |
242 | + | |
243 | + qemu_free(s); | |
244 | +} | |
245 | + | |
234 | 246 | void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) |
235 | 247 | { |
236 | 248 | MIPSnetState *s; |
... | ... | @@ -246,10 +258,12 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) |
246 | 258 | register_ioport_write(base, 36, 4, mipsnet_ioport_write, s); |
247 | 259 | register_ioport_read(base, 36, 4, mipsnet_ioport_read, s); |
248 | 260 | |
261 | + s->io_base = base; | |
249 | 262 | s->irq = irq; |
250 | 263 | if (nd && nd->vlan) { |
251 | 264 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
252 | - mipsnet_receive, mipsnet_can_receive, s); | |
265 | + mipsnet_receive, mipsnet_can_receive, | |
266 | + mipsnet_cleanup, s); | |
253 | 267 | } else { |
254 | 268 | s->vc = NULL; |
255 | 269 | } | ... | ... |
hw/musicpal.c
... | ... | @@ -536,6 +536,7 @@ typedef struct mv88w8618_eth_state { |
536 | 536 | uint32_t smir; |
537 | 537 | uint32_t icr; |
538 | 538 | uint32_t imr; |
539 | + int mmio_index; | |
539 | 540 | int vlan_header; |
540 | 541 | uint32_t tx_queue[2]; |
541 | 542 | uint32_t rx_queue[4]; |
... | ... | @@ -745,20 +746,29 @@ static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = { |
745 | 746 | mv88w8618_eth_write |
746 | 747 | }; |
747 | 748 | |
749 | +static void eth_cleanup(VLANClientState *vc) | |
750 | +{ | |
751 | + mv88w8618_eth_state *s = vc->opaque; | |
752 | + | |
753 | + cpu_unregister_io_memory(s->mmio_index); | |
754 | + | |
755 | + qemu_free(s); | |
756 | +} | |
757 | + | |
748 | 758 | static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq) |
749 | 759 | { |
750 | 760 | mv88w8618_eth_state *s; |
751 | - int iomemtype; | |
752 | 761 | |
753 | 762 | qemu_check_nic_model(nd, "mv88w8618"); |
754 | 763 | |
755 | 764 | s = qemu_mallocz(sizeof(mv88w8618_eth_state)); |
756 | 765 | s->irq = irq; |
757 | 766 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
758 | - eth_receive, eth_can_receive, s); | |
759 | - iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn, | |
760 | - mv88w8618_eth_writefn, s); | |
761 | - cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype); | |
767 | + eth_receive, eth_can_receive, | |
768 | + eth_cleanup, s); | |
769 | + s->mmio_index = cpu_register_io_memory(0, mv88w8618_eth_readfn, | |
770 | + mv88w8618_eth_writefn, s); | |
771 | + cpu_register_physical_memory(base, MP_ETH_SIZE, s->mmio_index); | |
762 | 772 | } |
763 | 773 | |
764 | 774 | /* LCD register offsets */ | ... | ... |
hw/ne2000.c
... | ... | @@ -140,6 +140,7 @@ typedef struct NE2000State { |
140 | 140 | uint8_t curpag; |
141 | 141 | uint8_t mult[8]; /* multicast mask array */ |
142 | 142 | qemu_irq irq; |
143 | + int isa_io_base; | |
143 | 144 | PCIDevice *pci_dev; |
144 | 145 | VLANClientState *vc; |
145 | 146 | uint8_t macaddr[6]; |
... | ... | @@ -718,6 +719,19 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id) |
718 | 719 | return 0; |
719 | 720 | } |
720 | 721 | |
722 | +static void isa_ne2000_cleanup(VLANClientState *vc) | |
723 | +{ | |
724 | + NE2000State *s = vc->opaque; | |
725 | + | |
726 | + unregister_savevm("ne2000", s); | |
727 | + | |
728 | + isa_unassign_ioport(s->isa_io_base, 16); | |
729 | + isa_unassign_ioport(s->isa_io_base + 0x10, 2); | |
730 | + isa_unassign_ioport(s->isa_io_base + 0x1f, 1); | |
731 | + | |
732 | + qemu_free(s); | |
733 | +} | |
734 | + | |
721 | 735 | void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) |
722 | 736 | { |
723 | 737 | NE2000State *s; |
... | ... | @@ -736,13 +750,15 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) |
736 | 750 | |
737 | 751 | register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); |
738 | 752 | register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
753 | + s->isa_io_base = base; | |
739 | 754 | s->irq = irq; |
740 | 755 | memcpy(s->macaddr, nd->macaddr, 6); |
741 | 756 | |
742 | 757 | ne2000_reset(s); |
743 | 758 | |
744 | 759 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
745 | - ne2000_receive, ne2000_can_receive, s); | |
760 | + ne2000_receive, ne2000_can_receive, | |
761 | + isa_ne2000_cleanup, s); | |
746 | 762 | |
747 | 763 | qemu_format_nic_info_str(s->vc, s->macaddr); |
748 | 764 | |
... | ... | @@ -777,6 +793,13 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, |
777 | 793 | register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
778 | 794 | } |
779 | 795 | |
796 | +static void ne2000_cleanup(VLANClientState *vc) | |
797 | +{ | |
798 | + NE2000State *s = vc->opaque; | |
799 | + | |
800 | + unregister_savevm("ne2000", s); | |
801 | +} | |
802 | + | |
780 | 803 | PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn) |
781 | 804 | { |
782 | 805 | PCINE2000State *d; |
... | ... | @@ -802,7 +825,8 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn) |
802 | 825 | memcpy(s->macaddr, nd->macaddr, 6); |
803 | 826 | ne2000_reset(s); |
804 | 827 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
805 | - ne2000_receive, ne2000_can_receive, s); | |
828 | + ne2000_receive, ne2000_can_receive, | |
829 | + ne2000_cleanup, s); | |
806 | 830 | |
807 | 831 | qemu_format_nic_info_str(s->vc, s->macaddr); |
808 | 832 | ... | ... |
hw/pcnet.c
... | ... | @@ -75,6 +75,7 @@ struct PCNetState_st { |
75 | 75 | uint8_t buffer[4096]; |
76 | 76 | int tx_busy; |
77 | 77 | qemu_irq irq; |
78 | + qemu_irq *reset_irq; | |
78 | 79 | void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, |
79 | 80 | uint8_t *buf, int len, int do_bswap); |
80 | 81 | void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, |
... | ... | @@ -1929,7 +1930,15 @@ static int pcnet_load(QEMUFile *f, void *opaque, int version_id) |
1929 | 1930 | return 0; |
1930 | 1931 | } |
1931 | 1932 | |
1932 | -static void pcnet_common_init(PCNetState *d, NICInfo *nd) | |
1933 | +static void pcnet_common_cleanup(PCNetState *d) | |
1934 | +{ | |
1935 | + unregister_savevm("pcnet", d); | |
1936 | + | |
1937 | + qemu_del_timer(d->poll_timer); | |
1938 | + qemu_free_timer(d->poll_timer); | |
1939 | +} | |
1940 | + | |
1941 | +static void pcnet_common_init(PCNetState *d, NICInfo *nd, NetCleanup *cleanup) | |
1933 | 1942 | { |
1934 | 1943 | d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); |
1935 | 1944 | |
... | ... | @@ -1937,7 +1946,8 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd) |
1937 | 1946 | |
1938 | 1947 | if (nd && nd->vlan) { |
1939 | 1948 | d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
1940 | - pcnet_receive, pcnet_can_receive, d); | |
1949 | + pcnet_receive, pcnet_can_receive, | |
1950 | + cleanup, d); | |
1941 | 1951 | |
1942 | 1952 | qemu_format_nic_info_str(d->vc, d->nd->macaddr); |
1943 | 1953 | } else { |
... | ... | @@ -1985,6 +1995,22 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, |
1985 | 1995 | cpu_physical_memory_read(addr, buf, len); |
1986 | 1996 | } |
1987 | 1997 | |
1998 | +static void pci_pcnet_cleanup(VLANClientState *vc) | |
1999 | +{ | |
2000 | + PCNetState *d = vc->opaque; | |
2001 | + | |
2002 | + pcnet_common_cleanup(d); | |
2003 | +} | |
2004 | + | |
2005 | +static int pci_pcnet_uninit(PCIDevice *dev) | |
2006 | +{ | |
2007 | + PCNetState *d = (PCNetState *)dev; | |
2008 | + | |
2009 | + cpu_unregister_io_memory(d->mmio_index); | |
2010 | + | |
2011 | + return 0; | |
2012 | +} | |
2013 | + | |
1988 | 2014 | PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) |
1989 | 2015 | { |
1990 | 2016 | PCNetState *d; |
... | ... | @@ -1997,7 +2023,7 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) |
1997 | 2023 | |
1998 | 2024 | d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState), |
1999 | 2025 | devfn, NULL, NULL); |
2000 | - | |
2026 | + d->dev.unregister = pci_pcnet_uninit; | |
2001 | 2027 | pci_conf = d->dev.config; |
2002 | 2028 | |
2003 | 2029 | pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD); |
... | ... | @@ -2031,7 +2057,8 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) |
2031 | 2057 | d->phys_mem_write = pci_physical_memory_write; |
2032 | 2058 | d->pci_dev = &d->dev; |
2033 | 2059 | |
2034 | - pcnet_common_init(d, nd); | |
2060 | + pcnet_common_init(d, nd, pci_pcnet_cleanup); | |
2061 | + | |
2035 | 2062 | return (PCIDevice *)d; |
2036 | 2063 | } |
2037 | 2064 | |
... | ... | @@ -2081,29 +2108,42 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = { |
2081 | 2108 | NULL, |
2082 | 2109 | }; |
2083 | 2110 | |
2111 | +static void lance_cleanup(VLANClientState *vc) | |
2112 | +{ | |
2113 | + PCNetState *d = vc->opaque; | |
2114 | + | |
2115 | + pcnet_common_cleanup(d); | |
2116 | + | |
2117 | + qemu_free_irqs(d->reset_irq); | |
2118 | + | |
2119 | + cpu_unregister_io_memory(d->mmio_index); | |
2120 | + | |
2121 | + qemu_free(d); | |
2122 | +} | |
2123 | + | |
2084 | 2124 | void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque, |
2085 | 2125 | qemu_irq irq, qemu_irq *reset) |
2086 | 2126 | { |
2087 | 2127 | PCNetState *d; |
2088 | - int lance_io_memory; | |
2089 | 2128 | |
2090 | 2129 | qemu_check_nic_model(nd, "lance"); |
2091 | 2130 | |
2092 | 2131 | d = qemu_mallocz(sizeof(PCNetState)); |
2093 | 2132 | |
2094 | - lance_io_memory = | |
2133 | + d->mmio_index = | |
2095 | 2134 | cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d); |
2096 | 2135 | |
2097 | 2136 | d->dma_opaque = dma_opaque; |
2098 | 2137 | |
2099 | - *reset = *qemu_allocate_irqs(parent_lance_reset, d, 1); | |
2138 | + d->reset_irq = qemu_allocate_irqs(parent_lance_reset, d, 1); | |
2139 | + *reset = *d->reset_irq; | |
2100 | 2140 | |
2101 | - cpu_register_physical_memory(leaddr, 4, lance_io_memory); | |
2141 | + cpu_register_physical_memory(leaddr, 4, d->mmio_index); | |
2102 | 2142 | |
2103 | 2143 | d->irq = irq; |
2104 | 2144 | d->phys_mem_read = ledma_memory_read; |
2105 | 2145 | d->phys_mem_write = ledma_memory_write; |
2106 | 2146 | |
2107 | - pcnet_common_init(d, nd); | |
2147 | + pcnet_common_init(d, nd, lance_cleanup); | |
2108 | 2148 | } |
2109 | 2149 | #endif /* TARGET_SPARC */ | ... | ... |
hw/rtl8139.c
... | ... | @@ -3414,6 +3414,33 @@ static void rtl8139_timer(void *opaque) |
3414 | 3414 | } |
3415 | 3415 | #endif /* RTL8139_ONBOARD_TIMER */ |
3416 | 3416 | |
3417 | +static void rtl8139_cleanup(VLANClientState *vc) | |
3418 | +{ | |
3419 | + RTL8139State *s = vc->opaque; | |
3420 | + | |
3421 | + if (s->cplus_txbuffer) { | |
3422 | + qemu_free(s->cplus_txbuffer); | |
3423 | + s->cplus_txbuffer = NULL; | |
3424 | + } | |
3425 | + | |
3426 | +#ifdef RTL8139_ONBOARD_TIMER | |
3427 | + qemu_del_timer(s->timer); | |
3428 | + qemu_free_timer(s->timer); | |
3429 | +#endif | |
3430 | + | |
3431 | + unregister_savevm("rtl8139", s); | |
3432 | +} | |
3433 | + | |
3434 | +static int pci_rtl8139_uninit(PCIDevice *dev) | |
3435 | +{ | |
3436 | + PCIRTL8139State *d = (PCIRTL8139State *)dev; | |
3437 | + RTL8139State *s = &d->rtl8139; | |
3438 | + | |
3439 | + cpu_unregister_io_memory(s->rtl8139_mmio_io_addr); | |
3440 | + | |
3441 | + return 0; | |
3442 | +} | |
3443 | + | |
3417 | 3444 | PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) |
3418 | 3445 | { |
3419 | 3446 | PCIRTL8139State *d; |
... | ... | @@ -3424,6 +3451,7 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) |
3424 | 3451 | "RTL8139", sizeof(PCIRTL8139State), |
3425 | 3452 | devfn, |
3426 | 3453 | NULL, NULL); |
3454 | + d->dev.unregister = pci_rtl8139_uninit; | |
3427 | 3455 | pci_conf = d->dev.config; |
3428 | 3456 | pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK); |
3429 | 3457 | pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8139); |
... | ... | @@ -3450,7 +3478,8 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) |
3450 | 3478 | memcpy(s->macaddr, nd->macaddr, 6); |
3451 | 3479 | rtl8139_reset(s); |
3452 | 3480 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
3453 | - rtl8139_receive, rtl8139_can_receive, s); | |
3481 | + rtl8139_receive, rtl8139_can_receive, | |
3482 | + rtl8139_cleanup, s); | |
3454 | 3483 | |
3455 | 3484 | qemu_format_nic_info_str(s->vc, s->macaddr); |
3456 | 3485 | ... | ... |
hw/smc91c111.c
... | ... | @@ -42,6 +42,7 @@ typedef struct { |
42 | 42 | uint8_t int_level; |
43 | 43 | uint8_t int_mask; |
44 | 44 | uint8_t macaddr[6]; |
45 | + int mmio_index; | |
45 | 46 | } smc91c111_state; |
46 | 47 | |
47 | 48 | #define RCR_SOFT_RST 0x8000 |
... | ... | @@ -690,24 +691,32 @@ static CPUWriteMemoryFunc *smc91c111_writefn[] = { |
690 | 691 | smc91c111_writel |
691 | 692 | }; |
692 | 693 | |
694 | +static void smc91c111_cleanup(VLANClientState *vc) | |
695 | +{ | |
696 | + smc91c111_state *s = vc->opaque; | |
697 | + | |
698 | + cpu_unregister_io_memory(s->mmio_index); | |
699 | + qemu_free(s); | |
700 | +} | |
701 | + | |
693 | 702 | void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq) |
694 | 703 | { |
695 | 704 | smc91c111_state *s; |
696 | - int iomemtype; | |
697 | 705 | |
698 | 706 | qemu_check_nic_model(nd, "smc91c111"); |
699 | 707 | |
700 | 708 | s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state)); |
701 | - iomemtype = cpu_register_io_memory(0, smc91c111_readfn, | |
702 | - smc91c111_writefn, s); | |
703 | - cpu_register_physical_memory(base, 16, iomemtype); | |
709 | + s->mmio_index = cpu_register_io_memory(0, smc91c111_readfn, | |
710 | + smc91c111_writefn, s); | |
711 | + cpu_register_physical_memory(base, 16, s->mmio_index); | |
704 | 712 | s->irq = irq; |
705 | 713 | memcpy(s->macaddr, nd->macaddr, 6); |
706 | 714 | |
707 | 715 | smc91c111_reset(s); |
708 | 716 | |
709 | 717 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
710 | - smc91c111_receive, smc91c111_can_receive, s); | |
718 | + smc91c111_receive, smc91c111_can_receive, | |
719 | + smc91c111_cleanup, s); | |
711 | 720 | qemu_format_nic_info_str(s->vc, s->macaddr); |
712 | 721 | /* ??? Save/restore. */ |
713 | 722 | } | ... | ... |
hw/stellaris_enet.c
... | ... | @@ -69,6 +69,7 @@ typedef struct { |
69 | 69 | VLANClientState *vc; |
70 | 70 | qemu_irq irq; |
71 | 71 | uint8_t macaddr[6]; |
72 | + int mmio_index; | |
72 | 73 | } stellaris_enet_state; |
73 | 74 | |
74 | 75 | static void stellaris_enet_update(stellaris_enet_state *s) |
... | ... | @@ -384,23 +385,35 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) |
384 | 385 | return 0; |
385 | 386 | } |
386 | 387 | |
388 | +static void stellaris_enet_cleanup(VLANClientState *vc) | |
389 | +{ | |
390 | + stellaris_enet_state *s = vc->opaque; | |
391 | + | |
392 | + unregister_savevm("stellaris_enet", s); | |
393 | + | |
394 | + cpu_unregister_io_memory(s->mmio_index); | |
395 | + | |
396 | + qemu_free(s); | |
397 | +} | |
398 | + | |
387 | 399 | void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) |
388 | 400 | { |
389 | 401 | stellaris_enet_state *s; |
390 | - int iomemtype; | |
391 | 402 | |
392 | 403 | qemu_check_nic_model(nd, "stellaris"); |
393 | 404 | |
394 | 405 | s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state)); |
395 | - iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn, | |
396 | - stellaris_enet_writefn, s); | |
397 | - cpu_register_physical_memory(base, 0x00001000, iomemtype); | |
406 | + s->mmio_index = cpu_register_io_memory(0, stellaris_enet_readfn, | |
407 | + stellaris_enet_writefn, s); | |
408 | + cpu_register_physical_memory(base, 0x00001000, s->mmio_index); | |
398 | 409 | s->irq = irq; |
399 | 410 | memcpy(s->macaddr, nd->macaddr, 6); |
400 | 411 | |
401 | 412 | if (nd->vlan) { |
402 | 413 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
403 | - stellaris_enet_receive, stellaris_enet_can_receive, s); | |
414 | + stellaris_enet_receive, | |
415 | + stellaris_enet_can_receive, | |
416 | + stellaris_enet_cleanup, s); | |
404 | 417 | qemu_format_nic_info_str(s->vc, s->macaddr); |
405 | 418 | } |
406 | 419 | ... | ... |
hw/usb-net.c
... | ... | @@ -1415,14 +1415,20 @@ static int usbnet_can_receive(void *opaque) |
1415 | 1415 | return !s->in_len; |
1416 | 1416 | } |
1417 | 1417 | |
1418 | +static void usbnet_cleanup(VLANClientState *vc) | |
1419 | +{ | |
1420 | + USBNetState *s = vc->opaque; | |
1421 | + | |
1422 | + rndis_clear_responsequeue(s); | |
1423 | + qemu_free(s); | |
1424 | +} | |
1425 | + | |
1418 | 1426 | static void usb_net_handle_destroy(USBDevice *dev) |
1419 | 1427 | { |
1420 | 1428 | USBNetState *s = (USBNetState *) dev; |
1421 | 1429 | |
1422 | 1430 | /* TODO: remove the nd_table[] entry */ |
1423 | 1431 | qemu_del_vlan_client(s->vc); |
1424 | - rndis_clear_responsequeue(s); | |
1425 | - qemu_free(s); | |
1426 | 1432 | } |
1427 | 1433 | |
1428 | 1434 | USBDevice *usb_net_init(NICInfo *nd) |
... | ... | @@ -1452,7 +1458,9 @@ USBDevice *usb_net_init(NICInfo *nd) |
1452 | 1458 | pstrcpy(s->dev.devname, sizeof(s->dev.devname), |
1453 | 1459 | "QEMU USB Network Interface"); |
1454 | 1460 | s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
1455 | - usbnet_receive, usbnet_can_receive, s); | |
1461 | + usbnet_receive, | |
1462 | + usbnet_can_receive, | |
1463 | + usbnet_cleanup, s); | |
1456 | 1464 | |
1457 | 1465 | qemu_format_nic_info_str(s->vc, s->mac); |
1458 | 1466 | ... | ... |
hw/virtio-net.c
... | ... | @@ -570,6 +570,21 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) |
570 | 570 | return 0; |
571 | 571 | } |
572 | 572 | |
573 | +static void virtio_net_cleanup(VLANClientState *vc) | |
574 | +{ | |
575 | + VirtIONet *n = vc->opaque; | |
576 | + | |
577 | + unregister_savevm("virtio-net", n); | |
578 | + | |
579 | + qemu_free(n->mac_table.macs); | |
580 | + qemu_free(n->vlans); | |
581 | + | |
582 | + qemu_del_timer(n->tx_timer); | |
583 | + qemu_free_timer(n->tx_timer); | |
584 | + | |
585 | + virtio_cleanup(&n->vdev); | |
586 | +} | |
587 | + | |
573 | 588 | PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) |
574 | 589 | { |
575 | 590 | VirtIONet *n; |
... | ... | @@ -598,7 +613,9 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) |
598 | 613 | memcpy(n->mac, nd->macaddr, ETH_ALEN); |
599 | 614 | n->status = VIRTIO_NET_S_LINK_UP; |
600 | 615 | n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
601 | - virtio_net_receive, virtio_net_can_receive, n); | |
616 | + virtio_net_receive, | |
617 | + virtio_net_can_receive, | |
618 | + virtio_net_cleanup, n); | |
602 | 619 | n->vc->link_status_changed = virtio_net_set_link_status; |
603 | 620 | |
604 | 621 | qemu_format_nic_info_str(n->vc, n->mac); | ... | ... |
hw/virtio.c
... | ... | @@ -750,6 +750,13 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) |
750 | 750 | virtio_update_irq(vdev); |
751 | 751 | } |
752 | 752 | |
753 | +void virtio_cleanup(VirtIODevice *vdev) | |
754 | +{ | |
755 | + if (vdev->config) | |
756 | + qemu_free(vdev->config); | |
757 | + qemu_free(vdev->vq); | |
758 | +} | |
759 | + | |
753 | 760 | VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name, |
754 | 761 | uint16_t vendor, uint16_t device, |
755 | 762 | uint16_t subvendor, uint16_t subdevice, | ... | ... |
hw/virtio.h
... | ... | @@ -117,6 +117,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f); |
117 | 117 | |
118 | 118 | void virtio_load(VirtIODevice *vdev, QEMUFile *f); |
119 | 119 | |
120 | +void virtio_cleanup(VirtIODevice *vdev); | |
121 | + | |
120 | 122 | void virtio_notify_config(VirtIODevice *vdev); |
121 | 123 | |
122 | 124 | void virtio_queue_set_notification(VirtQueue *vq, int enable); | ... | ... |
net.c
... | ... | @@ -333,6 +333,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, |
333 | 333 | const char *name, |
334 | 334 | IOReadHandler *fd_read, |
335 | 335 | IOCanRWHandler *fd_can_read, |
336 | + NetCleanup *cleanup, | |
336 | 337 | void *opaque) |
337 | 338 | { |
338 | 339 | VLANClientState *vc, **pvc; |
... | ... | @@ -344,6 +345,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, |
344 | 345 | vc->name = assign_name(vc, model); |
345 | 346 | vc->fd_read = fd_read; |
346 | 347 | vc->fd_can_read = fd_can_read; |
348 | + vc->cleanup = cleanup; | |
347 | 349 | vc->opaque = opaque; |
348 | 350 | vc->vlan = vlan; |
349 | 351 | |
... | ... | @@ -362,6 +364,9 @@ void qemu_del_vlan_client(VLANClientState *vc) |
362 | 364 | while (*pvc != NULL) |
363 | 365 | if (*pvc == vc) { |
364 | 366 | *pvc = vc->next; |
367 | + if (vc->cleanup) { | |
368 | + vc->cleanup(vc); | |
369 | + } | |
365 | 370 | free(vc->name); |
366 | 371 | free(vc->model); |
367 | 372 | free(vc); |
... | ... | @@ -521,7 +526,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name) |
521 | 526 | slirp_init(slirp_restrict, slirp_ip); |
522 | 527 | } |
523 | 528 | slirp_vc = qemu_new_vlan_client(vlan, model, name, |
524 | - slirp_receive, NULL, NULL); | |
529 | + slirp_receive, NULL, NULL, NULL); | |
525 | 530 | slirp_vc->info_str[0] = '\0'; |
526 | 531 | return 0; |
527 | 532 | } |
... | ... | @@ -702,6 +707,8 @@ typedef struct TAPState { |
702 | 707 | char down_script_arg[128]; |
703 | 708 | } TAPState; |
704 | 709 | |
710 | +static int launch_script(const char *setup_script, const char *ifname, int fd); | |
711 | + | |
705 | 712 | static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov, |
706 | 713 | int iovcnt) |
707 | 714 | { |
... | ... | @@ -748,6 +755,18 @@ static void tap_send(void *opaque) |
748 | 755 | } |
749 | 756 | } |
750 | 757 | |
758 | +static void tap_cleanup(VLANClientState *vc) | |
759 | +{ | |
760 | + TAPState *s = vc->opaque; | |
761 | + | |
762 | + if (s->down_script[0]) | |
763 | + launch_script(s->down_script, s->down_script_arg, s->fd); | |
764 | + | |
765 | + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | |
766 | + close(s->fd); | |
767 | + qemu_free(s); | |
768 | +} | |
769 | + | |
751 | 770 | /* fd support */ |
752 | 771 | |
753 | 772 | static TAPState *net_tap_fd_init(VLANState *vlan, |
... | ... | @@ -759,7 +778,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, |
759 | 778 | |
760 | 779 | s = qemu_mallocz(sizeof(TAPState)); |
761 | 780 | s->fd = fd; |
762 | - s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s); | |
781 | + s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, | |
782 | + NULL, tap_cleanup, s); | |
763 | 783 | s->vc->fd_readv = tap_receive_iov; |
764 | 784 | qemu_set_fd_handler(s->fd, tap_send, NULL, s); |
765 | 785 | snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd); |
... | ... | @@ -1058,6 +1078,14 @@ static void vde_from_qemu(void *opaque, const uint8_t *buf, int size) |
1058 | 1078 | } |
1059 | 1079 | } |
1060 | 1080 | |
1081 | +static void vde_cleanup(VLANClientState *vc) | |
1082 | +{ | |
1083 | + VDEState *s = vc->opaque; | |
1084 | + qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); | |
1085 | + vde_close(s->vde); | |
1086 | + qemu_free(s); | |
1087 | +} | |
1088 | + | |
1061 | 1089 | static int net_vde_init(VLANState *vlan, const char *model, |
1062 | 1090 | const char *name, const char *sock, |
1063 | 1091 | int port, const char *group, int mode) |
... | ... | @@ -1078,7 +1106,8 @@ static int net_vde_init(VLANState *vlan, const char *model, |
1078 | 1106 | free(s); |
1079 | 1107 | return -1; |
1080 | 1108 | } |
1081 | - s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s); | |
1109 | + s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, | |
1110 | + NULL, vde_cleanup, s); | |
1082 | 1111 | qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); |
1083 | 1112 | snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d", |
1084 | 1113 | sock, vde_datafd(s->vde)); |
... | ... | @@ -1263,6 +1292,14 @@ fail: |
1263 | 1292 | return -1; |
1264 | 1293 | } |
1265 | 1294 | |
1295 | +static void net_socket_cleanup(VLANClientState *vc) | |
1296 | +{ | |
1297 | + NetSocketState *s = vc->opaque; | |
1298 | + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | |
1299 | + close(s->fd); | |
1300 | + qemu_free(s); | |
1301 | +} | |
1302 | + | |
1266 | 1303 | static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, |
1267 | 1304 | const char *model, |
1268 | 1305 | const char *name, |
... | ... | @@ -1307,7 +1344,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, |
1307 | 1344 | s = qemu_mallocz(sizeof(NetSocketState)); |
1308 | 1345 | s->fd = fd; |
1309 | 1346 | |
1310 | - s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, NULL, s); | |
1347 | + s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, | |
1348 | + NULL, net_socket_cleanup, s); | |
1311 | 1349 | qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); |
1312 | 1350 | |
1313 | 1351 | /* mcast: save bound address as dst */ |
... | ... | @@ -1334,8 +1372,8 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, |
1334 | 1372 | NetSocketState *s; |
1335 | 1373 | s = qemu_mallocz(sizeof(NetSocketState)); |
1336 | 1374 | s->fd = fd; |
1337 | - s->vc = qemu_new_vlan_client(vlan, model, name, | |
1338 | - net_socket_receive, NULL, s); | |
1375 | + s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive, | |
1376 | + NULL, net_socket_cleanup, s); | |
1339 | 1377 | snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
1340 | 1378 | "socket: fd=%d", fd); |
1341 | 1379 | if (is_connected) { |
... | ... | @@ -1895,29 +1933,20 @@ done: |
1895 | 1933 | |
1896 | 1934 | void net_cleanup(void) |
1897 | 1935 | { |
1898 | -#if !defined(_WIN32) | |
1899 | 1936 | VLANState *vlan; |
1900 | 1937 | |
1901 | 1938 | /* close network clients */ |
1902 | 1939 | for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { |
1903 | - VLANClientState *vc; | |
1940 | + VLANClientState *vc = vlan->first_client; | |
1904 | 1941 | |
1905 | - for(vc = vlan->first_client; vc != NULL; vc = vc->next) { | |
1906 | - if (vc->fd_read == tap_receive) { | |
1907 | - TAPState *s = vc->opaque; | |
1942 | + while (vc) { | |
1943 | + VLANClientState *next = vc->next; | |
1908 | 1944 | |
1909 | - if (s->down_script[0]) | |
1910 | - launch_script(s->down_script, s->down_script_arg, s->fd); | |
1911 | - } | |
1912 | -#if defined(CONFIG_VDE) | |
1913 | - if (vc->fd_read == vde_from_qemu) { | |
1914 | - VDEState *s = vc->opaque; | |
1915 | - vde_close(s->vde); | |
1916 | - } | |
1917 | -#endif | |
1945 | + qemu_del_vlan_client(vc); | |
1946 | + | |
1947 | + vc = next; | |
1918 | 1948 | } |
1919 | 1949 | } |
1920 | -#endif | |
1921 | 1950 | } |
1922 | 1951 | |
1923 | 1952 | void net_client_check(void) | ... | ... |
net.h
... | ... | @@ -9,6 +9,7 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int); |
9 | 9 | |
10 | 10 | typedef struct VLANClientState VLANClientState; |
11 | 11 | |
12 | +typedef void (NetCleanup) (VLANClientState *); | |
12 | 13 | typedef void (LinkStatusChanged)(VLANClientState *); |
13 | 14 | |
14 | 15 | struct VLANClientState { |
... | ... | @@ -17,6 +18,7 @@ struct VLANClientState { |
17 | 18 | /* Packets may still be sent if this returns zero. It's used to |
18 | 19 | rate-limit the slirp code. */ |
19 | 20 | IOCanRWHandler *fd_can_read; |
21 | + NetCleanup *cleanup; | |
20 | 22 | LinkStatusChanged *link_status_changed; |
21 | 23 | int link_down; |
22 | 24 | void *opaque; |
... | ... | @@ -40,6 +42,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, |
40 | 42 | const char *name, |
41 | 43 | IOReadHandler *fd_read, |
42 | 44 | IOCanRWHandler *fd_can_read, |
45 | + NetCleanup *cleanup, | |
43 | 46 | void *opaque); |
44 | 47 | void qemu_del_vlan_client(VLANClientState *vc); |
45 | 48 | VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque); | ... | ... |
tap-win32.c
... | ... | @@ -638,6 +638,18 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, |
638 | 638 | tap_win32_overlapped_t *handle; |
639 | 639 | } TAPState; |
640 | 640 | |
641 | +static void tap_cleanup(VLANClientState *vc) | |
642 | +{ | |
643 | + TAPState *s = vc->opaque; | |
644 | + | |
645 | + qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL); | |
646 | + | |
647 | + /* FIXME: need to kill thread and close file handle: | |
648 | + tap_win32_close(s); | |
649 | + */ | |
650 | + qemu_free(s); | |
651 | +} | |
652 | + | |
641 | 653 | static void tap_receive(void *opaque, const uint8_t *buf, int size) |
642 | 654 | { |
643 | 655 | TAPState *s = opaque; |
... | ... | @@ -672,7 +684,8 @@ int tap_win32_init(VLANState *vlan, const char *model, |
672 | 684 | return -1; |
673 | 685 | } |
674 | 686 | |
675 | - s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s); | |
687 | + s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, | |
688 | + NULL, tap_cleanup, s); | |
676 | 689 | |
677 | 690 | snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
678 | 691 | "tap: ifname=%s", ifname); | ... | ... |