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
This commit is contained in:
		
							parent
							
								
									32a8f6ae93
								
							
						
					
					
						commit
						b946a15332
					
				
							
								
								
									
										20
									
								
								hw/dp8393x.c
								
								
								
								
							
							
						
						
									
										20
									
								
								hw/dp8393x.c
								
								
								
								
							|  | @ -156,6 +156,7 @@ typedef struct dp8393xState { | |||
|     QEMUTimer *watchdog; | ||||
|     int64_t wt_last_update; | ||||
|     VLANClientState *vc; | ||||
|     int mmio_index; | ||||
| 
 | ||||
|     /* Registers */ | ||||
|     uint8_t cam[16][6]; | ||||
|  | @ -858,12 +859,23 @@ static void nic_reset(void *opaque) | |||
|     dp8393x_update_irq(s); | ||||
| } | ||||
| 
 | ||||
| static void nic_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     dp8393xState *s = vc->opaque; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
| 
 | ||||
|     qemu_del_timer(s->watchdog); | ||||
|     qemu_free_timer(s->watchdog); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, | ||||
|                   qemu_irq irq, void* mem_opaque, | ||||
|                   void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)) | ||||
| { | ||||
|     dp8393xState *s; | ||||
|     int io; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "dp83932"); | ||||
| 
 | ||||
|  | @ -877,12 +889,12 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, | |||
|     s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  nic_receive, nic_can_receive, s); | ||||
|                                  nic_receive, nic_can_receive, nic_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, nd->macaddr); | ||||
|     qemu_register_reset(nic_reset, s); | ||||
|     nic_reset(s); | ||||
| 
 | ||||
|     io = cpu_register_io_memory(0, dp8393x_read, dp8393x_write, s); | ||||
|     cpu_register_physical_memory(base, 0x40 << it_shift, io); | ||||
|     s->mmio_index = cpu_register_io_memory(0, dp8393x_read, dp8393x_write, s); | ||||
|     cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										11
									
								
								hw/e1000.c
								
								
								
								
							
							
						
						
									
										11
									
								
								hw/e1000.c
								
								
								
								
							|  | @ -1033,6 +1033,14 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num, | |||
|                                      excluded_regs[i] - 4); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| e1000_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     E1000State *d = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("e1000", d); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| pci_e1000_uninit(PCIDevice *dev) | ||||
| { | ||||
|  | @ -1094,7 +1102,8 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn) | |||
|     memset(&d->tx, 0, sizeof d->tx); | ||||
| 
 | ||||
|     d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  e1000_receive, e1000_can_receive, d); | ||||
|                                  e1000_receive, e1000_can_receive, | ||||
|                                  e1000_cleanup, d); | ||||
|     d->vc->link_status_changed = e1000_set_link_status; | ||||
| 
 | ||||
|     qemu_format_nic_info_str(d->vc, nd->macaddr); | ||||
|  |  | |||
|  | @ -1710,6 +1710,25 @@ static void nic_save(QEMUFile * f, void *opaque) | |||
|     qemu_put_buffer(f, s->configuration, sizeof(s->configuration)); | ||||
| } | ||||
| 
 | ||||
| static void nic_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     EEPRO100State *s = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm(vc->model, s); | ||||
| 
 | ||||
|     eeprom93xx_free(s->eeprom); | ||||
| } | ||||
| 
 | ||||
| static int pci_nic_uninit(PCIDevice *dev) | ||||
| { | ||||
|     PCIEEPRO100State *d = (PCIEEPRO100State *) dev; | ||||
|     EEPRO100State *s = &d->eepro100; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) | ||||
| { | ||||
|     PCIEEPRO100State *d; | ||||
|  | @ -1720,6 +1739,7 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) | |||
|     d = (PCIEEPRO100State *) pci_register_device(bus, nd->model, | ||||
|                                                  sizeof(PCIEEPRO100State), -1, | ||||
|                                                  NULL, NULL); | ||||
|     d->dev.unregister = pci_nic_uninit; | ||||
| 
 | ||||
|     s = &d->eepro100; | ||||
|     s->device = device; | ||||
|  | @ -1750,7 +1770,8 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device) | |||
|     nic_reset(s); | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  nic_receive, nic_can_receive, s); | ||||
|                                  nic_receive, nic_can_receive, | ||||
|                                  nic_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
| 
 | ||||
|  |  | |||
|  | @ -554,6 +554,16 @@ static CPUWriteMemoryFunc *eth_write[] = { | |||
| 	ð_writel, | ||||
| }; | ||||
| 
 | ||||
