From mithlesh@linsyssoft.com Fri Jan 16 18:19:57 2009 From: Mithlesh Thukral Date: Mon, 5 Jan 2009 21:13:23 +0530 (IST) Subject: Staging: sxg: New SXG_SGL design and MAC Header changes To: Greg KH Cc: Sahara Project , Richard Blackborow , Michael Miles , Christopher Harrer Message-ID: From: Mithlesh Thukral * This patch introduces the new SXG_SGL design. * Related changes to sxg_scatter_gather structure. * Introduced PSXG_X64_SGL changes which are x64 friendly * Setting the MAC HEADER pointer properly in skb before giving to higher layers. Signed-off-by: Michael Miles Signed-off-by: LinSysSoft Sahara Team Signed-off-by: Christopher Harrer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sxg/sxg.c | 194 ++++++++++++++++++++++++--------- drivers/staging/sxg/sxg.h | 31 ----- drivers/staging/sxg/sxgdbg.h | 3 drivers/staging/sxg/sxghif.h | 251 ++++++++++++++++++++++++++++--------------- drivers/staging/sxg/sxghw.h | 177 +++++++++++++++++++++++++----- 5 files changed, 464 insertions(+), 192 deletions(-) --- a/drivers/staging/sxg/sxg.c +++ b/drivers/staging/sxg/sxg.c @@ -97,7 +97,7 @@ static int sxg_entry_halt(p_net_device d static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd); static int sxg_send_packets(struct sk_buff *skb, p_net_device dev); static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb); -static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GATHER *SxgSgl); +static void sxg_dumb_sgl(struct SXG_X64_SGL *pSgl, struct SXG_SCATTER_GATHER *SxgSgl); static void sxg_handle_interrupt(struct adapter_t *adapter); static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId); @@ -114,10 +114,8 @@ static struct net_device_stats *sxg_get_ #define XXXTODO 0 -#if XXXTODO static int sxg_mac_set_address(p_net_device dev, void *ptr); static void sxg_mcast_set_list(p_net_device dev); -#endif static void sxg_adapter_set_hwaddr(struct adapter_t *adapter); @@ -622,6 +620,66 @@ static void sxg_config_pci(struct pci_de } } +static unsigned char temp_mac_address[6] = { 0x00, 0xab, 0xcd, 0xef, 0x12, 0x69 }; +/* + * sxg_read_config + * @adapter : Pointer to the adapter structure for the card + * This function will read the configuration data from EEPROM/FLASH + */ +static inline int sxg_read_config(struct adapter_t *adapter) +{ + //struct sxg_config data; + struct SW_CFG_DATA *data; + dma_addr_t p_addr; + unsigned long status; + unsigned long i; + + data = pci_alloc_consistent(adapter->pcidev, sizeof(struct SW_CFG_DATA), &p_addr); + if(!data) { + /* We cant get even this much memory. Raise a hell + * Get out of here + */ + printk(KERN_ERR"%s : Could not allocate memory for reading EEPROM\n", __FUNCTION__); + return -ENOMEM; + } + + WRITE_REG(adapter->UcodeRegs[0].ConfigStat, SXG_CFG_TIMEOUT, TRUE); + + WRITE_REG64(adapter, adapter->UcodeRegs[0].Config, p_addr, 0); + for(i=0; i<1000; i++) { + READ_REG(adapter->UcodeRegs[0].ConfigStat, status); + if (status != SXG_CFG_TIMEOUT) + break; + mdelay(1); /* Do we really need this */ + } + + switch(status) { + case SXG_CFG_LOAD_EEPROM: /*Config read from EEPROM succeeded */ + case SXG_CFG_LOAD_FLASH: /* onfig read from Flash succeeded */ + /* Copy the MAC address to adapter structure */ + memcpy(temp_mac_address, data->MacAddr[0].MacAddr, 6); + /* TODO: We are not doing the remaining part : FRU, etc */ + break; + + case SXG_CFG_TIMEOUT: + case SXG_CFG_LOAD_INVALID: + case SXG_CFG_LOAD_ERROR: + default: /* Fix default handler later */ + printk(KERN_WARNING"%s : We could not read the config word." + "Status = %ld\n", __FUNCTION__, status); + break; + } + pci_free_consistent(adapter->pcidev, sizeof(struct SW_CFG_DATA), data, p_addr); + if (adapter->netdev) { + memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6); + memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6); + } + printk("LINSYS : These are the new MAC address\n"); + sxg_dbg_macaddrs(adapter); + + return status; +} + static int sxg_entry_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_tbl_entry) { @@ -774,16 +832,13 @@ static int sxg_entry_probe(struct pci_de adapter->vendid = pci_tbl_entry->vendor; adapter->devid = pci_tbl_entry->device; adapter->subsysid = pci_tbl_entry->subdevice; - adapter->busnumber = pcidev->bus->number; adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F); adapter->functionnumber = (pcidev->devfn & 0x7); adapter->memorylength = pci_resource_len(pcidev, 0); adapter->irq = pcidev->irq; adapter->next_netdevice = head_netdevice; head_netdevice = netdev; -/* adapter->chipid = chip_idx; */ adapter->port = 0; /*adapter->functionnumber; */ - adapter->cardindex = adapter->port; /* Allocate memory and other resources */ DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __func__); @@ -798,6 +853,7 @@ static int sxg_entry_probe(struct pci_de if (sxg_download_microcode(adapter, SXG_UCODE_SAHARA)) { DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n", __func__); + sxg_read_config(adapter); sxg_adapter_set_hwaddr(adapter); } else { adapter->state = ADAPT_FAIL; @@ -816,8 +872,8 @@ static int sxg_entry_probe(struct pci_de #if SLIC_GET_STATS_ENABLED netdev->get_stats = sxg_get_stats; #endif - netdev->set_multicast_list = sxg_mcast_set_list; #endif + netdev->set_multicast_list = sxg_mcast_set_list; strcpy(netdev->name, "eth%d"); /* strcpy(netdev->name, pci_name(pcidev)); */ @@ -992,12 +1048,14 @@ static irqreturn_t sxg_isr(int irq, void return IRQ_HANDLED; } +int debug_inthandler = 0; + static void sxg_handle_interrupt(struct adapter_t *adapter) { /* unsigned char RssId = 0; */ u32 NewIsr; - if (adapter->Stats.RcvNoBuffer < 5) { + if (++debug_inthandler < 20) { DBG_ERROR("Enter sxg_handle_interrupt ISR[%x]\n", adapter->IsrCopy[0]); } @@ -1033,7 +1091,7 @@ static void sxg_handle_interrupt(struct SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr", adapter, NewIsr, 0, 0); - if (adapter->Stats.RcvNoBuffer < 5) { + if (debug_inthandler < 20) { DBG_ERROR ("Exit sxg_handle_interrupt2 after enabling interrupt\n"); } @@ -1205,14 +1263,12 @@ static u32 sxg_process_event_queue(struc #else /* CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE); */ rx_bytes = Event->Length; /* (rcvbuf->length & IRHDDR_FLEN_MSK); */ - skb_put(skb, rx_bytes); adapter->stats.rx_packets++; adapter->stats.rx_bytes += rx_bytes; #if SXG_OFFLOAD_IP_CHECKSUM skb->ip_summed = CHECKSUM_UNNECESSARY; #endif skb->dev = adapter->netdev; - skb->protocol = eth_type_trans(skb, skb->dev); netif_rx(skb); #endif } @@ -1321,12 +1377,16 @@ static void sxg_complete_slow_send(struc case SXG_SGL_DUMB: { struct sk_buff *skb; + struct SXG_SCATTER_GATHER *SxgSgl = (struct SXG_SCATTER_GATHER *)ContextType; + /* Dumb-nic send. Command context is the dumb-nic SGL */ skb = (struct sk_buff *)ContextType; + skb = SxgSgl->DumbPacket; /* Complete the send */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DmSndCmp", skb, 0, 0, 0); + printk("ASK:sxg_complete_slow_send: freeing an skb [%p]\n", skb); ASSERT(adapter->Stats.XmtQLen); adapter->Stats.XmtQLen--; /* within XmtZeroLock */ adapter->Stats.XmtOk++; @@ -1363,12 +1423,14 @@ static struct sk_buff *sxg_slow_receive( { struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; struct sk_buff *Packet; + unsigned char*data; + int i; + char dstr[128]; + char *dptr = dstr; RcvDataBufferHdr = (struct SXG_RCV_DATA_BUFFER_HDR*) Event->HostHandle; ASSERT(RcvDataBufferHdr); ASSERT(RcvDataBufferHdr->State == SXG_BUFFER_ONCARD); - ASSERT(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr) == - RcvDataBufferHdr->VirtualAddress); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event, RcvDataBufferHdr, RcvDataBufferHdr->State, RcvDataBufferHdr->VirtualAddress); @@ -1385,6 +1447,13 @@ static struct sk_buff *sxg_slow_receive( goto drop; } + printk("ASK:sxg_slow_receive: event host handle %p\n", RcvDataBufferHdr); + data = SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr); + for (i = 0; i < 32; i++) + dptr += sprintf(dptr, "%02x ", (unsigned)data[i]); + printk("ASK:sxg_slow_receive: data %s\n", dstr); + //memcpy(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), RcvDataBufferHdr->VirtualAddress, Event->Length); + /* Change buffer state to UPSTREAM */ RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; if (Event->Status & EVENT_STATUS_RCVERR) { @@ -1415,24 +1484,28 @@ static struct sk_buff *sxg_slow_receive( /* */ /* Dumb-nic frame. See if it passes our mac filter and update stats */ /* */ - if (!sxg_mac_filter(adapter, (struct ether_header*) + /* ASK if (!sxg_mac_filter(adapter, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), Event->Length)) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvFiltr", Event, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), Event->Length, 0); goto drop; - } + } */ Packet = RcvDataBufferHdr->SxgDumbRcvPacket; + SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event); + Packet->protocol = eth_type_trans(Packet, adapter->netdev); + printk("ASK:sxg_slow_receive: protocol %x\n", (unsigned) Packet->protocol); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumbRcv", RcvDataBufferHdr, Packet, Event->Length, 0); /* */ /* Lastly adjust the receive packet length. */ /* */ - SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event); + RcvDataBufferHdr->SxgDumbRcvPacket = NULL; + SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); return (Packet); drop: @@ -1666,9 +1739,9 @@ static int sxg_if_init(struct adapter_t p_net_device dev = adapter->netdev; int status = 0; - DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d:%d] flags[%x]\n", + DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d] flags[%x]\n", __func__, adapter->netdev->name, - adapter->queues_initialized, adapter->state, + adapter->state, adapter->linkstate, dev->flags); /* adapter should be down at this point */ @@ -1871,8 +1944,10 @@ static int sxg_send_packets(struct sk_bu struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); u32 status = STATUS_SUCCESS; - DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __func__, - skb); + //DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__, + // skb); + printk("ASK:sxg_send_packets: skb[%p]\n", skb); + /* Check the adapter state */ switch (adapter->State) { case SXG_STATE_INITIALIZING: @@ -1936,8 +2011,8 @@ static int sxg_send_packets(struct sk_bu */ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb) { - struct SCATTER_GATHER_LIST *pSgl; - struct SXG_SCATTER_GATHER *SxgSgl; + struct SXG_X64_SGL *pSgl; + struct SXG_SCATTER_GATHER *SxgSgl; void *SglBuffer; u32 SglBufferLength; @@ -1980,7 +2055,7 @@ static int sxg_transmit_packet(struct ad * Return Value: * None. */ -static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GATHER *SxgSgl) +static void sxg_dumb_sgl(struct SXG_X64_SGL *pSgl, struct SXG_SCATTER_GATHER *SxgSgl) { struct adapter_t *adapter = SxgSgl->adapter; struct sk_buff *skb = SxgSgl->DumbPacket; @@ -1993,15 +2068,23 @@ static void sxg_dumb_sgl(struct SCATTER_ /* unsigned int BufLen; */ /* u32 SglOffset; */ u64 phys_addr; + unsigned char*data; + int i; + char dstr[128]; + char *dptr = dstr; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl", pSgl, SxgSgl, 0, 0); + data = skb->data; + for (i = 0; i < 32; i++) + dptr += sprintf(dptr, "%02x ", (unsigned)data[i]); + printk("ASK:sxg_dumb_sgl: data %s\n", dstr); /* Set aside a pointer to the sgl */ SxgSgl->pSgl = pSgl; /* Sanity check that our SGL format is as we expect. */ - ASSERT(sizeof(SXG_X64_SGE) == sizeof(SCATTER_GATHER_ELEMENT)); + ASSERT(sizeof(struct SXG_X64_SGE) == sizeof(struct SXG_X64_SGE)); /* Shouldn't be a vlan tag on this frame */ ASSERT(SxgSgl->VlanTag.VlanTci == 0); ASSERT(SxgSgl->VlanTag.VlanTpid == 0); @@ -2050,25 +2133,14 @@ static void sxg_dumb_sgl(struct SCATTER_ phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len, PCI_DMA_TODEVICE); - XmtCmd->Buffer.FirstSgeAddress = SXG_GET_ADDR_HIGH(phys_addr); - XmtCmd->Buffer.FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress << 32; - XmtCmd->Buffer.FirstSgeAddress = - XmtCmd->Buffer.FirstSgeAddress | SXG_GET_ADDR_LOW(phys_addr); -/* XmtCmd->Buffer.FirstSgeAddress = SxgSgl->Sgl.Elements[Index].Address; */ -/* XmtCmd->Buffer.FirstSgeAddress.LowPart += MdlOffset; */ + memset(XmtCmd, '\0', sizeof(*XmtCmd)); + XmtCmd->Buffer.FirstSgeAddress = phys_addr; XmtCmd->Buffer.FirstSgeLength = DataLength; - /* Set a pointer to the remaining SGL entries */ -/* XmtCmd->Sgl = SxgSgl->PhysicalAddress; */ - /* Advance the physical address of the SxgSgl structure to */ - /* the second SGE */ -/* SglOffset = (u32)((u32 *)(&SxgSgl->Sgl.Elements[Index+1]) - */ -/* (u32 *)SxgSgl); */ -/* XmtCmd->Sgl.LowPart += SglOffset; */ XmtCmd->Buffer.SgeOffset = 0; - /* Note - TotalLength might be overwritten with MSS below.. */ XmtCmd->Buffer.TotalLength = DataLength; - XmtCmd->SgEntries = 1; /*(ushort)(SxgSgl->Sgl.NumberOfElements - Index); */ + XmtCmd->SgEntries = 1; XmtCmd->Flags = 0; + printk("ASK:sxg_dumb_sgl: wrote to xmit register\n"); /* */ /* Advance transmit cmd descripter by 1. */ /* NOTE - See comments in SxgTcpOutput where we write */ @@ -2144,11 +2216,11 @@ static int sxg_initialize_link(struct ad /* XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f) */ /* is stored with the first nibble (0a) in the byte 0 */ /* of the Mac address. Possibly reverse? */ - Value = *(u32 *) adapter->MacAddr; + Value = *(u32 *) adapter->macaddr; WRITE_REG(HwRegs->LinkAddress0Low, Value, TRUE); /* also write the MAC address to the MAC. Endian is reversed. */ WRITE_REG(HwRegs->MacAddressLow, ntohl(Value), TRUE); - Value = (*(u16 *) & adapter->MacAddr[4] & 0x0000FFFF); + Value = (*(u16 *) & adapter->macaddr[4] & 0x0000FFFF); WRITE_REG(HwRegs->LinkAddress0High, Value | LINK_ADDRESS_ENABLE, TRUE); /* endian swap for the MAC (put high bytes in bits [31:16], swapped) */ Value = ntohl(Value); @@ -2208,6 +2280,7 @@ static int sxg_initialize_link(struct ad status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ PHY_PMA_CONTROL1, /* PMA/PMD control register */ &Value); + DBG_ERROR("After sxg_read_mdio_reg Value[%x] fail=%x\n", Value, (Value & PMA_CONTROL1_RESET)); if (status != STATUS_SUCCESS) return (STATUS_FAILURE); if (Value & PMA_CONTROL1_RESET) /* reset complete if bit is 0 */ @@ -2600,7 +2673,7 @@ static int sxg_read_mdio_reg(struct adap SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO", adapter, 0, 0, 0); -/* DBG_ERROR("ENTER %s\n", __func__); */ + DBG_ERROR("ENTER %s\n", __FUNCTION__); /* Ensure values don't exceed field width */ DevAddr &= 0x001F; /* 5-bit field */ @@ -2636,6 +2709,8 @@ static int sxg_read_mdio_reg(struct adap udelay(100); /* Timeout in 100us units */ READ_REG(HwRegs->MacAmiimIndicator, ValueRead); if (--Timeout == 0) { + DBG_ERROR("EXIT %s with STATUS_FAILURE 1\n", __FUNCTION__); + return (STATUS_FAILURE); } } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY); @@ -2655,6 +2730,8 @@ static int sxg_read_mdio_reg(struct adap udelay(100); /* Timeout in 100us units */ READ_REG(HwRegs->MacAmiimIndicator, ValueRead); if (--Timeout == 0) { + DBG_ERROR("EXIT %s with STATUS_FAILURE 2\n", __FUNCTION__); + return (STATUS_FAILURE); } } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY); @@ -2663,7 +2740,7 @@ static int sxg_read_mdio_reg(struct adap READ_REG(HwRegs->MacAmiimField, *pValue); *pValue &= 0xFFFF; /* data is in the lower 16 bits */ -/* DBG_ERROR("EXIT %s\n", __func__); */ + DBG_ERROR("EXIT %s\n", __FUNCTION__); return (STATUS_SUCCESS); } @@ -2705,7 +2782,6 @@ static void sxg_mcast_init_crc32(void) } } -#if XXXTODO static u32 sxg_crc_init; /* Is table initialized */ /* * Return the MAC hast as described above. @@ -2777,7 +2853,7 @@ static void sxg_mcast_set_mask(struct ad */ static int sxg_mcast_add_list(struct adapter_t *adapter, char *address) { - p_mcast_address_t mcaddr, mlist; + struct mcast_address_t *mcaddr, *mlist; bool equaladdr; /* Check to see if it already exists */ @@ -2791,7 +2867,7 @@ static int sxg_mcast_add_list(struct ada } /* Doesn't already exist. Allocate a structure to hold it */ - mcaddr = kmalloc(sizeof(mcast_address_t), GFP_ATOMIC); + mcaddr = kmalloc(sizeof(struct mcast_address_t), GFP_ATOMIC); if (mcaddr == NULL) return 1; @@ -2829,6 +2905,13 @@ static void sxg_mcast_set_list(p_net_dev int mc_count = dev->mc_count; ASSERT(adapter); + if (dev->flags & IFF_PROMISC) { + adapter->MacFilter |= MAC_PROMISC; + } + //XXX handle other flags as well + sxg_mcast_set_mask(adapter); + +#if 0 for (i = 1; i <= mc_count; i++) { addresses = (char *)&mc_list->dmi_addr; @@ -2873,8 +2956,8 @@ static void sxg_mcast_set_list(p_net_dev } } return; -} #endif +} static void sxg_unmap_mmio_space(struct adapter_t *adapter) { @@ -3133,12 +3216,16 @@ static void sxg_allocate_rcvblock_comple SXG_RCV_DATA_BUFFER_HDR_OFFSET (BufferSize)); RcvDataBufferHdr->VirtualAddress = RcvDataBuffer; - RcvDataBufferHdr->PhysicalAddress = Paddr; RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; /* For FREE macro assertion */ RcvDataBufferHdr->Size = SXG_RCV_BUFFER_DATA_SIZE(BufferSize); SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr); + //ASK hardcoded 2048 + RcvDataBufferHdr->PhysicalAddress = pci_map_single(adapter->pcidev, + RcvDataBufferHdr->SxgDumbRcvPacket->data, + 2048, + PCI_DMA_FROMDEVICE); if (RcvDataBufferHdr->SxgDumbRcvPacket == NULL) goto fail; @@ -3240,8 +3327,6 @@ static void sxg_allocate_sgl_buffer_comp adapter, SxgSgl, Length, 0); } -static unsigned char temp_mac_address[6] = - { 0x00, 0xab, 0xcd, 0xef, 0x12, 0x69 }; static void sxg_adapter_set_hwaddr(struct adapter_t *adapter) { @@ -3262,6 +3347,7 @@ static void sxg_adapter_set_hwaddr(struc } if (adapter->netdev) { memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6); + memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6); } /* DBG_ERROR ("%s EXIT port %d\n", __func__, adapter->port); */ sxg_dbg_macaddrs(adapter); @@ -3395,6 +3481,7 @@ static int sxg_initialize_adapter(struct /* SlicCheckForHang or SlicDumpThread will take it from here. */ adapter->Dead = FALSE; adapter->PingOutstanding = FALSE; + adapter->State = SXG_STATE_RUNNING; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInit", adapter, 0, 0, 0); @@ -3448,10 +3535,16 @@ static int sxg_fill_descriptor_block(str for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; i++) { SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); ASSERT(RcvDataBufferHdr); + ASSERT(RcvDataBufferHdr->SxgDumbRcvPacket); SXG_REINIATIALIZE_PACKET(RcvDataBufferHdr->SxgDumbRcvPacket); RcvDataBufferHdr->State = SXG_BUFFER_ONCARD; RcvDescriptorBlock->Descriptors[i].VirtualAddress = (void *)RcvDataBufferHdr; + if (i == 0) + printk("ASK:sxg_fill_descriptor_block: first virt address %p\n", RcvDataBufferHdr); + if (i == (SXG_RCV_DESCRIPTORS_PER_BLOCK - 1)) + printk("ASK:sxg_fill_descriptor_block: last virt address %p\n", RcvDataBufferHdr); + RcvDescriptorBlock->Descriptors[i].PhysicalAddress = RcvDataBufferHdr->PhysicalAddress; } @@ -3503,6 +3596,7 @@ static void sxg_stock_rcv_buffers(struct ReceiveBufferSize), SXG_BUFFER_TYPE_RCV); } + printk("ASK:sxg_stock_rcv_buffers: RcvBuffersOnCard %d\n", adapter->RcvBuffersOnCard); /* Now grab the RcvQLock lock and proceed */ spin_lock(&adapter->RcvQLock); while (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) { --- a/drivers/staging/sxg/sxgdbg.h +++ b/drivers/staging/sxg/sxgdbg.h @@ -46,12 +46,13 @@ #define ATKDBG 1 #define ATK_TRACE_ENABLED 1 -#define DBG_ERROR(n, args...) printk(KERN_EMERG n, ##args) +#define DBG_ERROR(n, args...) printk(KERN_WARNING n, ##args) #ifdef ASSERT #undef ASSERT #endif +#define SXG_ASSERT_ENABLED #ifdef SXG_ASSERT_ENABLED #ifndef ASSERT #define ASSERT(a) \ --- a/drivers/staging/sxg/sxg.h +++ b/drivers/staging/sxg/sxg.h @@ -141,7 +141,7 @@ struct SXG_STATS { #define SXG_ALLOCATE_RCV_PACKET(_pAdapt, _RcvDataBufferHdr) { \ struct sk_buff * skb; \ - skb = alloc_skb(2048, GFP_ATOMIC); \ + skb = netdev_alloc_skb(_pAdapt->netdev, 2048); \ if (skb) { \ (_RcvDataBufferHdr)->skb = skb; \ skb->next = NULL; \ @@ -207,7 +207,7 @@ struct SXG_STATS { (_RcvDataBufferHdr), (_Packet), \ (_Event)->Status, 0); \ ASSERT((_Event)->Length <= (_RcvDataBufferHdr)->Size); \ - Packet->len = (_Event)->Length; \ + skb_put(Packet, (_Event)->Length); \ } /////////////////////////////////////////////////////////////////////////////// @@ -503,10 +503,6 @@ struct adapter_t { unsigned int port; struct physcard_t *physcard; unsigned int physport; - unsigned int cardindex; - unsigned int card_size; - unsigned int chipid; - unsigned int busnumber; unsigned int slotnumber; unsigned int functionnumber; ushort vendid; @@ -514,25 +510,15 @@ struct adapter_t { ushort subsysid; u32 irq; - void * sxg_adapter; - u32 nBusySend; - void __iomem * base_addr; u32 memorylength; u32 drambase; u32 dramlength; - unsigned int queues_initialized; - unsigned int allocated; unsigned int activated; u32 intrregistered; unsigned int isp_initialized; - unsigned int gennumber; - u32 curaddrupper; - u32 isrcopy; unsigned char state; unsigned char linkstate; - unsigned char linkspeed; - unsigned char linkduplex; unsigned int flags; unsigned char macaddr[6]; unsigned char currmacaddr[6]; @@ -581,8 +567,6 @@ struct adapter_t { u32 PowerState; // NDIS power state struct adapter_t *Next; // Linked list ushort AdapterID; // 1..n - unsigned char MacAddr[6]; // Our permanent HW mac address - unsigned char CurrMacAddr[6]; // Our Current mac address p_net_device netdev; p_net_device next_netdevice; struct pci_dev * pcidev; @@ -597,17 +581,11 @@ struct adapter_t { struct SXG_HW_REGS *HwRegs; // Sahara HW Register Memory (BAR0/1) struct SXG_UCODE_REGS *UcodeRegs; // Microcode Register Memory (BAR2/3) struct SXG_TCB_REGS *TcbRegs; // Same as Ucode regs - See sxghw.h - ushort ResetDpcCount; // For timeout - ushort RssDpcCount; // For timeout - ushort VendorID; // Vendor ID - ushort DeviceID; // Device ID - ushort SubSystemID; // Sub-System ID - ushort FrameSize; // Maximum frame size + ushort FrameSize; // Maximum frame size u32 * DmaHandle; // NDIS DMA handle u32 * PacketPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out u32 * BufferPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out u32 MacFilter; // NDIS MAC Filter - ushort IpId; // For slowpath struct SXG_EVENT_RING *EventRings; // Host event rings. 1/CPU to 16 max dma_addr_t PEventRings; // Physical address u32 NextEvent[SXG_MAX_RSS]; // Current location in ring @@ -690,9 +668,6 @@ struct adapter_t { // Put preprocessor-conditional fields at the end so we don't // have to recompile sxgdbg everytime we reconfigure the driver ///////////////////////////////////////////////////////////////////// - void * PendingSetRss; // Pending RSS parameter change - u32 IPv4HdrSize; // Shared 5.2/6.0 encap param - unsigned char * InterruptInfo; // Allocated by us during AddDevice #if defined(CONFIG_X86) u32 AddrUpper; // Upper 32 bits of 64-bit register #endif --- a/drivers/staging/sxg/sxghif.h +++ b/drivers/staging/sxg/sxghif.h @@ -22,7 +22,9 @@ struct SXG_UCODE_REGS { u32 RsvdReg5; // Code = 5 - TOE -NA u32 CardUp; // Code = 6 - Microcode initialized when 1 u32 RsvdReg7; // Code = 7 - TOE -NA - u32 CodeNotUsed[8]; // Codes 8-15 not used. ExCode = 0 + u32 ConfigStat; // Code = 8 - Configuration data load status + u32 RsvdReg9; // Code = 9 - TOE -NA + u32 CodeNotUsed[6]; // Codes 10-15 not used. ExCode = 0 // This brings us to ExCode 1 at address 0x40 = Interrupt status pointer u32 Isp; // Code = 0 (extended), ExCode = 1 u32 PadEx1[15]; // Codes 1-15 not used with extended codes @@ -53,7 +55,7 @@ struct SXG_UCODE_REGS { // ExCode 10 = Receive ring size u32 RcvSize; // Code = 0 (extended), ExCode = 10 u32 PadEx10[15]; - // ExCode 11 = Read EEPROM Config + // ExCode 11 = Read EEPROM/Flash Config u32 Config; // Code = 0 (extended), ExCode = 11 u32 PadEx11[15]; // ExCode 12 = Multicast bits 31:0 @@ -77,15 +79,16 @@ struct SXG_UCODE_REGS { // ExCode 18 = Slowpath Send Index Address u32 SPSendIndex; // Code = 0 (extended), ExCode = 18 u32 PadEx18[15]; - u32 RsvdXF; // Code = 0 (extended), ExCode = 19 + // ExCode 19 = Get ucode statistics + u32 GetUcodeStats; // Code = 0 (extended), ExCode = 19 u32 PadEx19[15]; - // ExCode 20 = Aggregation + // ExCode 20 = Aggregation - See sxgmisc.c:SxgSetInterruptAggregation u32 Aggregation; // Code = 0 (extended), ExCode = 20 u32 PadEx20[15]; // ExCode 21 = Receive MDL push timer u32 PushTicks; // Code = 0 (extended), ExCode = 21 u32 PadEx21[15]; - // ExCode 22 = TOE NA + // ExCode 22 = ACK Frequency u32 AckFrequency; // Code = 0 (extended), ExCode = 22 u32 PadEx22[15]; // ExCode 23 = TOE NA @@ -139,8 +142,14 @@ struct SXG_UCODE_REGS { ((((_MessageId) << SXG_ICR_MSGID_SHIFT) & \ SXG_ICR_MSGID_MASK) | (_Data)) -// The Microcode supports up to 16 RSS queues -#define SXG_MAX_RSS 16 +#define SXG_MIN_AGG_DEFAULT 0x0010 // Minimum aggregation default +#define SXG_MAX_AGG_DEFAULT 0x0040 // Maximum aggregation default +#define SXG_MAX_AGG_SHIFT 16 // Maximum in top 16 bits of register +#define SXG_AGG_XMT_DISABLE 0x80000000 // Disable interrupt aggregation on xmt + +// The Microcode supports up to 8 RSS queues +#define SXG_MAX_RSS 8 + #define SXG_MAX_RSS_TABLE_SIZE 256 // 256-byte max #define SXG_RSS_TCP6 0x00000001 // RSS TCP over IPv6 @@ -156,11 +165,15 @@ struct SXG_UCODE_REGS { #define SXG_XMT_CPUID_SHIFT 16 -#if VPCI -#define SXG_CHECK_FOR_HANG_TIME 3000 -#else +// Status returned by ucode in the ConfigStat reg (see above) when attempted +// to load configuration data from the EEPROM/Flash. +#define SXG_CFG_TIMEOUT 1 // init value - timeout if unchanged +#define SXG_CFG_LOAD_EEPROM 2 // config data loaded from EEPROM +#define SXG_CFG_LOAD_FLASH 3 // config data loaded from flash +#define SXG_CFG_LOAD_INVALID 4 // no valid config data found +#define SXG_CFG_LOAD_ERROR 5 // hardware error + #define SXG_CHECK_FOR_HANG_TIME 5 -#endif /* * TCB registers - This is really the same register memory area as UCODE_REGS @@ -176,10 +189,11 @@ struct SXG_TCB_REGS { u32 Rsvd1; /* Code = 3 - TOE NA */ u32 Rsvd2; /* Code = 4 - TOE NA */ u32 Rsvd3; /* Code = 5 - TOE NA */ - u32 Invalid; /* Code = 6 - Reserved for "CardUp" see above */ + u32 Invalid1; /* Code = 6 - Reserved for "CardUp" see above */ u32 Rsvd4; /* Code = 7 - TOE NA */ - u32 Rsvd5; /* Code = 8 - TOE NA */ - u32 Pad[7]; /* Codes 8-15 - Not used. */ + u32 Invalid2; /* Code = 8 - Reserved for "ConfigStat" see above */ + u32 Rsvd5; /* Code = 9 - TOE NA */ + u32 Pad[6]; /* Codes 10-15 - Not used. */ }; /*************************************************************************** @@ -319,7 +333,7 @@ struct SXG_EVENT { // Size must be power of 2, between 128 and 16k #define EVENT_RING_SIZE 4096 // ?? #define EVENT_RING_BATCH 16 // Hand entries back 16 at a time. -#define EVENT_BATCH_LIMIT 256 // Stop processing events after 256 (16 * 16) +#define EVENT_BATCH_LIMIT 256 // Stop processing events after 4096 (256 * 16) struct SXG_EVENT_RING { struct SXG_EVENT Ring[EVENT_RING_SIZE]; @@ -664,23 +678,22 @@ enum SXG_BUFFER_TYPE { * => Total = ~1282k/block * ***************************************************************************/ -#define SXG_RCV_DATA_BUFFERS 4096 // Amount to give to the card -#define SXG_INITIAL_RCV_DATA_BUFFERS 8192 // Initial pool of buffers -#define SXG_MIN_RCV_DATA_BUFFERS 2048 // Minimum amount and when to get more -#define SXG_MAX_RCV_BLOCKS 128 // = 16384 receive buffers +#define SXG_RCV_DATA_BUFFERS 8192 // Amount to give to the card +#define SXG_INITIAL_RCV_DATA_BUFFERS 16384 // Initial pool of buffers +#define SXG_MIN_RCV_DATA_BUFFERS 4096 // Minimum amount and when to get more +#define SXG_MAX_RCV_BLOCKS 256 // = 32k receive buffers // Receive buffer header struct SXG_RCV_DATA_BUFFER_HDR { dma_addr_t PhysicalAddress; // Buffer physical address // Note - DO NOT USE the VirtualAddress field to locate data. // Use the sxg.h:SXG_RECEIVE_DATA_LOCATION macro instead. - void *VirtualAddress; // Start of buffer - struct LIST_ENTRY FreeList; // Free queue of buffers + void *VirtualAddress; // Start of buffer + u32 Size; // Buffer size struct SXG_RCV_DATA_BUFFER_HDR *Next; // Fastpath data buffer queue - u32 Size; // Buffer size - u32 ByteOffset; // See SXG_RESTORE_MDL_OFFSET - unsigned char State; // See SXG_BUFFER state above - unsigned char Status; // Event status (to log PUSH) + struct LIST_ENTRY FreeList; // Free queue of buffers + unsigned char State; // See SXG_BUFFER state above + unsigned char Status; // Event status (to log PUSH) struct sk_buff *skb; // Double mapped (nbl and pkt) }; @@ -744,15 +757,6 @@ struct SXG_RCV_BLOCK_HDR { (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK)) + \ (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK_HDR))) -// Use the miniport reserved portion of the NBL to locate -// our SXG_RCV_DATA_BUFFER_HDR structure. -struct SXG_RCV_NBL_RESERVED { - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; - void *Available; -}; - -#define SXG_RCV_NBL_BUFFER_HDR(_NBL) (((PSXG_RCV_NBL_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(_NBL))->RcvDataBufferHdr) - /*************************************************************************** * Scatter gather list buffer ***************************************************************************/ @@ -760,6 +764,102 @@ struct SXG_RCV_NBL_RESERVED { #define SXG_MIN_SGL_BUFFERS 2048 // Minimum amount and when to get more #define SXG_MAX_SGL_BUFFERS 16384 // Maximum to allocate (note ADAPT:ushort) +// SXG_SGL_POOL_PROPERTIES - This structure is used to define a pool of SGL buffers. +// These buffers are allocated out of shared memory and used to +// contain a physical scatter gather list structure that is shared +// with the card. +// +// We split our SGL buffers into multiple pools based on size. The motivation +// is that some applications perform very large I/Os (1MB for example), so +// we need to be able to allocate an SGL to accommodate such a request. +// But such an SGL would require 256 24-byte SG entries - ~6k. +// Given that the vast majority of I/Os are much smaller than 1M, allocating +// a single pool of SGL buffers would be a horribly inefficient use of +// memory. +// +// The following structure includes two fields relating to its size. +// The NBSize field specifies the largest NET_BUFFER that can be handled +// by the particular pool. The SGEntries field defines the size, in +// entries, of the SGL for that pool. The SGEntries is determined by +// dividing the NBSize by the expected page size (4k), and then padding +// it by some appropriate amount as insurance (20% or so..??). +typedef struct _SXG_SGL_POOL_PROPERTIES { + u32 NBSize; // Largest NET_BUFFER size for this pool + ushort SGEntries; // Number of entries in SGL + ushort InitialBuffers; // Number to allocate at initializationtime + ushort MinBuffers; // When to get more + ushort MaxBuffers; // When to stop + ushort PerCpuThreshold;// See sxgh.h:SXG_RESOURCES +} SXG_SGL_POOL_PROPERTIES, *PSXG_SGL_POOL_PROPERTIES; + +// At the moment I'm going to statically initialize 4 pools: +// 100k buffer pool: The vast majority of the expected buffers are expected to +// be less than or equal to 100k. At 30 entries per and +// 8k initial buffers amounts to ~4MB of memory +// NOTE - This used to be 64K with 20 entries, but during +// WHQL NDIS 6.0 Testing (2c_mini6stress) MS does their +// best to send absurd NBL's with ridiculous SGLs, we +// have received 400byte sends contained in SGL's that +// have 28 entries +// 1M buffer pool: Buffers between 64k and 1M. Allocate 256 initial buffers +// with 300 entries each => ~2MB of memory +// 5M buffer pool: Not expected often, if at all. 32 initial buffers +// at 1500 entries each => ~1MB of memory +// 10M buffer pool: Not expected at all, except under pathelogical conditions. +// Allocate one at initialization time. +// Note - 10M is the current limit of what we can +// realistically support due to the sahara SGL +// bug described in the SAHARA SGL WORKAROUND below +// +// We will likely adjust the number of pools and/or pool properties over time.. +#define SXG_NUM_SGL_POOLS 4 +#define INITIALIZE_SGL_POOL_PROPERTIES \ +SXG_SGL_POOL_PROPERTIES SxgSglPoolProperties[SXG_NUM_SGL_POOLS] = \ +{ \ + { 102400, 30, 8192, 2048, 16384, 256}, \ + { 1048576, 300, 256, 128, 1024, 16}, \ + { 5252880, 1500, 32, 16, 512, 0}, \ + {10485760, 2700, 2, 4, 32, 0}, \ +}; + +extern SXG_SGL_POOL_PROPERTIES SxgSglPoolProperties[]; + +#define SXG_MAX_SGL_BUFFER_SIZE \ + SxgSglPoolProperties[SXG_NUM_SGL_POOLS - 1].NBSize + +// SAHARA SGL WORKAROUND!! +// The current Sahara card uses a 16-bit counter when advancing +// SGL address locations. This means that if an SGL crosses +// a 64k boundary, the hardware will actually skip back to +// the start of the previous 64k boundary, with obviously +// undesirable results. +// +// We currently workaround this issue by allocating SGL buffers +// in 64k blocks and skipping over buffers that straddle the boundary. +#define SXG_INVALID_SGL(_SxgSgl) \ + (((_SxgSgl)->PhysicalAddress.LowPart & 0xFFFF0000) != \ + (((_SxgSgl)->PhysicalAddress.LowPart + \ + SXG_SGL_SIZE((_SxgSgl)->Pool)) & 0xFFFF0000)) + +// Allocate SGLs in blocks so we can skip over invalid entries. +// We allocation 64k worth of SGL buffers, including the +// SXG_SGL_BLOCK_HDR, plus one for padding +#define SXG_SGL_BLOCK_SIZE 65536 +#define SXG_SGL_ALLOCATION_SIZE(_Pool) SXG_SGL_BLOCK_SIZE + SXG_SGL_SIZE(_Pool) + +typedef struct _SXG_SGL_BLOCK_HDR { + ushort Pool; // Associated SGL pool + struct LIST_ENTRY List; // SXG_SCATTER_GATHER blocks + dma64_addr_t PhysicalAddress;// physical address +} SXG_SGL_BLOCK_HDR, *PSXG_SGL_BLOCK_HDR; + + +// The following definition denotes the maximum block of memory that the +// card can DMA to. It is specified in the call to NdisMRegisterScatterGatherDma. +// For now, use the same value as used in the Slic/Oasis driver, which +// is 128M. That should cover any expected MDL that I can think of. +#define SXG_MAX_PHYS_MAP (1024 * 1024 * 128) + // Self identifying structure type enum SXG_SGL_TYPE { SXG_SGL_DUMB, // Dumb NIC SGL @@ -767,32 +867,6 @@ enum SXG_SGL_TYPE { SXG_SGL_CHIMNEY // Chimney offload SGL }; -// Note - the description below is Microsoft specific -// -// The following definition specifies the amount of shared memory to allocate -// for the SCATTER_GATHER_LIST portion of the SXG_SCATTER_GATHER data structure. -// The following considerations apply when setting this value: -// - First, the Sahara card is designed to read the Microsoft SGL structure -// straight out of host memory. This means that the SGL must reside in -// shared memory. If the length here is smaller than the SGL for the -// NET_BUFFER, then NDIS will allocate its own buffer. The buffer -// that NDIS allocates is not in shared memory, so when this happens, -// the SGL will need to be copied to a set of SXG_SCATTER_GATHER buffers. -// In other words.. we don't want this value to be too small. -// - On the other hand.. we're allocating up to 16k of these things. If -// we make this too big, we start to consume a ton of memory.. -// At the moment, I'm going to limit the number of SG entries to 150. -// If each entry maps roughly 4k, then this should cover roughly 600kB -// NET_BUFFERs. Furthermore, since each entry is 24 bytes, the total -// SGE portion of the structure consumes 3600 bytes, which should allow -// the entire SXG_SCATTER_GATHER structure to reside comfortably within -// a 4k block, providing the remaining fields stay under 500 bytes. -// -// So with 150 entries, the SXG_SCATTER_GATHER structure becomes roughly -// 4k. At 16k of them, that amounts to 64M of shared memory. A ton, but -// manageable. -#define SXG_SGL_ENTRIES 150 - // The ucode expects an NDIS SGL structure that // is formatted for an x64 system. When running // on an x64 system, we can simply hand the NDIS SGL @@ -806,31 +880,19 @@ struct SXG_X64_SGE { u64 Reserved; // u32 * in wdm.h. Force to 8 bytes }; -struct SCATTER_GATHER_ELEMENT { - dma64_addr_t Address; // same as wdm.h - u32 Length; // same as wdm.h - u32 CompilerPad; // The compiler pads to 8-bytes - u64 Reserved; // u32 * in wdm.h. Force to 8 bytes -}; - -struct SCATTER_GATHER_LIST { - u32 NumberOfElements; - u32 *Reserved; - struct SCATTER_GATHER_ELEMENT Elements[]; -}; - -// The card doesn't care about anything except elements, so -// we can leave the u32 * reserved field alone in the following -// SGL structure. But redefine from wdm.h:SCATTER_GATHER_LIST so -// we can specify SXG_X64_SGE and define a fixed number of elements +// Our SGL structure - Essentially the same as +// wdm.h:SCATTER_GATHER_LIST. Note the variable number of +// elements based on the pool specified above struct SXG_X64_SGL { u32 NumberOfElements; u32 *Reserved; - struct SXG_X64_SGE Elements[SXG_SGL_ENTRIES]; + struct SXG_X64_SGE Elements[1]; // Variable }; struct SXG_SCATTER_GATHER { enum SXG_SGL_TYPE Type; // FIRST! Dumb-nic or offload + ushort Pool; // Associated SGL pool + ushort Entries; // SGL total entries void *adapter; // Back pointer to adapter struct LIST_ENTRY FreeList; // Free SXG_SCATTER_GATHER blocks struct LIST_ENTRY AllList; // All SXG_SCATTER_GATHER blocks @@ -842,17 +904,40 @@ struct SXG_SCATTER_GATHER { u32 CurOffset; // Current SGL offset u32 SglRef; // SGL reference count struct VLAN_HDR VlanTag; // VLAN tag to be inserted into SGL - struct SCATTER_GATHER_LIST *pSgl; // SGL Addr. Possibly &Sgl - struct SXG_X64_SGL Sgl; // SGL handed to card + struct SXG_X64_SGL *pSgl; // SGL Addr. Possibly &Sgl + struct SXG_X64_SGL Sgl; // SGL handed to card }; +// Note - the "- 1" is because SXG_SCATTER_GATHER=>SXG_X64_SGL includes 1 SGE.. +#define SXG_SGL_SIZE(_Pool) \ + (sizeof(struct SXG_SCATTER_GATHER) + \ + ((SxgSglPoolProperties[_Pool].SGEntries - 1) * sizeof(struct SXG_X64_SGE))) + #if defined(CONFIG_X86_64) -#define SXG_SGL_BUFFER(_SxgSgl) (&_SxgSgl->Sgl) -#define SXG_SGL_BUF_SIZE sizeof(struct SXG_X64_SGL) +#define SXG_SGL_BUFFER(_SxgSgl) (&_SxgSgl->Sgl) +#define SXG_SGL_BUFFER_LENGTH(_SxgSgl) ((_SxgSgl)->Entries * sizeof(struct SXG_X64_SGE)) +#define SXG_SGL_BUF_SIZE sizeof(struct SXG_X64_SGL) #elif defined(CONFIG_X86) // Force NDIS to give us it's own buffer so we can reformat to our own -#define SXG_SGL_BUFFER(_SxgSgl) NULL +#define SXG_SGL_BUFFER(_SxgSgl) NULL +#define SXG_SGL_BUFFER_LENGTH(_SxgSgl) 0 #define SXG_SGL_BUF_SIZE 0 #else #error staging: sxg: driver is for X86 only! #endif + +/*************************************************************************** + * Microcode statistics + ***************************************************************************/ +typedef struct _SXG_UCODE_STATS { + u32 RPDQOflow; // PDQ overflow (unframed ie dq & drop 1st) + u32 XDrops; // Xmt drops due to no xmt buffer + u32 ERDrops; // Rcv drops due to ER full + u32 NBDrops; // Rcv drops due to out of host buffers + u32 PQDrops; // Rcv drops due to PDQ full + u32 BFDrops; // Rcv drops due to bad frame: no link addr match, frlen > max + u32 UPDrops; // Rcv drops due to UPFq full + u32 XNoBufs; // Xmt drop due to no DRAM Xmit buffer or PxyBuf +} SXG_UCODE_STATS, *PSXG_UCODE_STATS; + + --- a/drivers/staging/sxg/sxghw.h +++ b/drivers/staging/sxg/sxghw.h @@ -11,7 +11,7 @@ /******************************************************************************* - * Configuration space + * PCI Configuration space *******************************************************************************/ /* PCI Vendor ID */ #define SXG_VENDOR_ID 0x139A /* Alacritech's Vendor ID */ @@ -214,6 +214,11 @@ struct SXG_HW_REGS { #define RCV_CONFIG_TZIPV4 0x00800000 // Include TCP port w/ IPv4 toeplitz #define RCV_CONFIG_FLUSH 0x00400000 // Flush buffers #define RCV_CONFIG_PRIORITY_MASK 0x00300000 // Priority level +#define RCV_CONFIG_CONN_MASK 0x000C0000 // Number of connections +#define RCV_CONFIG_CONN_4K 0x00000000 // 4k connections +#define RCV_CONFIG_CONN_2K 0x00040000 // 2k connections +#define RCV_CONFIG_CONN_1K 0x00080000 // 1k connections +#define RCV_CONFIG_CONN_512 0x000C0000 // 512 connections #define RCV_CONFIG_HASH_MASK 0x00030000 // Hash depth #define RCV_CONFIG_HASH_8 0x00000000 // Hash depth 8 #define RCV_CONFIG_HASH_16 0x00010000 // Hash depth 16 @@ -526,6 +531,21 @@ struct PHY_UCODE { /***************************************************************************** + * Slow Bus Register Definitions + *****************************************************************************/ + +// Module 0 registers +#define GPIO_L_IN 0x15 // GPIO input (low) +#define GPIO_L_OUT 0x16 // GPIO output (low) +#define GPIO_L_DIR 0x17 // GPIO direction (low) +#define GPIO_H_IN 0x19 // GPIO input (high) +#define GPIO_H_OUT 0x1A // GPIO output (high) +#define GPIO_H_DIR 0x1B // GPIO direction (high) + +// Definitions for other slow bus registers can be added as needed + + +/***************************************************************************** * Transmit Sequencer Command Descriptor definitions *****************************************************************************/ @@ -613,8 +633,8 @@ struct RCV_BUF_HDR { ushort SktHash; // Socket hash unsigned char TcpHdrOffset; // TCP header offset into packet unsigned char IpHdrOffset; // IP header offset into packet - u32 TpzHash; // Toeplitz hash - ushort Reserved; // Reserved + u32 TpzHash; // Toeplitz hash + ushort Reserved; // Reserved }; #pragma pack(pop) @@ -662,26 +682,43 @@ struct RCV_BUF_HDR { /***************************************************************************** * SXG EEPROM/Flash Configuration Definitions *****************************************************************************/ -#pragma pack(push, 1) +// Location of configuration data in EEPROM or Flash +#define EEPROM_CONFIG_START_ADDR 0x00 // start addr for config info in EEPROM +#define FLASH_CONFIG_START_ADDR 0x80 // start addr for config info in Flash + +// Configuration data section defines +#define HW_CFG_SECTION_SIZE 512 // size of H/W section +#define HW_CFG_SECTION_SIZE_A 256 // size of H/W section (Sahara rev A) +#define SW_CFG_SECTION_START 512 // starting location (offset) of S/W section +#define SW_CFG_SECTION_START_A 256 // starting location (offset) of S/W section (Sahara rev A) +#define SW_CFG_SECTION_SIZE 128 // size of S/W section + +#define HW_CFG_MAGIC_WORD 0xA5A5 // H/W configuration data magic word +// Goes in Addr field of first HW_CFG_DATA entry +#define HW_CFG_TERMINATOR 0xFFFF // H/W configuration data terminator +// Goes in Addr field of last HW_CFG_DATA entry +#define SW_CFG_MAGIC_WORD 0x5A5A // S/W configuration data magic word -/* */ +#pragma pack(push, 1) +// Structure for an element of H/W configuration data. +// Read by the Sahara hardware struct HW_CFG_DATA { ushort Addr; - union { - ushort Data; - ushort Checksum; - }; + ushort Data; }; -/* */ -#define NUM_HW_CFG_ENTRIES ((128/sizeof(struct HW_CFG_DATA)) - 4) +// Number of HW_CFG_DATA structures to put in the configuration data +// data structure (SXG_CONFIG or SXG_CONFIG_A). The number is computed +// to fill the entire H/W config section of the structure. +#define NUM_HW_CFG_ENTRIES (HW_CFG_SECTION_SIZE / sizeof(struct HW_CFG_DATA)) +#define NUM_HW_CFG_ENTRIES_A (HW_CFG_SECTION_SIZE_A / sizeof(struct HW_CFG_DATA)) -/* MAC address */ +/* MAC address structure */ struct SXG_CONFIG_MAC { unsigned char MacAddr[6]; /* MAC Address */ }; -/* */ +/* FRU data structure */ struct ATK_FRU { unsigned char PartNum[6]; unsigned char Revision[2]; @@ -697,30 +734,109 @@ struct ATK_FRU { #define EMC_FRU_FORMAT 0x0005 #define NO_FRU_FORMAT 0xFFFF +#define ATK_OEM_ASSY_SIZE 10 // assy num is 9 chars plus \0 + +// OEM FRU structure for Alacritech +struct ATK_OEM { + unsigned char Assy[ATK_OEM_ASSY_SIZE]; +}; + +#define OEM_EEPROM_FRUSIZE 74 // size of OEM fru info - size +// chosen to fill out the S/W section + +union OEM_FRU { // OEM FRU information + unsigned char OemFru[OEM_EEPROM_FRUSIZE]; + struct ATK_OEM AtkOem; +}; + +// Structure to hold the S/W configuration data. +struct SW_CFG_DATA { + ushort MagicWord; // Magic word for section 2 + ushort Version; // Format version + struct SXG_CONFIG_MAC MacAddr[4]; // space for 4 MAC addresses + struct ATK_FRU AtkFru; // FRU information + ushort OemFruFormat; // OEM FRU format type + union OEM_FRU OemFru; // OEM FRU information + ushort Checksum; // Checksum of section 2 +}; + + /* EEPROM/Flash Format */ struct SXG_CONFIG { - /* */ - /* Section 1 (128 bytes) */ - /* */ - ushort MagicWord; /* EEPROM/FLASH Magic code 'A5A5' */ - ushort SpiClks; /* SPI bus clock dividers */ + /* + * H/W Section - Read by Sahara hardware (512 bytes) + */ struct HW_CFG_DATA HwCfg[NUM_HW_CFG_ENTRIES]; - /* */ - /* */ - /* */ - ushort Version; /* EEPROM format version */ - struct SXG_CONFIG_MAC MacAddr[4]; /* space for 4 MAC addresses */ - struct ATK_FRU AtkFru; /* FRU information */ - ushort OemFruFormat; /* OEM FRU format type */ - unsigned char OemFru[76]; /* OEM FRU information (optional) */ - ushort Checksum; /* Checksum of section 2 */ - /* CS info XXXTODO */ + /* + * S/W Section - Other configuration data (128 bytes) + */ + struct SW_CFG_DATA SwCfg; }; + +// EEPROM/Flash Format (Sahara rev A) +struct SXG_CONFIG_A { + /* + * H/W Section - Read by Sahara hardware (256 bytes) + */ + struct HW_CFG_DATA HwCfg[NUM_HW_CFG_ENTRIES_A]; + + /* + * S/W Section - Other configuration data (128 bytes) + */ + struct SW_CFG_DATA SwCfg; +}; + +#ifdef WINDOWS_COMPILER +// The following macro is something of a kludge, but it is the only way +// that I could find to catch certain programming errors at compile time. +// If the asserted condition is true, then nothing happens. If false, then +// the compiler tries to typedef an array with -1 members, which generates +// an error. Unfortunately, the error message is meaningless, but at least +// it catches the problem. This macro would be unnecessary if the compiler +// allowed the sizeof and offsetof macros to be used in the #if directive. +#define compile_time_assert(cond) \ + typedef char comp_error[(cond) ? 1 : -1] + +// A compiler error on either of the next two lines indicates that the SXG_CONFIG +// structure was built incorrectly. Unfortunately, the error message produced +// is meaningless. But this is apparently the only way to catch this problem +// at compile time. +compile_time_assert (offsetof(SXG_CONFIG, SwCfg) == SW_CFG_SECTION_START); +compile_time_assert (sizeof(SXG_CONFIG) == HW_CFG_SECTION_SIZE + SW_CFG_SECTION_SIZE); + +compile_time_assert (offsetof(SXG_CONFIG_A, SwCfg) == SW_CFG_SECTION_START_A); +compile_time_assert (sizeof(SXG_CONFIG_A) == HW_CFG_SECTION_SIZE_A + SW_CFG_SECTION_SIZE); +#endif +/* + * Structure used to pass information between driver and user-mode + * control application + */ +struct ADAPT_USERINFO { + bool LinkUp; + // u32 LinkState; // use LinkUp - any need for other states? + u32 LinkSpeed; // not currently needed + u32 LinkDuplex; // not currently needed + u32 Port; // not currently needed + u32 PhysPort; // not currently needed + ushort PciLanes; + unsigned char MacAddr[6]; + unsigned char CurrMacAddr[6]; + struct ATK_FRU AtkFru; + ushort OemFruFormat; + union OEM_FRU OemFru; +}; + #pragma pack(pop) /***************************************************************************** * Miscellaneous Hardware definitions *****************************************************************************/ + +// Type of ASIC in use +enum ASIC_TYPE{ + SAHARA_REV_A, + SAHARA_REV_B +}; // Sahara (ASIC level) defines #define SAHARA_GRAM_SIZE 0x020000 // GRAM size - 128 KB @@ -730,5 +846,6 @@ struct SXG_CONFIG { // Arabia (board level) defines #define FLASH_SIZE 0x080000 // 512 KB (4 Mb) -#define EEPROM_SIZE_XFMR 512 // true EEPROM size (bytes), including xfmr area -#define EEPROM_SIZE_NO_XFMR 256 // EEPROM size excluding xfmr area +#define EEPROM_SIZE_XFMR 1024 // EEPROM size (bytes), including xfmr area +#define EEPROM_SIZE_NO_XFMR 640 // EEPROM size excluding xfmr area (512 + 128) +#define EEPROM_SIZE_REV_A 512 // EEPROM size for Sahara rev A