cadence_gem: Add the num-priority-queues property
The Cadence GEM hardware supports N number priority queues, this patch is a step towards that by adding the property to set the queues. At the moment behaviour doesn't change as we only use queue 0. Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 6543ec0d0c4bfd2678d0ed683efb197e91b17733.1469727764.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									bcb39a65f1
								
							
						
					
					
						commit
						2bf57f73e3
					
				| @ -26,6 +26,7 @@ | ||||
| #include <zlib.h> /* For crc32 */ | ||||
| 
 | ||||
| #include "hw/net/cadence_gem.h" | ||||
| #include "qapi/error.h" | ||||
| #include "net/checksum.h" | ||||
| 
 | ||||
| #ifdef CADENCE_GEM_ERR_DEBUG | ||||
| @ -428,18 +429,18 @@ static int gem_can_receive(NetClientState *nc) | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     if (rx_desc_get_ownership(s->rx_desc) == 1) { | ||||
|     if (rx_desc_get_ownership(s->rx_desc[0]) == 1) { | ||||
|         if (s->can_rx_state != 2) { | ||||
|             s->can_rx_state = 2; | ||||
|             DB_PRINT("can't receive - busy buffer descriptor 0x%x\n", | ||||
|                      s->rx_desc_addr); | ||||
|                      s->rx_desc_addr[0]); | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     if (s->can_rx_state != 0) { | ||||
|         s->can_rx_state = 0; | ||||
|         DB_PRINT("can receive 0x%x\n", s->rx_desc_addr); | ||||
|         DB_PRINT("can receive 0x%x\n", s->rx_desc_addr[0]); | ||||
|     } | ||||
|     return 1; | ||||
| } | ||||
| @ -452,7 +453,7 @@ static void gem_update_int_status(CadenceGEMState *s) | ||||
| { | ||||
|     if (s->regs[GEM_ISR]) { | ||||
|         DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]); | ||||
|         qemu_set_irq(s->irq, 1); | ||||
|         qemu_set_irq(s->irq[0], 1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -603,15 +604,15 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) | ||||
| 
 | ||||
| static void gem_get_rx_desc(CadenceGEMState *s) | ||||
| { | ||||
|     DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr); | ||||
|     DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[0]); | ||||
|     /* read current descriptor */ | ||||
|     cpu_physical_memory_read(s->rx_desc_addr, | ||||
|                              (uint8_t *)s->rx_desc, sizeof(s->rx_desc)); | ||||
|     cpu_physical_memory_read(s->rx_desc_addr[0], | ||||
|                              (uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0])); | ||||
| 
 | ||||
|     /* Descriptor owned by software ? */ | ||||
|     if (rx_desc_get_ownership(s->rx_desc) == 1) { | ||||
|     if (rx_desc_get_ownership(s->rx_desc[0]) == 1) { | ||||
|         DB_PRINT("descriptor 0x%x owned by sw.\n", | ||||
|                  (unsigned)s->rx_desc_addr); | ||||
|                  (unsigned)s->rx_desc_addr[0]); | ||||
|         s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF; | ||||
|         s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]); | ||||
|         /* Handle interrupt consequences */ | ||||
| @ -632,6 +633,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) | ||||
|     uint8_t   *rxbuf_ptr; | ||||
|     bool first_desc = true; | ||||
|     int maf; | ||||
|     int q = 0; | ||||
| 
 | ||||
|     s = qemu_get_nic_opaque(nc); | ||||
| 
 | ||||
| @ -718,54 +720,56 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) | ||||
|         } | ||||
| 
 | ||||
|         DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize), | ||||
|                 rx_desc_get_buffer(s->rx_desc)); | ||||
|                 rx_desc_get_buffer(s->rx_desc[q])); | ||||
| 
 | ||||