| static void eth_cleanup(VLANClientState *vc) | ||||
| { | ||||
|         struct fs_eth *eth = vc->opaque; | ||||
| 
 | ||||
|         cpu_unregister_io_memory(eth->ethregs); | ||||
| 
 | ||||
|         qemu_free(eth->dma_out); | ||||
|         qemu_free(eth); | ||||
| } | ||||
| 
 | ||||
| void *etraxfs_eth_init(NICInfo *nd, CPUState *env,  | ||||
| 		       qemu_irq *irq, target_phys_addr_t base, int phyaddr) | ||||
| { | ||||
|  | @ -585,7 +595,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, | |||
| 	cpu_register_physical_memory (base, 0x5c, eth->ethregs); | ||||
| 
 | ||||
| 	eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
| 				       eth_receive, eth_can_receive, eth); | ||||
| 				       eth_receive, eth_can_receive, | ||||
| 				       eth_cleanup, eth); | ||||
| 	eth->vc->opaque = eth; | ||||
| 	eth->vc->link_status_changed = eth_set_link; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										20
									
								
								hw/mcf_fec.c
								
								
								
								
							
							
						
						
									
										20
									
								
								hw/mcf_fec.c
								
								
								
								
							|  | @ -24,6 +24,7 @@ do { printf("mcf_fec: " fmt , ##args); } while (0) | |||
| 
 | ||||
| typedef struct { | ||||
|     qemu_irq *irq; | ||||
|     int mmio_index; | ||||
|     VLANClientState *vc; | ||||
|     uint32_t irq_state; | ||||
|     uint32_t eir; | ||||
|  | @ -441,21 +442,30 @@ static CPUWriteMemoryFunc *mcf_fec_writefn[] = { | |||
|    mcf_fec_write | ||||
| }; | ||||
| 
 | ||||
| static void mcf_fec_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     mcf_fec_state *s = vc->opaque; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) | ||||
| { | ||||
|     mcf_fec_state *s; | ||||
|     int iomemtype; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "mcf_fec"); | ||||
| 
 | ||||
|     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state)); | ||||
|     s->irq = irq; | ||||
|     iomemtype = cpu_register_io_memory(0, mcf_fec_readfn, | ||||
|                                        mcf_fec_writefn, s); | ||||
|     cpu_register_physical_memory(base, 0x400, iomemtype); | ||||
|     s->mmio_index = cpu_register_io_memory(0, mcf_fec_readfn, | ||||
|                                            mcf_fec_writefn, s); | ||||
|     cpu_register_physical_memory(base, 0x400, s->mmio_index); | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  mcf_fec_receive, mcf_fec_can_receive, s); | ||||
|                                  mcf_fec_receive, mcf_fec_can_receive, | ||||
|                                  mcf_fec_cleanup, s); | ||||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										16
									
								
								hw/mipsnet.c
								
								
								
								
							
							
						
						
									
										16
									
								
								hw/mipsnet.c
								
								
								
								
							|  | @ -33,6 +33,7 @@ typedef struct MIPSnetState { | |||
|     uint32_t intctl; | ||||
|     uint8_t rx_buffer[MAX_ETH_FRAME_SIZE]; | ||||
|     uint8_t tx_buffer[MAX_ETH_FRAME_SIZE]; | ||||
|     int io_base; | ||||
|     qemu_irq irq; | ||||
|     VLANClientState *vc; | ||||
| } MIPSnetState; | ||||
|  | @ -231,6 +232,17 @@ static int mipsnet_load(QEMUFile *f, void *opaque, int version_id) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void mipsnet_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     MIPSnetState *s = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("mipsnet", s); | ||||
| 
 | ||||
|     isa_unassign_ioport(s->io_base, 36); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) | ||||
| { | ||||
|     MIPSnetState *s; | ||||
|  | @ -246,10 +258,12 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) | |||
|     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s); | ||||
|     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s); | ||||
| 
 | ||||
|     s->io_base = base; | ||||
|     s->irq = irq; | ||||
|     if (nd && nd->vlan) { | ||||
|         s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                      mipsnet_receive, mipsnet_can_receive, s); | ||||
|                                      mipsnet_receive, mipsnet_can_receive, | ||||
|                                      mipsnet_cleanup, s); | ||||
|     } else { | ||||
|         s->vc = NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -536,6 +536,7 @@ typedef struct mv88w8618_eth_state { | |||
|     uint32_t smir; | ||||
|     uint32_t icr; | ||||
|     uint32_t imr; | ||||
|     int mmio_index; | ||||
|     int vlan_header; | ||||
|     uint32_t tx_queue[2]; | ||||
|     uint32_t rx_queue[4]; | ||||
|  | @ -745,20 +746,29 @@ static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = { | |||
|     mv88w8618_eth_write | ||||
| }; | ||||
| 
 | ||||
| static void eth_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     mv88w8618_eth_state *s = vc->opaque; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq) | ||||
| { | ||||
|     mv88w8618_eth_state *s; | ||||
|     int iomemtype; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "mv88w8618"); | ||||
| 
 | ||||
|     s = qemu_mallocz(sizeof(mv88w8618_eth_state)); | ||||
|     s->irq = irq; | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  eth_receive, eth_can_receive, s); | ||||
|     iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn, | ||||
|                                        mv88w8618_eth_writefn, s); | ||||
|     cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype); | ||||
|                                  eth_receive, eth_can_receive, | ||||
|                                  eth_cleanup, s); | ||||
|     s->mmio_index = cpu_register_io_memory(0, mv88w8618_eth_readfn, | ||||
|                                            mv88w8618_eth_writefn, s); | ||||
|     cpu_register_physical_memory(base, MP_ETH_SIZE, s->mmio_index); | ||||
| } | ||||
| 
 | ||||
| /* LCD register offsets */ | ||||
|  |  | |||
							
								
								
									
										28
									
								
								hw/ne2000.c
								
								
								
								
							
							
						
						
									
										28
									
								
								hw/ne2000.c
								
								
								
								
							|  | @ -140,6 +140,7 @@ typedef struct NE2000State { | |||
|     uint8_t curpag; | ||||
|     uint8_t mult[8]; /* multicast mask array */ | ||||
|     qemu_irq irq; | ||||
|     int isa_io_base; | ||||
|     PCIDevice *pci_dev; | ||||
|     VLANClientState *vc; | ||||
|     uint8_t macaddr[6]; | ||||
|  | @ -718,6 +719,19 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void isa_ne2000_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     NE2000State *s = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("ne2000", s); | ||||
| 
 | ||||
|     isa_unassign_ioport(s->isa_io_base, 16); | ||||
|     isa_unassign_ioport(s->isa_io_base + 0x10, 2); | ||||
|     isa_unassign_ioport(s->isa_io_base + 0x1f, 1); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) | ||||
| { | ||||
|     NE2000State *s; | ||||
|  | @ -736,13 +750,15 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) | |||
| 
 | ||||
|     register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); | ||||
|     register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); | ||||
|     s->isa_io_base = base; | ||||
|     s->irq = irq; | ||||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
| 
 | ||||
|     ne2000_reset(s); | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  ne2000_receive, ne2000_can_receive, s); | ||||
|                                  ne2000_receive, ne2000_can_receive, | ||||
|                                  isa_ne2000_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
| 
 | ||||
|  | @ -777,6 +793,13 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, | |||
|     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); | ||||
| } | ||||
| 
 | ||||
| static void ne2000_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     NE2000State *s = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("ne2000", s); | ||||
| } | ||||
| 
 | ||||
| PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn) | ||||
| { | ||||
|     PCINE2000State *d; | ||||
|  | @ -802,7 +825,8 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn) | |||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
|     ne2000_reset(s); | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  ne2000_receive, ne2000_can_receive, s); | ||||
|                                  ne2000_receive, ne2000_can_receive, | ||||
|                                  ne2000_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										58
									
								
								hw/pcnet.c
								
								
								
								
							
							
						
						
									
										58
									
								
								hw/pcnet.c
								
								
								
								
							|  | @ -75,6 +75,7 @@ struct PCNetState_st { | |||
|     uint8_t buffer[4096]; | ||||
|     int tx_busy; | ||||
|     qemu_irq irq; | ||||
|     qemu_irq *reset_irq; | ||||
|     void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, | ||||
|                          uint8_t *buf, int len, int do_bswap); | ||||
|     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) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void pcnet_common_init(PCNetState *d, NICInfo *nd) | ||||
| static void pcnet_common_cleanup(PCNetState *d) | ||||
| { | ||||
|     unregister_savevm("pcnet", d); | ||||
| 
 | ||||
|     qemu_del_timer(d->poll_timer); | ||||
|     qemu_free_timer(d->poll_timer); | ||||
| } | ||||
| 
 | ||||