|         /* Copy packet data to emulated DMA buffer */ | ||||
|         cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset, | ||||
|         cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) + | ||||
|                                                                  rxbuf_offset, | ||||
|                                   rxbuf_ptr, MIN(bytes_to_copy, rxbufsize)); | ||||
|         rxbuf_ptr += MIN(bytes_to_copy, rxbufsize); | ||||
|         bytes_to_copy -= MIN(bytes_to_copy, rxbufsize); | ||||
| 
 | ||||
|         /* Update the descriptor.  */ | ||||
|         if (first_desc) { | ||||
|             rx_desc_set_sof(s->rx_desc); | ||||
|             rx_desc_set_sof(s->rx_desc[q]); | ||||
|             first_desc = false; | ||||
|         } | ||||
|         if (bytes_to_copy == 0) { | ||||
|             rx_desc_set_eof(s->rx_desc); | ||||
|             rx_desc_set_length(s->rx_desc, size); | ||||
|             rx_desc_set_eof(s->rx_desc[q]); | ||||
|             rx_desc_set_length(s->rx_desc[q], size); | ||||
|         } | ||||
|         rx_desc_set_ownership(s->rx_desc); | ||||
|         rx_desc_set_ownership(s->rx_desc[q]); | ||||
| 
 | ||||
|         switch (maf) { | ||||
|         case GEM_RX_PROMISCUOUS_ACCEPT: | ||||
|             break; | ||||
|         case GEM_RX_BROADCAST_ACCEPT: | ||||
|             rx_desc_set_broadcast(s->rx_desc); | ||||
|             rx_desc_set_broadcast(s->rx_desc[q]); | ||||
|             break; | ||||
|         case GEM_RX_UNICAST_HASH_ACCEPT: | ||||
|             rx_desc_set_unicast_hash(s->rx_desc); | ||||
|             rx_desc_set_unicast_hash(s->rx_desc[q]); | ||||
|             break; | ||||
|         case GEM_RX_MULTICAST_HASH_ACCEPT: | ||||
|             rx_desc_set_multicast_hash(s->rx_desc); | ||||
|             rx_desc_set_multicast_hash(s->rx_desc[q]); | ||||
|             break; | ||||
|         case GEM_RX_REJECT: | ||||
|             abort(); | ||||
|         default: /* SAR */ | ||||
|             rx_desc_set_sar(s->rx_desc, maf); | ||||
|             rx_desc_set_sar(s->rx_desc[q], maf); | ||||
|         } | ||||
| 
 | ||||
|         /* Descriptor write-back.  */ | ||||
|         cpu_physical_memory_write(s->rx_desc_addr, | ||||
|                                   (uint8_t *)s->rx_desc, sizeof(s->rx_desc)); | ||||
|         cpu_physical_memory_write(s->rx_desc_addr[q], | ||||
|                                   (uint8_t *)s->rx_desc[q], | ||||
|                                   sizeof(s->rx_desc[q])); | ||||
| 
 | ||||
|         /* Next descriptor */ | ||||
|         if (rx_desc_get_wrap(s->rx_desc)) { | ||||
|         if (rx_desc_get_wrap(s->rx_desc[q])) { | ||||
|             DB_PRINT("wrapping RX descriptor list\n"); | ||||
|             s->rx_desc_addr = s->regs[GEM_RXQBASE]; | ||||
|             s->rx_desc_addr[q] = s->regs[GEM_RXQBASE]; | ||||
|         } else { | ||||
|             DB_PRINT("incrementing RX descriptor list\n"); | ||||
|             s->rx_desc_addr += 8; | ||||
|             s->rx_desc_addr[q] += 8; | ||||
|         } | ||||
|         gem_get_rx_desc(s); | ||||
|     } | ||||
| @ -839,6 +843,7 @@ static void gem_transmit(CadenceGEMState *s) | ||||
|     uint8_t     tx_packet[2048]; | ||||
|     uint8_t     *p; | ||||
|     unsigned    total_bytes; | ||||
|     int q = 0; | ||||
| 
 | ||||