| static void pcnet_common_init(PCNetState *d, NICInfo *nd, NetCleanup *cleanup) | ||||
| { | ||||
|     d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); | ||||
| 
 | ||||
|  | @ -1937,7 +1946,8 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd) | |||
| 
 | ||||
|     if (nd && nd->vlan) { | ||||
|         d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                      pcnet_receive, pcnet_can_receive, d); | ||||
|                                      pcnet_receive, pcnet_can_receive, | ||||
|                                      cleanup, d); | ||||
| 
 | ||||
|         qemu_format_nic_info_str(d->vc, d->nd->macaddr); | ||||
|     } else { | ||||
|  | @ -1985,6 +1995,22 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, | |||
|     cpu_physical_memory_read(addr, buf, len); | ||||
| } | ||||
| 
 | ||||
| static void pci_pcnet_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     PCNetState *d = vc->opaque; | ||||
| 
 | ||||
|     pcnet_common_cleanup(d); | ||||
| } | ||||
| 
 | ||||
| static int pci_pcnet_uninit(PCIDevice *dev) | ||||
| { | ||||
|     PCNetState *d = (PCNetState *)dev; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(d->mmio_index); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) | ||||
| { | ||||
|     PCNetState *d; | ||||
|  | @ -1997,7 +2023,7 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn) | |||
| 
 | ||||
|     d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState), | ||||
|                                           devfn, NULL, NULL); | ||||
| 
 | ||||
|     d->dev.unregister = pci_pcnet_uninit; | ||||
|     pci_conf = d->dev.config; | ||||
| 
 | ||||
|     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) | |||
|     d->phys_mem_write = pci_physical_memory_write; | ||||
|     d->pci_dev = &d->dev; | ||||
| 
 | ||||
|     pcnet_common_init(d, nd); | ||||
|     pcnet_common_init(d, nd, pci_pcnet_cleanup); | ||||
| 
 | ||||
|     return (PCIDevice *)d; | ||||
| } | ||||
| 
 | ||||
|  | @ -2081,29 +2108,42 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = { | |||
|     NULL, | ||||
| }; | ||||
| 
 | ||||
| static void lance_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     PCNetState *d = vc->opaque; | ||||
| 
 | ||||
|     pcnet_common_cleanup(d); | ||||
| 
 | ||||
|     qemu_free_irqs(d->reset_irq); | ||||
| 
 | ||||
|     cpu_unregister_io_memory(d->mmio_index); | ||||
| 
 | ||||
|     qemu_free(d); | ||||
| } | ||||
| 
 | ||||
| void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque, | ||||
|                 qemu_irq irq, qemu_irq *reset) | ||||
| { | ||||
|     PCNetState *d; | ||||
|     int lance_io_memory; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "lance"); | ||||
| 
 | ||||
|     d = qemu_mallocz(sizeof(PCNetState)); | ||||
| 
 | ||||
|     lance_io_memory = | ||||
|     d->mmio_index = | ||||
|         cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d); | ||||
| 
 | ||||
|     d->dma_opaque = dma_opaque; | ||||
| 
 | ||||
|     *reset = *qemu_allocate_irqs(parent_lance_reset, d, 1); | ||||
|     d->reset_irq = qemu_allocate_irqs(parent_lance_reset, d, 1); | ||||
|     *reset = *d->reset_irq; | ||||
| 
 | ||||
|     cpu_register_physical_memory(leaddr, 4, lance_io_memory); | ||||
|     cpu_register_physical_memory(leaddr, 4, d->mmio_index); | ||||
| 
 | ||||
|     d->irq = irq; | ||||
|     d->phys_mem_read = ledma_memory_read; | ||||
|     d->phys_mem_write = ledma_memory_write; | ||||
| 
 | ||||
|     pcnet_common_init(d, nd); | ||||
|     pcnet_common_init(d, nd, lance_cleanup); | ||||
| } | ||||
| #endif /* TARGET_SPARC */ | ||||
|  |  | |||
							
								
								
									
										31
									
								
								hw/rtl8139.c
								
								
								
								
							
							
						
						
									
										31
									
								
								hw/rtl8139.c
								
								
								
								
							|  | @ -3414,6 +3414,33 @@ static void rtl8139_timer(void *opaque) | |||
| } | ||||
| #endif /* RTL8139_ONBOARD_TIMER */ | ||||
| 
 | ||||
| static void rtl8139_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     RTL8139State *s = vc->opaque; | ||||
| 
 | ||||
|     if (s->cplus_txbuffer) { | ||||
|         qemu_free(s->cplus_txbuffer); | ||||
|         s->cplus_txbuffer = NULL; | ||||
|     } | ||||
| 
 | ||||
| #ifdef RTL8139_ONBOARD_TIMER | ||||
|     qemu_del_timer(s->timer); | ||||
|     qemu_free_timer(s->timer); | ||||
| #endif | ||||
| 
 | ||||
|     unregister_savevm("rtl8139", s); | ||||
| } | ||||
| 
 | ||||
| static int pci_rtl8139_uninit(PCIDevice *dev) | ||||
| { | ||||
|     PCIRTL8139State *d = (PCIRTL8139State *)dev; | ||||
|     RTL8139State *s = &d->rtl8139; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->rtl8139_mmio_io_addr); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) | ||||
| { | ||||
|     PCIRTL8139State *d; | ||||
|  | @ -3424,6 +3451,7 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) | |||
|                                               "RTL8139", sizeof(PCIRTL8139State), | ||||
|                                               devfn, | ||||
|                                               NULL, NULL); | ||||
|     d->dev.unregister = pci_rtl8139_uninit; | ||||
|     pci_conf = d->dev.config; | ||||
|     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK); | ||||
|     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) | |||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
|     rtl8139_reset(s); | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  rtl8139_receive, rtl8139_can_receive, s); | ||||
|                                  rtl8139_receive, rtl8139_can_receive, | ||||
|                                  rtl8139_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,6 +42,7 @@ typedef struct { | |||
|     uint8_t int_level; | ||||
|     uint8_t int_mask; | ||||
|     uint8_t macaddr[6]; | ||||
|     int mmio_index; | ||||
| } smc91c111_state; | ||||
| 
 | ||||
| #define RCR_SOFT_RST  0x8000 | ||||
|  | @ -690,24 +691,32 @@ static CPUWriteMemoryFunc *smc91c111_writefn[] = { | |||
|     smc91c111_writel | ||||
| }; | ||||
| 
 | ||||
| static void smc91c111_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     smc91c111_state *s = vc->opaque; | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq) | ||||
| { | ||||
|     smc91c111_state *s; | ||||
|     int iomemtype; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "smc91c111"); | ||||
| 
 | ||||
|     s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state)); | ||||
|     iomemtype = cpu_register_io_memory(0, smc91c111_readfn, | ||||
|                                        smc91c111_writefn, s); | ||||
|     cpu_register_physical_memory(base, 16, iomemtype); | ||||
|     s->mmio_index = cpu_register_io_memory(0, smc91c111_readfn, | ||||
|                                            smc91c111_writefn, s); | ||||
|     cpu_register_physical_memory(base, 16, s->mmio_index); | ||||
|     s->irq = irq; | ||||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
| 
 | ||||
|     smc91c111_reset(s); | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  smc91c111_receive, smc91c111_can_receive, s); | ||||
|                                  smc91c111_receive, smc91c111_can_receive, | ||||
|                                  smc91c111_cleanup, s); | ||||
|     qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
|     /* ??? Save/restore.  */ | ||||
| } | ||||
|  |  | |||
|  | @ -69,6 +69,7 @@ typedef struct { | |||
|     VLANClientState *vc; | ||||
|     qemu_irq irq; | ||||
|     uint8_t macaddr[6]; | ||||
|     int mmio_index; | ||||
| } stellaris_enet_state; | ||||
| 
 | ||||
| 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) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void stellaris_enet_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     stellaris_enet_state *s = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("stellaris_enet", s); | ||||
| 
 | ||||
|     cpu_unregister_io_memory(s->mmio_index); | ||||
| 
 | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) | ||||
| { | ||||
|     stellaris_enet_state *s; | ||||
|     int iomemtype; | ||||
| 
 | ||||
|     qemu_check_nic_model(nd, "stellaris"); | ||||
| 
 | ||||
|     s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state)); | ||||
|     iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn, | ||||
|                                        stellaris_enet_writefn, s); | ||||
|     cpu_register_physical_memory(base, 0x00001000, iomemtype); | ||||
|     s->mmio_index = cpu_register_io_memory(0, stellaris_enet_readfn, | ||||
|                                            stellaris_enet_writefn, s); | ||||
|     cpu_register_physical_memory(base, 0x00001000, s->mmio_index); | ||||
|     s->irq = irq; | ||||
|     memcpy(s->macaddr, nd->macaddr, 6); | ||||
| 
 | ||||