|     /* Do nothing if transmit is not enabled. */ | ||||
|     if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) { | ||||
| @ -855,7 +860,7 @@ static void gem_transmit(CadenceGEMState *s) | ||||
|     total_bytes = 0; | ||||
| 
 | ||||
|     /* read current descriptor */ | ||||
|     packet_desc_addr = s->tx_desc_addr; | ||||
|     packet_desc_addr = s->tx_desc_addr[q]; | ||||
| 
 | ||||
|     DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr); | ||||
|     cpu_physical_memory_read(packet_desc_addr, | ||||
| @ -902,18 +907,18 @@ static void gem_transmit(CadenceGEMState *s) | ||||
|             /* Modify the 1st descriptor of this packet to be owned by
 | ||||
|              * the processor. | ||||
|              */ | ||||
|             cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first, | ||||
|             cpu_physical_memory_read(s->tx_desc_addr[q], (uint8_t *)desc_first, | ||||
|                                      sizeof(desc_first)); | ||||
|             tx_desc_set_used(desc_first); | ||||
|             cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first, | ||||
|             cpu_physical_memory_write(s->tx_desc_addr[q], (uint8_t *)desc_first, | ||||
|                                       sizeof(desc_first)); | ||||
|             /* Advance the hardware current descriptor past this packet */ | ||||
|             if (tx_desc_get_wrap(desc)) { | ||||
|                 s->tx_desc_addr = s->regs[GEM_TXQBASE]; | ||||
|                 s->tx_desc_addr[q] = s->regs[GEM_TXQBASE]; | ||||
|             } else { | ||||
|                 s->tx_desc_addr = packet_desc_addr + 8; | ||||
|                 s->tx_desc_addr[q] = packet_desc_addr + 8; | ||||
|             } | ||||
|             DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr); | ||||
|             DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]); | ||||
| 
 | ||||