|     if (nd->vlan) { | ||||
|         s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                      stellaris_enet_receive, stellaris_enet_can_receive, s); | ||||
|                                      stellaris_enet_receive, | ||||
|                                      stellaris_enet_can_receive, | ||||
|                                      stellaris_enet_cleanup, s); | ||||
|         qemu_format_nic_info_str(s->vc, s->macaddr); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										14
									
								
								hw/usb-net.c
								
								
								
								
							
							
						
						
									
										14
									
								
								hw/usb-net.c
								
								
								
								
							|  | @ -1415,14 +1415,20 @@ static int usbnet_can_receive(void *opaque) | |||
|     return !s->in_len; | ||||
| } | ||||
| 
 | ||||
| static void usbnet_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     USBNetState *s = vc->opaque; | ||||
| 
 | ||||
|     rndis_clear_responsequeue(s); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| static void usb_net_handle_destroy(USBDevice *dev) | ||||
| { | ||||
|     USBNetState *s = (USBNetState *) dev; | ||||
| 
 | ||||
|     /* TODO: remove the nd_table[] entry */ | ||||
|     qemu_del_vlan_client(s->vc); | ||||
|     rndis_clear_responsequeue(s); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| USBDevice *usb_net_init(NICInfo *nd) | ||||
|  | @ -1452,7 +1458,9 @@ USBDevice *usb_net_init(NICInfo *nd) | |||
|     pstrcpy(s->dev.devname, sizeof(s->dev.devname), | ||||
|                     "QEMU USB Network Interface"); | ||||
|     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                     usbnet_receive, usbnet_can_receive, s); | ||||
|                                  usbnet_receive, | ||||
|                                  usbnet_can_receive, | ||||
|                                  usbnet_cleanup, s); | ||||
| 
 | ||||
|     qemu_format_nic_info_str(s->vc, s->mac); | ||||
| 
 | ||||
|  |  | |||
|  | @ -570,6 +570,21 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void virtio_net_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     VirtIONet *n = vc->opaque; | ||||
| 
 | ||||
|     unregister_savevm("virtio-net", n); | ||||
| 
 | ||||
|     qemu_free(n->mac_table.macs); | ||||
|     qemu_free(n->vlans); | ||||
| 
 | ||||
|     qemu_del_timer(n->tx_timer); | ||||
|     qemu_free_timer(n->tx_timer); | ||||
| 
 | ||||
|     virtio_cleanup(&n->vdev); | ||||
| } | ||||
| 
 | ||||
| PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) | ||||
| { | ||||
|     VirtIONet *n; | ||||
|  | @ -598,7 +613,9 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) | |||
|     memcpy(n->mac, nd->macaddr, ETH_ALEN); | ||||
|     n->status = VIRTIO_NET_S_LINK_UP; | ||||
|     n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, | ||||
|                                  virtio_net_receive, virtio_net_can_receive, n); | ||||
|                                  virtio_net_receive, | ||||
|                                  virtio_net_can_receive, | ||||
|                                  virtio_net_cleanup, n); | ||||
|     n->vc->link_status_changed = virtio_net_set_link_status; | ||||
| 
 | ||||
|     qemu_format_nic_info_str(n->vc, n->mac); | ||||
|  |  | |||
|  | @ -750,6 +750,13 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) | |||
|     virtio_update_irq(vdev); | ||||
| } | ||||
| 
 | ||||
| void virtio_cleanup(VirtIODevice *vdev) | ||||
| { | ||||
|     if (vdev->config) | ||||
|         qemu_free(vdev->config); | ||||
|     qemu_free(vdev->vq); | ||||
| } | ||||
| 
 | ||||
| VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name, | ||||
|                               uint16_t vendor, uint16_t device, | ||||
|                               uint16_t subvendor, uint16_t subdevice, | ||||
|  |  | |||
|  | @ -117,6 +117,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f); | |||
| 
 | ||||
| void virtio_load(VirtIODevice *vdev, QEMUFile *f); | ||||
| 
 | ||||
| void virtio_cleanup(VirtIODevice *vdev); | ||||
| 
 | ||||
| void virtio_notify_config(VirtIODevice *vdev); | ||||
| 
 | ||||