|             s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL; | ||||
|             s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]); | ||||
| @ -1076,7 +1081,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) | ||||
|     switch (offset) { | ||||
|     case GEM_ISR: | ||||
|         DB_PRINT("lowering irq on ISR read\n"); | ||||
|         qemu_set_irq(s->irq, 0); | ||||
|         qemu_set_irq(s->irq[0], 0); | ||||
|         break; | ||||
|     case GEM_PHYMNTNC: | ||||
|         if (retval & GEM_PHYMNTNC_OP_R) { | ||||
| @ -1139,7 +1144,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, | ||||
|         } | ||||
|         if (!(val & GEM_NWCTRL_TXENA)) { | ||||
|             /* Reset to start of Q when transmit disabled. */ | ||||
|             s->tx_desc_addr = s->regs[GEM_TXQBASE]; | ||||
|             s->tx_desc_addr[0] = s->regs[GEM_TXQBASE]; | ||||
|         } | ||||
|         if (gem_can_receive(qemu_get_queue(s->nic))) { | ||||
|             qemu_flush_queued_packets(qemu_get_queue(s->nic)); | ||||
| @ -1150,10 +1155,10 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, | ||||
|         gem_update_int_status(s); | ||||
|         break; | ||||
|     case GEM_RXQBASE: | ||||
|         s->rx_desc_addr = val; | ||||
|         s->rx_desc_addr[0] = val; | ||||
|         break; | ||||
|     case GEM_TXQBASE: | ||||
|         s->tx_desc_addr = val; | ||||
|         s->tx_desc_addr[0] = val; | ||||
|         break; | ||||
|     case GEM_RXSTATUS: | ||||
|         gem_update_int_status(s); | ||||
| @ -1218,7 +1223,14 @@ static void gem_realize(DeviceState *dev, Error **errp) | ||||
| { | ||||
|     CadenceGEMState *s = CADENCE_GEM(dev); | ||||
| 
 | ||||
|     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); | ||||
|     if (s->num_priority_queues == 0 || | ||||
|         s->num_priority_queues > MAX_PRIORITY_QUEUES) { | ||||
|         error_setg(errp, "Invalid num-priority-queues value: %" PRIx8, | ||||
|                    s->num_priority_queues); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]); | ||||
| 
 | ||||
|     qemu_macaddr_default_if_unset(&s->conf.macaddr); | ||||
| 
 | ||||
| @ -1242,14 +1254,16 @@ static void gem_init(Object *obj) | ||||
| 
 | ||||
| static const VMStateDescription vmstate_cadence_gem = { | ||||
|     .name = "cadence_gem", | ||||
|     .version_id = 2, | ||||
|     .minimum_version_id = 2, | ||||
|     .version_id = 3, | ||||
|     .minimum_version_id = 3, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT32_ARRAY(regs, CadenceGEMState, CADENCE_GEM_MAXREG), | ||||
|         VMSTATE_UINT16_ARRAY(phy_regs, CadenceGEMState, 32), | ||||
|         VMSTATE_UINT8(phy_loop, CadenceGEMState), | ||||
|         VMSTATE_UINT32(rx_desc_addr, CadenceGEMState), | ||||
|         VMSTATE_UINT32(tx_desc_addr, CadenceGEMState), | ||||
|         VMSTATE_UINT32_ARRAY(rx_desc_addr, CadenceGEMState, | ||||
|                              MAX_PRIORITY_QUEUES), | ||||
|         VMSTATE_UINT32_ARRAY(tx_desc_addr, CadenceGEMState, | ||||
|                              MAX_PRIORITY_QUEUES), | ||||
|         VMSTATE_BOOL_ARRAY(sar_active, CadenceGEMState, 4), | ||||
|         VMSTATE_END_OF_LIST(), | ||||
|     } | ||||
| @ -1257,6 +1271,8 @@ static const VMStateDescription vmstate_cadence_gem = { | ||||
| 
 | ||||
| static Property gem_properties[] = { | ||||
|     DEFINE_NIC_PROPERTIES(CadenceGEMState, conf), | ||||
|     DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState, | ||||
|                       num_priority_queues, 1), | ||||
|     DEFINE_PROP_END_OF_LIST(), | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -32,6 +32,8 @@ | ||||
| 
 | ||||
| #define CADENCE_GEM_MAXREG        (0x00000640/4) /* Last valid GEM address */ | ||||
| 
 | ||||
| #define MAX_PRIORITY_QUEUES             8 | ||||
| 
 | ||||
| typedef struct CadenceGEMState { | ||||
|     /*< private >*/ | ||||
|     SysBusDevice parent_obj; | ||||
| @ -40,7 +42,10 @@ typedef struct CadenceGEMState { | ||||
|     MemoryRegion iomem; | ||||
|     NICState *nic; | ||||
|     NICConf conf; | ||||
|     qemu_irq irq; | ||||
|     qemu_irq irq[MAX_PRIORITY_QUEUES]; | ||||
| 
 | ||||
|     /* Static properties */ | ||||
|     uint8_t num_priority_queues; | ||||
| 
 | ||||
|     /* GEM registers backing store */ | ||||
|     uint32_t regs[CADENCE_GEM_MAXREG]; | ||||
| @ -59,12 +64,12 @@ typedef struct CadenceGEMState { | ||||
|     uint8_t phy_loop; /* Are we in phy loopback? */ | ||||
| 
 | ||||
|     /* The current DMA descriptor pointers */ | ||||
|     uint32_t rx_desc_addr; | ||||
|     uint32_t tx_desc_addr; | ||||
|     uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES]; | ||||
|     uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES]; | ||||
| 
 | ||||
|     uint8_t can_rx_state; /* Debug only */ | ||||
| 
 | ||||
|     unsigned rx_desc[2]; | ||||
|     unsigned rx_desc[MAX_PRIORITY_QUEUES][2]; | ||||
| 
 | ||||
|     bool sar_active[4]; | ||||
| } CadenceGEMState; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Alistair Francis
						Alistair Francis