| void virtio_queue_set_notification(VirtQueue *vq, int enable); | ||||
|  |  | |||
							
								
								
									
										71
									
								
								net.c
								
								
								
								
							
							
						
						
									
										71
									
								
								net.c
								
								
								
								
							|  | @ -333,6 +333,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, | |||
|                                       const char *name, | ||||
|                                       IOReadHandler *fd_read, | ||||
|                                       IOCanRWHandler *fd_can_read, | ||||
|                                       NetCleanup *cleanup, | ||||
|                                       void *opaque) | ||||
| { | ||||
|     VLANClientState *vc, **pvc; | ||||
|  | @ -344,6 +345,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, | |||
|         vc->name = assign_name(vc, model); | ||||
|     vc->fd_read = fd_read; | ||||
|     vc->fd_can_read = fd_can_read; | ||||
|     vc->cleanup = cleanup; | ||||
|     vc->opaque = opaque; | ||||
|     vc->vlan = vlan; | ||||
| 
 | ||||
|  | @ -362,6 +364,9 @@ void qemu_del_vlan_client(VLANClientState *vc) | |||
|     while (*pvc != NULL) | ||||
|         if (*pvc == vc) { | ||||
|             *pvc = vc->next; | ||||
|             if (vc->cleanup) { | ||||
|                 vc->cleanup(vc); | ||||
|             } | ||||
|             free(vc->name); | ||||
|             free(vc->model); | ||||
|             free(vc); | ||||
|  | @ -521,7 +526,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name) | |||
|         slirp_init(slirp_restrict, slirp_ip); | ||||
|     } | ||||
|     slirp_vc = qemu_new_vlan_client(vlan, model, name, | ||||
|                                     slirp_receive, NULL, NULL); | ||||
|                                     slirp_receive, NULL, NULL, NULL); | ||||
|     slirp_vc->info_str[0] = '\0'; | ||||
|     return 0; | ||||
| } | ||||
|  | @ -702,6 +707,8 @@ typedef struct TAPState { | |||
|     char down_script_arg[128]; | ||||
| } TAPState; | ||||
| 
 | ||||
| static int launch_script(const char *setup_script, const char *ifname, int fd); | ||||
| 
 | ||||
| static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov, | ||||
|                                int iovcnt) | ||||
| { | ||||
|  | @ -748,6 +755,18 @@ static void tap_send(void *opaque) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static void tap_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     TAPState *s = vc->opaque; | ||||
| 
 | ||||
|     if (s->down_script[0]) | ||||
|         launch_script(s->down_script, s->down_script_arg, s->fd); | ||||
| 
 | ||||
|     qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | ||||
|     close(s->fd); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| /* fd support */ | ||||
| 
 | ||||
| static TAPState *net_tap_fd_init(VLANState *vlan, | ||||
|  | @ -759,7 +778,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, | |||
| 
 | ||||
|     s = qemu_mallocz(sizeof(TAPState)); | ||||
|     s->fd = fd; | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s); | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, | ||||
|                                  NULL, tap_cleanup, s); | ||||
|     s->vc->fd_readv = tap_receive_iov; | ||||
|     qemu_set_fd_handler(s->fd, tap_send, NULL, s); | ||||
|     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) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static void vde_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     VDEState *s = vc->opaque; | ||||
|     qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); | ||||
|     vde_close(s->vde); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| static int net_vde_init(VLANState *vlan, const char *model, | ||||
|                         const char *name, const char *sock, | ||||
|                         int port, const char *group, int mode) | ||||
|  | @ -1078,7 +1106,8 @@ static int net_vde_init(VLANState *vlan, const char *model, | |||
|         free(s); | ||||
|         return -1; | ||||
|     } | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s); | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, | ||||
|                                  NULL, vde_cleanup, s); | ||||
|     qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); | ||||
|     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d", | ||||
|              sock, vde_datafd(s->vde)); | ||||
|  | @ -1263,6 +1292,14 @@ fail: | |||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| static void net_socket_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     NetSocketState *s = vc->opaque; | ||||
|     qemu_set_fd_handler(s->fd, NULL, NULL, NULL); | ||||
|     close(s->fd); | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, | ||||
|                                                 const char *model, | ||||
|                                                 const char *name, | ||||
|  | @ -1307,7 +1344,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, | |||
|     s = qemu_mallocz(sizeof(NetSocketState)); | ||||
|     s->fd = fd; | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, NULL, s); | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, | ||||
|                                  NULL, net_socket_cleanup, s); | ||||
|     qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); | ||||
| 
 | ||||
|     /* mcast: save bound address as dst */ | ||||
|  | @ -1334,8 +1372,8 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, | |||
|     NetSocketState *s; | ||||
|     s = qemu_mallocz(sizeof(NetSocketState)); | ||||
|     s->fd = fd; | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, | ||||
|                                  net_socket_receive, NULL, s); | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive, | ||||
|                                  NULL, net_socket_cleanup, s); | ||||
|     snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||||
|              "socket: fd=%d", fd); | ||||
|     if (is_connected) { | ||||
|  | @ -1895,29 +1933,20 @@ done: | |||
| 
 | ||||
| void net_cleanup(void) | ||||
| { | ||||
| #if !defined(_WIN32) | ||||
|     VLANState *vlan; | ||||
| 
 | ||||
|     /* close network clients */ | ||||
|     for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { | ||||
|         VLANClientState *vc; | ||||
|         VLANClientState *vc = vlan->first_client; | ||||
| 
 | ||||
|         for(vc = vlan->first_client; vc != NULL; vc = vc->next) { | ||||
|             if (vc->fd_read == tap_receive) { | ||||
|                 TAPState *s = vc->opaque; | ||||
|         while (vc) { | ||||
|             VLANClientState *next = vc->next; | ||||
| 
 | ||||
|                 if (s->down_script[0]) | ||||
|                     launch_script(s->down_script, s->down_script_arg, s->fd); | ||||
|             } | ||||
| #if defined(CONFIG_VDE) | ||||
|             if (vc->fd_read == vde_from_qemu) { | ||||
|                 VDEState *s = vc->opaque; | ||||
|                 vde_close(s->vde); | ||||
|             } | ||||
| #endif | ||||
|             qemu_del_vlan_client(vc); | ||||
| 
 | ||||
|             vc = next; | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void net_client_check(void) | ||||
|  |  | |||
							
								
								
									
										3
									
								
								net.h
								
								
								
								
							
							
						
						
									
										3
									
								
								net.h
								
								
								
								
							|  | @ -9,6 +9,7 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int); | |||
| 
 | ||||
| typedef struct VLANClientState VLANClientState; | ||||
| 
 | ||||
| typedef void (NetCleanup) (VLANClientState *); | ||||
| typedef void (LinkStatusChanged)(VLANClientState *); | ||||
| 
 | ||||
| struct VLANClientState { | ||||
|  | @ -17,6 +18,7 @@ struct VLANClientState { | |||
|     /* Packets may still be sent if this returns zero.  It's used to
 | ||||
|        rate-limit the slirp code.  */ | ||||
|     IOCanRWHandler *fd_can_read; | ||||
|     NetCleanup *cleanup; | ||||
|     LinkStatusChanged *link_status_changed; | ||||
|     int link_down; | ||||
|     void *opaque; | ||||
|  | @ -40,6 +42,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, | |||
|                                       const char *name, | ||||
|                                       IOReadHandler *fd_read, | ||||
|                                       IOCanRWHandler *fd_can_read, | ||||
|                                       NetCleanup *cleanup, | ||||
|                                       void *opaque); | ||||
| void qemu_del_vlan_client(VLANClientState *vc); | ||||
| VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque); | ||||
|  |  | |||
							
								
								
									
										15
									
								
								tap-win32.c
								
								
								
								
							
							
						
						
									
										15
									
								
								tap-win32.c
								
								
								
								
							|  | @ -638,6 +638,18 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, | |||
|      tap_win32_overlapped_t *handle; | ||||
|  } TAPState; | ||||
| 
 | ||||
| static void tap_cleanup(VLANClientState *vc) | ||||
| { | ||||
|     TAPState *s = vc->opaque; | ||||
| 
 | ||||
|     qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL); | ||||
| 
 | ||||
|     /* FIXME: need to kill thread and close file handle:
 | ||||
|        tap_win32_close(s); | ||||
|     */ | ||||
|     qemu_free(s); | ||||
| } | ||||
| 
 | ||||
| static void tap_receive(void *opaque, const uint8_t *buf, int size) | ||||
| { | ||||
|     TAPState *s = opaque; | ||||
|  | @ -672,7 +684,8 @@ int tap_win32_init(VLANState *vlan, const char *model, | |||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s); | ||||
|     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, | ||||
|                                  NULL, tap_cleanup, s); | ||||
| 
 | ||||
|     snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||||
|              "tap: ifname=%s", ifname); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 aliguori
						aliguori