/* rx status word 0 holds part of the status bits of the Rx DMA engine *thatgetcopiedouttomemorybytheET-1310.Word0isa32bitword *whichcontainstheFreeBufferring0and1availableoffset. * *bit0-9FBR1offset *bit10WrapflagforFBR1 *bit16-25FBR0offset *bit26WrapflagforFBR0
*/
/* RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine *thatgetcopiedouttomemorybytheET-1310.Word3isa32bitword *whichcontainsthePacketStatusRingavailableoffset. * *bit0-15reserved *bit16-27PSRoffset *bit28PSRwrap *bit29-31unused
*/
/* struct rx_status_block is a structure representing the status of the Rx *DMAengineitsitsinfreememory,andispointedtoby0x101c/0x1020
*/ struct rx_status_block {
u32 word0;
u32 word1;
};
/* TX defines */ /* word 2 of the control bits in the Tx Descriptor ring for the ET-1310 * *0-15:lengthofpacket *16-27:VLANtag *28:VLANCFI *29-31:VLANpriority * *word3ofthecontrolbitsintheTxDescriptorringfortheET-1310 * *0:lastpacketinthesequence *1:firstpacketinthesequence *2:interrupttheprocessorwhenthispktsent *3:Controlword-nopacketdata *4:Issuehalf-duplexbackpressure:XON/XOFF *5:sendpauseframe *6:Txframehaserror *7:appendCRC *8:MACoverride *9:padpacket *10:PacketisaHugepacket *11:appendVLANtag *12:IPchecksumassist *13:TCPchecksumassist *14:UDPchecksumassist
*/ #define TXDESC_FLAG_LASTPKT 0x0001 #define TXDESC_FLAG_FIRSTPKT 0x0002 #define TXDESC_FLAG_INTPROC 0x0004
/* struct tx_desc represents each descriptor on the ring */ struct tx_desc {
u32 addr_hi;
u32 addr_lo;
u32 len_vlan; /* control words how to xmit the */
u32 flags; /* data (detailed above) */
};
/* The status of the Tx DMA engine it sits in free memory, and is pointed to *by0x101c/0x1020.ThisisaDMA10type
*/
/* TCB (Transmit Control Block: Host Side) */ struct tcb { struct tcb *next; /* Next entry in ring */
u32 count; /* Used to spot stuck/lost packets */
u32 stale; /* Used to spot stuck/lost packets */ struct sk_buff *skb; /* Network skb we are tied to */
u32 index; /* Ring indexes */
u32 index_start;
};
/* Structure representing our local reference(s) to the ring */ struct tx_ring { /* TCB (Transmit Control Block) memory and lists */ struct tcb *tcb_ring;
/* List of TCBs that are ready to be used */ struct tcb *tcb_qhead; struct tcb *tcb_qtail;
/* list of TCBs that are currently being sent. */ struct tcb *send_head; struct tcb *send_tail; int used;
/* The actual descriptor ring */ struct tx_desc *tx_desc_ring;
dma_addr_t tx_desc_ring_pa;
/* send_idx indicates where we last wrote to in the descriptor ring. */
u32 send_idx;
/* The location of the write-back status block */
u32 *tx_status;
dma_addr_t tx_status_pa;
/* Packets since the last IRQ: used for interrupt coalescing */ int since_irq;
};
/* Do not change these values: if changed, then change also in respective *TXdmaandRxdmaengines
*/ #define NUM_DESC_PER_RING_TX 512/* TX Do not change these values */ #define NUM_TCB 64
/* These values are all superseded by registry entries to facilitate tuning. *Oncethedesiredperformancehasbeenachieved,theoptimalregistryvalues *shouldbere-populatedtothese#defines:
*/ #define TX_ERROR_PERIOD 1000
spinlock_t tcb_send_qlock; /* protects the tx_ring send tcb list */
spinlock_t tcb_ready_qlock; /* protects the tx_ring ready tcb list */
spinlock_t rcv_lock; /* protects the rx_ring receive list */
/* Packet Filter and look ahead size */
u32 packet_filter;
/* multicast list */
u32 multicast_addr_count;
u8 multicast_list[NIC_MAX_MCAST_LIST][ETH_ALEN];
/* Pointer to the device's PCI register space */ struct address_map __iomem *regs;
/* Registry parameters */
u8 wanted_flow; /* Flow we want for 802.3x flow control */
u32 registry_jumbo_packet; /* Max supported ethernet packet size */
/* Derived from the registry: */
u8 flow; /* flow control validated by the far-end */
/* 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and *bits7,1:0bothequalto1,atleastonceafterreset. *Subsequentoperationsneedonlytocheckthatbits1:0areequal *to1priortostartingasinglebyteread/write
*/ for (i = 0; i < MAX_NUM_REGISTER_POLLS; i++) { if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP, ®)) return -EIO;
/* I2C idle and Phy Queue Avail both true */ if ((reg & 0x3000) == 0x3000) { if (status)
*status = reg; return reg & 0xFF;
}
} return -ETIMEDOUT;
}
staticint eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
{ struct pci_dev *pdev = adapter->pdev; int index = 0; int retries; int err = 0; int writeok = 0;
u32 status;
u32 val = 0;
/* For an EEPROM, an I2C single byte write is defined as a START *conditionfollowedbythedeviceaddress,EEPROMaddress,onebyte *ofdataandaSTOPcondition.TheSTOPconditionwilltriggerthe *EEPROM'sinternallytimedwritecycletothenonvolatilememory. *AllinputsaredisabledduringthiswritecycleandtheEEPROMwill *notrespondtoanyaccessuntiltheinternalwriteiscomplete.
*/
err = eeprom_wait_ready(pdev, NULL); if (err < 0) return err;
/* 2. Write to the LBCIF Control Register: bit 7=1, bit 6=1, bit 3=0, *andbits1:0both=0.Bit5shouldbesetaccordingtothe *typeofEEPROMbeingaccessed(1=twobyteaddressing,0=one *byteaddressing).
*/ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
LBCIF_CONTROL_LBCIF_ENABLE |
LBCIF_CONTROL_I2C_WRITE)) return -EIO;
/* Prepare EEPROM address for Step 3 */ for (retries = 0; retries < MAX_NUM_WRITE_RETRIES; retries++) { if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr)) break; /* Write the data to the LBCIF Data Register (the I2C write *willbegin).
*/ if (pci_write_config_byte(pdev, LBCIF_DATA_REGISTER, data)) break; /* Monitor bit 1:0 of the LBCIF Status Register. When bits *1:0arebothequalto1,theI2Cwritehascompletedandthe *internalwritecycleoftheEEPROMisabouttostart. *(bits1:0=01isalegalstatewhilewaitingfromboth *equalto1,butbits1:0=10isinvalidandimpliesthat *somethingisbroken).
*/
err = eeprom_wait_ready(pdev, &status); if (err < 0) return0;
/* Check bit 3 of the LBCIF Status Register. If equal to 1, *anerrorhasoccurred.Don'tbreakhereifwearerevision *1,thisissowedoablindwriteforloadbug.
*/ if ((status & LBCIF_STATUS_GENERAL_ERROR) &&
adapter->pdev->revision == 0) break;
/* Check bit 2 of the LBCIF Status Register. If equal to 1 an *ACKerrorhasoccurredontheaddressphaseofthewrite. *Thiscouldbeduetoanactualhardwarefailureorthe *EEPROMmaystillbeinitsinternalwritecyclefroma *previouswrite.Thiswriteoperationwasignoredandmustbe *repeatedlater.
*/ if (status & LBCIF_STATUS_ACK_ERROR) { /* This could be due to an actual hardware failure *ortheEEPROMmaystillbeinitsinternalwrite *cyclefromapreviouswrite.Thiswriteoperation *wasignoredandmustberepeatedlater.
*/
udelay(10); continue;
}
writeok = 1; break;
}
udelay(10);
while (1) { if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
LBCIF_CONTROL_LBCIF_ENABLE))
writeok = 0;
/* Do read until internal ACK_ERROR goes away meaning write *completed
*/ do {
pci_write_config_dword(pdev,
LBCIF_ADDRESS_REGISTER,
addr); do {
pci_read_config_dword(pdev,
LBCIF_DATA_REGISTER,
&val);
} while ((val & 0x00010000) == 0);
} while (val & 0x00040000);
if ((val & 0xFF00) != 0xC000 || index == 10000) break;
index++;
} return writeok ? 0 : -EIO;
}
/* A single byte read is similar to the single byte write, with the *exceptionofthedataflow:
*/
err = eeprom_wait_ready(pdev, NULL); if (err < 0) return err; /* Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0, *andbits1:0both=0.Bit5shouldbesetaccordingtothetype *ofEEPROMbeingaccessed(1=twobyteaddressing,0=onebyte *addressing).
*/ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
LBCIF_CONTROL_LBCIF_ENABLE)) return -EIO; /* Write the address to the LBCIF Address Register (I2C read will *begin).
*/ if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr)) return -EIO; /* Monitor bit 0 of the LBCIF Status Register. When = 1, I2C read *iscomplete.(ifbit1=1andbit0stays=0,ahardwarefailure *hasoccurred).
*/
err = eeprom_wait_ready(pdev, &status); if (err < 0) return err; /* Regardless of error status, read data byte from LBCIF Data *Register.
*/
*pdata = err;
/* THIS IS A WORKAROUND: *Ineedtocallthisfunctiontwicetogetmycardina *LGM1ExpressDualrunning.Itriedalsoamsleepbeforethis *function,becauseIthoughttherecouldbesometimeconditions *butitdidn'twork.Callthewholefunctiontwicealsowork.
*/ if (pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, &eestatus)) {
dev_err(&pdev->dev, "Could not read PCI config space for EEPROM Status\n"); return -EIO;
}
/* Determine if the error(s) we care about are present. If they are *presentweneedtofail.
*/ if (eestatus & 0x4C) { int write_failed = 0;
if (pdev->revision == 0x01) { int i; staticconst u8 eedata[4] = { 0xFE, 0x13, 0x10, 0xFF };
/* Re-write the first 4 bytes if we have an eeprom *presentandtherevisionidis1,thisfixesthe *corruptionseenwith1310BSilicon
*/ for (i = 0; i < 3; i++) if (eeprom_write(adapter, i, eedata[i]) < 0)
write_failed = 1;
} if (pdev->revision != 0x01 || write_failed) {
dev_err(&pdev->dev, "Fatal EEPROM Status Error - 0x%04x\n",
eestatus);
/* This error could mean that there was an error *readingtheeepromorthattheeepromdoesn'texist. *Wewilltreateachcasethesameandnottryto *gatheradditionalinformationthatnormallywould *comefromtheeeprom,likeMACAddress
*/
adapter->has_eeprom = false; return -EIO;
}
}
adapter->has_eeprom = true;
/* Read the EEPROM for information regarding LED behavior. Refer to *et131x_xcvr_init()foritsuse.
*/
eeprom_read(adapter, 0x70, &adapter->eeprom_data[0]);
eeprom_read(adapter, 0x71, &adapter->eeprom_data[1]);
if (adapter->eeprom_data[0] != 0xcd) /* Disable all optional features */
adapter->eeprom_data[1] = 0x00;
return0;
}
staticvoid et131x_rx_dma_enable(struct et131x_adapter *adapter)
{ /* Setup the receive dma configuration register for normal operation */
u32 csr = ET_RXDMA_CSR_FBR1_ENABLE; struct rx_ring *rx_ring = &adapter->rx_ring;
/* First we need to reset everything. Write to MAC configuration *register1toperformreset.
*/
writel(ET_MAC_CFG1_SOFT_RESET | ET_MAC_CFG1_SIM_RESET |
ET_MAC_CFG1_RESET_RXMC | ET_MAC_CFG1_RESET_TXMC |
ET_MAC_CFG1_RESET_RXFUNC | ET_MAC_CFG1_RESET_TXFUNC,
¯egs->cfg1);
/* Next lets configure the MAC Inter-packet gap register */
ipg = 0x38005860; /* IPG1 0x38 IPG2 0x58 B2B 0x60 */
ipg |= 0x50 << 8; /* ifg enforce 0x50 */
writel(ipg, ¯egs->ipg);
/* Next lets configure the MAC Half Duplex register */ /* BEB trunc 0xA, Ex Defer, Rexmit 0xF Coll 0x37 */
writel(0x00A1F037, ¯egs->hfdp);
/* Next lets configure the MAC Interface Control register */
writel(0, ¯egs->if_ctrl);
/* Next lets configure the MAC Station Address register. These *valuesarereadfromtheEEPROMduringinitializationandstored *intheadapterstructure.Wewritewhatisstoredintheadapter *structuretotheMACStationAddressregistershighandlow.This *stationaddressisusedforgeneratingandcheckingpausecontrol *packets.
*/
station2 = (adapter->addr[1] << ET_MAC_STATION_ADDR2_OC2_SHIFT) |
(adapter->addr[0] << ET_MAC_STATION_ADDR2_OC1_SHIFT);
station1 = (adapter->addr[5] << ET_MAC_STATION_ADDR1_OC6_SHIFT) |
(adapter->addr[4] << ET_MAC_STATION_ADDR1_OC5_SHIFT) |
(adapter->addr[3] << ET_MAC_STATION_ADDR1_OC4_SHIFT) |
adapter->addr[2];
writel(station1, ¯egs->station_addr_1);
writel(station2, ¯egs->station_addr_2);
/* Max ethernet packet in bytes that will be passed by the mac without *beingtruncated.AllowtheMACtopass4morethanourmaxpacket *size.Thisis4fortheEthernetCRC. * *Packetslargerthan(registry_jumbo_packet)thatdonotcontaina *VLANIDwillbedroppedbytheRxfunction.
*/
writel(adapter->registry_jumbo_packet + 4, ¯egs->max_fm_len);
/* clear out MAC config reset */
writel(0, ¯egs->cfg1);
}
/* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision *themulti-castLIST.IfitisNOTspecified,(and"ALL"isnot *specified)thenweshouldpassNOmulti-castaddressestothe *driver.
*/ if (adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST) { int i;
/* Loop through our multicast array and set up the device */ for (i = 0; i < adapter->multicast_addr_count; i++) {
u32 result;
result = ether_crc(6, adapter->multicast_list[i]);
/* Write out the new hash to the device */ if (!et1310_in_phy_coma(adapter)) {
writel(hash1, &rxmac->multi_hash1);
writel(hash2, &rxmac->multi_hash2);
writel(hash3, &rxmac->multi_hash3);
writel(hash4, &rxmac->multi_hash4);
}
}
/* Set up unicast packet filter reg 3 to be the first two octets of *theMACaddressforbothaddress * *Setupunicastpacketfilterreg2tobetheoctets2-5ofthe *MACaddressforsecondaddress * *Setupunicastpacketfilterreg3tobetheoctets2-5ofthe *MACaddressforfirstaddress
*/
uni_pf3 = (adapter->addr[0] << ET_RX_UNI_PF_ADDR2_1_SHIFT) |
(adapter->addr[1] << ET_RX_UNI_PF_ADDR2_2_SHIFT) |
(adapter->addr[0] << ET_RX_UNI_PF_ADDR1_1_SHIFT) |
adapter->addr[1];
/* Disable the MAC while it is being configured (also disable WOL) */
writel(0x8, &rxmac->ctrl);
/* Initialize WOL to disabled. */
writel(0, &rxmac->crc0);
writel(0, &rxmac->crc12);
writel(0, &rxmac->crc34);
/* We need to set the WOL mask0 - mask4 next. We initialize it to *itsdefaultValuesof0x00000000becausetherearenotWOLmasks *asofthistime.
*/ for (wolw = &rxmac->mask0_word0; wolw <= &rxmac->mask4_word3; wolw++)
writel(0, wolw);
/* Let's initialize the Multicast hash */ if (!(adapter->packet_filter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
pf_ctrl |= ET_RX_PFCTRL_MLTCST_FILTER_ENABLE;
et1310_setup_device_for_multicast(adapter);
}
/* Runt packet filtering. Didn't work in version A silicon. */
pf_ctrl |= (NIC_MIN_PACKET_SIZE + 4) << ET_RX_PFCTRL_MIN_PKT_SZ_SHIFT;
pf_ctrl |= ET_RX_PFCTRL_FRAG_FILTER_ENABLE;
if (adapter->registry_jumbo_packet > 8192) /* In order to transmit jumbo packets greater than 8k, the *FIFObetweenRxMACandRxDMAneedstobereducedinsize *to(16k-Jumbopacketsize).Inordertoimplementthis, *wemustuse"cutthrough"modeintheRxMAC,whichchops *packetsdownintosegmentswhichare(max_size*16).In *thiscaseweselected256bytes,sincethisisthesizeof *thePCI-ExpressTLP'sthatthe1310uses. * *seg_enon,fc_enoff,size0x10
*/
writel(0x41, &rxmac->mcif_ctrl_max_seg); else
writel(0, &rxmac->mcif_ctrl_max_seg);
/* We need to update the Control Frame Parameters *cfpt-controlframepausetimersetto64(0x40) *cfep-controlframeextendedpausetimersetto0x0
*/ if (adapter->flow == FLOW_NONE)
writel(0, &txmac->cf_param); else
writel(0x40, &txmac->cf_param);
}
/* initialize all the macstat registers to zero on the device */ for (reg = &macstat->txrx_0_64_byte_frames;
reg <= &macstat->carry_reg2; reg++)
writel(0, reg);
/* Unmask any counters that we want to track the overflow of. *Initiallythiswillbeallcounters.Itmaybecomeclearlater *thatwedonotneedtotrackallcounters.
*/
writel(0xFFFFBE32, &macstat->carry_reg1_mask);
writel(0xFFFE7E8B, &macstat->carry_reg2_mask);
}
/* Save a local copy of the registers we are dealing with so we can *setthemback
*/
mii_addr = readl(&mac->mii_mgmt_addr);
mii_cmd = readl(&mac->mii_mgmt_cmd);
/* Stop the current operation */
writel(0, &mac->mii_mgmt_cmd);
/* Set up the register we need to read from on the correct PHY */
writel(ET_MAC_MII_ADDR(addr, reg), &mac->mii_mgmt_addr);
writel(0x1, &mac->mii_mgmt_cmd);
do {
udelay(50);
delay++;
mii_indicator = readl(&mac->mii_mgmt_indicator);
} while ((mii_indicator & ET_MAC_MGMT_WAIT) && delay < 50);
/* If we hit the max delay, we could not read the register */ if (delay == 50) {
dev_warn(&adapter->pdev->dev, "reg 0x%08x could not be read\n", reg);
dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
mii_indicator);
status = -EIO; goto out;
}
/* If we hit here we were able to read the register and we need to *returnthevaluetothecaller
*/
*value = readl(&mac->mii_mgmt_stat) & ET_MAC_MIIMGMT_STAT_PHYCRTL_MASK;
out: /* Stop the read operation */
writel(0, &mac->mii_mgmt_cmd);
/* set the registers we touched back to the state at which we entered *thisfunction
*/
writel(mii_addr, &mac->mii_mgmt_addr);
writel(mii_cmd, &mac->mii_mgmt_cmd);
/* Save a local copy of the registers we are dealing with so we can *setthemback
*/
mii_addr = readl(&mac->mii_mgmt_addr);
mii_cmd = readl(&mac->mii_mgmt_cmd);
/* Stop the current operation */
writel(0, &mac->mii_mgmt_cmd);
/* Set up the register we need to write to on the correct PHY */
writel(ET_MAC_MII_ADDR(addr, reg), &mac->mii_mgmt_addr);
/* Add the value to write to the registers to the mac */
writel(value, &mac->mii_mgmt_ctrl);
do {
udelay(50);
delay++;
mii_indicator = readl(&mac->mii_mgmt_indicator);
} while ((mii_indicator & ET_MAC_MGMT_BUSY) && delay < 100);
/* If we hit the max delay, we could not write the register */ if (delay == 100) {
u16 tmp;
dev_warn(&adapter->pdev->dev, "reg 0x%08x could not be written", reg);
dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
mii_indicator);
dev_warn(&adapter->pdev->dev, "command is 0x%08x\n",
readl(&mac->mii_mgmt_cmd));
et131x_mii_read(adapter, reg, &tmp);
status = -EIO;
} /* Stop the write operation */
writel(0, &mac->mii_mgmt_cmd);
/* set the registers we touched back to the state at which we entered *thisfunction
*/
writel(mii_addr, &mac->mii_mgmt_addr);
writel(mii_cmd, &mac->mii_mgmt_cmd);
/* Read the interrupt bits from the register(s). These are Clear On *Write.
*/
carry_reg1 = readl(&adapter->regs->macstat.carry_reg1);
carry_reg2 = readl(&adapter->regs->macstat.carry_reg2);
et131x_mii_read(adapter, MII_BMCR, &data);
data &= ~BMCR_PDOWN; if (down)
data |= BMCR_PDOWN;
et131x_mii_write(adapter, phydev->mdio.addr, MII_BMCR, data);
}
/* et131x_xcvr_init - Init the phy if we are setting it into force mode */ staticvoid et131x_xcvr_init(struct et131x_adapter *adapter)
{
u16 lcr2; struct phy_device *phydev = adapter->netdev->phydev;
/* Set the LED behavior such that LED 1 indicates speed (off = *10Mbits,blink=100Mbits,on=1000Mbits)andLED2indicates *linkandactivity(onforlink,blinkoffforactivity). * *NOTE:Somecustomizationshavebeenaddedhereforspecific *vendors;TheLEDbehaviorisnowdeterminedbyvendordatainthe *EEPROM.However,theabovedescriptionisthedefault.
*/ if ((adapter->eeprom_data[1] & 0x4) == 0) {
et131x_mii_read(adapter, PHY_LED_2, &lcr2);
/* Set the address and parameters of the packet status ring */
writel(upper_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_hi);
writel(lower_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_lo);
writel(rx_local->psr_entries - 1, &rx_dma->psr_num_des);
writel(0, &rx_dma->psr_full_offset);
/* Now's the best time to initialize FBR contents */
fbr_entry = fbr->ring_virtaddr; for (entry = 0; entry < fbr->num_entries; entry++) {
fbr_entry->addr_hi = fbr->bus_high[entry];
fbr_entry->addr_lo = fbr->bus_low[entry];
fbr_entry->word2 = entry;
fbr_entry++;
}
/* Set the address and parameters of Free buffer ring 1 and 0 */
writel(upper_32_bits(fbr->ring_physaddr), base_hi);
writel(lower_32_bits(fbr->ring_physaddr), base_lo);
writel(fbr->num_entries - 1, num_des);
writel(ET_DMA10_WRAP, full_offset);
/* This variable tracks the free buffer ring 1 full position, *soithastomatchtheabove.
*/
fbr->local_full = ET_DMA10_WRAP;
writel(((fbr->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
min_des);
}
/* Program the number of packets we will receive before generating an *interrupt. *ForversionBsilicon,thisvaluegetsupdatedonceautonegis *complete.
*/
writel(PARM_RX_NUM_BUFS_DEF, &rx_dma->num_pkt_done);
/* The "time_done" is not working correctly to coalesce interrupts *afteragiventimeperiod,butratherisgivingusaninterrupt *regardlessofwhetherwehavereceivedpackets. *Thisvaluegetsupdatedonceautonegiscomplete.
*/
writel(PARM_RX_TIME_INT_DEF, &rx_dma->max_pkt_time);
/* et131x_config_tx_dma_regs - Set up the tx dma section of the JAGCore. * *Configurethetransmitenginewiththeringbufferswehavecreated *andprepareitforuse.
*/ staticvoid et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
{ struct txdma_regs __iomem *txdma = &adapter->regs->txdma; struct tx_ring *tx_ring = &adapter->tx_ring;
/* Load the hardware with the start of the transmit descriptor ring. */
writel(upper_32_bits(tx_ring->tx_desc_ring_pa), &txdma->pr_base_hi);
writel(lower_32_bits(tx_ring->tx_desc_ring_pa), &txdma->pr_base_lo);
/* et131x_adapter_setup - Set the adapter up as per cassini+ documentation */ staticvoid et131x_adapter_setup(struct et131x_adapter *adapter)
{
et131x_configure_global_regs(adapter);
et1310_config_mac_regs1(adapter);
/* Configure the MMC registers */ /* All we need to do is initialize the Memory Control Register */
writel(ET_MMC_ENABLE, &adapter->regs->mmc.mmc_ctrl);
/* Restore the GbE PHY speed and duplex modes; *ResetJAGCore;re-configureandinitializeJAGCoreandgigEPHY
*/
/* Re-initialize the send structures */
et131x_init_send(adapter);
/* Bring the device back to the state it was during init prior to *autonegotiationbeingcomplete.Thisway,whenwegettheauto-neg *completeinterrupt,wecancompleteinitbycallingConfigMacREGS2.
*/
et131x_soft_reset(adapter);
et131x_adapter_setup(adapter);
/* Allow Tx to restart */
adapter->flags &= ~FMP_ADAPTER_LOWER_POWER;
tmp_free_buff_ring++; /* This works for all cases where limit < 1024. The 1023 case *worksbecause1023++is1024whichmeanstheifconditionisnot *takenbutthecarryofthebitintothewrapbittogglesthewrap *valuecorrectly
*/ if ((tmp_free_buff_ring & ET_DMA10_MASK) > limit) {
tmp_free_buff_ring &= ~ET_DMA10_MASK;
tmp_free_buff_ring ^= ET_DMA10_WRAP;
} /* For the 1023 case */
tmp_free_buff_ring &= (ET_DMA10_MASK | ET_DMA10_WRAP);
*free_buff_ring = tmp_free_buff_ring; return tmp_free_buff_ring;
}
for (id = 0; id < NUM_FBRS; id++) {
fbr = rx_ring->fbr[id]; /* Allocate an area of memory for Free Buffer Ring */
bufsize = sizeof(struct fbr_desc) * fbr->num_entries;
fbr->ring_virtaddr = dma_alloc_coherent(&adapter->pdev->dev,
bufsize,
&fbr->ring_physaddr,
GFP_KERNEL); if (!fbr->ring_virtaddr) {
dev_err(&adapter->pdev->dev, "Cannot alloc memory for Free Buffer Ring %d\n",
id); return -ENOMEM;
}
}
for (id = 0; id < NUM_FBRS; id++) {
fbr = rx_ring->fbr[id];
fbr_chunksize = (FBR_CHUNKS * fbr->buffsize);
for (i = 0; i < fbr->num_entries / FBR_CHUNKS; i++) {
dma_addr_t fbr_physaddr;
if (!fbr->mem_virtaddrs[i]) {
dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM;
}
/* See NOTE in "Save Physical Address" comment above */
fbr_physaddr = fbr->mem_physaddrs[i];
for (j = 0; j < FBR_CHUNKS; j++) {
u32 k = (i * FBR_CHUNKS) + j;
/* Save the Virtual address of this index for *quickaccesslater
*/
fbr->virt[k] = (u8 *)fbr->mem_virtaddrs[i] +
(j * fbr->buffsize);
/* now store the physical address in the *descriptorsothedevicecanaccessit
*/
fbr->bus_high[k] = upper_32_bits(fbr_physaddr);
fbr->bus_low[k] = lower_32_bits(fbr_physaddr);
fbr_physaddr += fbr->buffsize;
}
}
}
/* Allocate an area of memory for FIFO of Packet Status ring entries */
psr_size = sizeof(struct pkt_stat_desc) * rx_ring->psr_entries;
if (!rx_ring->ps_ring_virtaddr) {
dev_err(&adapter->pdev->dev, "Cannot alloc memory for Packet Status Ring\n"); return -ENOMEM;
}
/* Allocate an area of memory for writeback of status information */
rx_ring->rx_status_block = dma_alloc_coherent(&adapter->pdev->dev, sizeof(struct rx_status_block),
&rx_ring->rx_status_bus,
GFP_KERNEL); if (!rx_ring->rx_status_block) {
dev_err(&adapter->pdev->dev, "Cannot alloc memory for Status Block\n"); return -ENOMEM;
}
rx_ring->num_rfd = NIC_DEFAULT_NUM_RFD;
/* The RFDs are going to be put on lists later on, so initialize the *listsnow.
*/
INIT_LIST_HEAD(&rx_ring->recv_list); return0;
}
/* Free Free Buffer Rings */ for (id = 0; id < NUM_FBRS; id++) {
fbr = rx_ring->fbr[id];
if (!fbr || !fbr->ring_virtaddr) continue;
/* First the packet memory */ for (ii = 0; ii < fbr->num_entries / FBR_CHUNKS; ii++) { if (fbr->mem_virtaddrs[ii]) {
bufsize = fbr->buffsize * FBR_CHUNKS;
/* Free area of memory for the writeback of status information */ if (rx_ring->rx_status_block) {
dma_free_coherent(&adapter->pdev->dev, sizeof(struct rx_status_block),
rx_ring->rx_status_block,
rx_ring->rx_status_bus);
rx_ring->rx_status_block = NULL;
}
/* Free the FBR Lookup Table */
kfree(rx_ring->fbr[0]);
kfree(rx_ring->fbr[1]);
/* Setup each RFD */ for (rfdct = 0; rfdct < rx_ring->num_rfd; rfdct++) {
rfd = kzalloc(sizeof(*rfd), GFP_ATOMIC | GFP_DMA); if (!rfd) return -ENOMEM;
rfd->skb = NULL;
/* Add this RFD to the recv_list */
list_add_tail(&rfd->list_node, &rx_ring->recv_list);
/* Increment the available RFD's */
rx_ring->num_ready_recv++;
}
return0;
}
/* et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate */ staticvoid et131x_set_rx_dma_timer(struct et131x_adapter *adapter)
{ struct phy_device *phydev = adapter->netdev->phydev;
/* For version B silicon, we do not use the RxDMA timer for 10 and 100 *Mbits/slinerates.WedonotenableandRxDMAinterruptcoalescing.
*/ if ((phydev->speed == SPEED_100) || (phydev->speed == SPEED_10)) {
writel(0, &adapter->regs->rxdma.max_pkt_time);
writel(1, &adapter->regs->rxdma.num_pkt_done);
}
}
/* nic_return_rfd - Recycle a RFD and put it back onto the receive list */ staticvoid nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
{ struct rx_ring *rx_local = &adapter->rx_ring; struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma;
u16 buff_index = rfd->bufferindex;
u8 ring_index = rfd->ringindex; unsignedlong flags; struct fbr_lookup *fbr = rx_local->fbr[ring_index];
/* We don't use any of the OOB data besides status. Otherwise, we *needtocleanupOOBdata
*/ if (buff_index < fbr->num_entries) {
u32 free_buff_ring;
u32 __iomem *offset; struct fbr_desc *next;
/* The processing on this RFD is done, so put it back on the tail of *ourlist
*/
spin_lock_irqsave(&adapter->rcv_lock, flags);
list_add_tail(&rfd->list_node, &rx_local->recv_list);
rx_local->num_ready_recv++;
spin_unlock_irqrestore(&adapter->rcv_lock, flags);
/* RX Status block is written by the DMA engine prior to every *interrupt.ItcontainsthenexttobeusedentryinthePacket *StatusRing,andalsothetwoFreeBufferrings.
*/
status = rx_local->rx_status_block;
word1 = status->word1 >> 16;
/* Check the PSR and wrap bits do not match */ if ((word1 & 0x1FFF) == (rx_local->local_psr_full & 0x1FFF)) return NULL; /* Looks like this ring is not updated yet */
/* The packet status ring indicates that data is available. */
psr = (struct pkt_stat_desc *)(rx_local->ps_ring_virtaddr) +
(rx_local->local_psr_full & 0xFFF);
/* Grab any information that is required once the PSR is advanced, *sincewecannolongerrelyonthememorybeingaccurate
*/
len = psr->word1 & 0xFFFF;
ring_index = (psr->word1 >> 26) & 0x03;
fbr = rx_local->fbr[ring_index];
buff_index = (psr->word1 >> 16) & 0x3FF;
word0 = psr->word0;
/* Indicate that we have used this PSR entry. */ /* FIXME wrap 12 */
add_12bit(&rx_local->local_psr_full, 1); if ((rx_local->local_psr_full & 0xFFF) > rx_local->psr_entries - 1) { /* Clear psr full and toggle the wrap bit */
rx_local->local_psr_full &= ~0xFFF;
rx_local->local_psr_full ^= 0x1000;
}
if (ring_index > 1 || buff_index > fbr->num_entries - 1) { /* Illegal buffer or ring index cannot be used by S/W*/
dev_err(&adapter->pdev->dev, "NICRxPkts PSR Entry %d indicates length of %d and/or bad bi(%d)\n",
rx_local->local_psr_full & 0xFFF, len, buff_index); return NULL;
}
/* Get and fill the RFD. */
spin_lock_irqsave(&adapter->rcv_lock, flags);
element = rx_local->recv_list.next;
rfd = list_entry(element, struct rfd, list_node);
if (!rfd) {
spin_unlock_irqrestore(&adapter->rcv_lock, flags); return NULL;
}
/* In V1 silicon, there is a bug which screws up filtering of runt *packets.ThereforeruntpacketfilteringisdisabledintheMACand *thepacketsaredroppedhere.Theyarealsocountedhere.
*/ if (len < (NIC_MIN_PACKET_SIZE + 4)) {
adapter->stats.rx_other_errs++;
rfd->len = 0; goto out;
}
if ((word0 & ALCATEL_MULTICAST_PKT) && !(word0 & ALCATEL_BROADCAST_PKT))
adapter->stats.multicast_pkts_rcvd++;
rfd->len = len;
skb = dev_alloc_skb(rfd->len + 2); if (!skb) return NULL;
staticint et131x_handle_recv_pkts(struct et131x_adapter *adapter, int budget)
{ struct rfd *rfd = NULL; int count = 0; int limit = budget; bool done = true; struct rx_ring *rx_ring = &adapter->rx_ring;
if (budget > MAX_PACKETS_HANDLED)
limit = MAX_PACKETS_HANDLED;
/* Process up to available RFD's */ while (count < limit) { if (list_empty(&rx_ring->recv_list)) {
WARN_ON(rx_ring->num_ready_recv != 0);
done = false; break;
}
rfd = nic_rx_pkts(adapter);
if (rfd == NULL) break;
/* Do not receive any packets until a filter has been set. *Donotreceiveanypacketsuntilwehavelink. *Iflengthiszero,returntheRFDinordertoadvancethe *Freebufferring.
*/ if (!adapter->packet_filter ||
!netif_carrier_ok(adapter->netdev) ||
rfd->len == 0) continue;
adapter->netdev->stats.rx_packets++;
if (rx_ring->num_ready_recv < RFD_LOW_WATER_MARK)
dev_warn(&adapter->pdev->dev, "RFD's are running out\n");
count++;
}
if (count == limit || !done) {
rx_ring->unfinished_receives = true;
writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
&adapter->regs->global.watchdog_timer);
} else { /* Watchdog timer will disable itself if appropriate. */
rx_ring->unfinished_receives = false;
}
if (tx_ring->tx_desc_ring) { /* Free memory relating to Tx rings here */
desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX);
dma_free_coherent(&adapter->pdev->dev,
desc_size,
tx_ring->tx_desc_ring,
tx_ring->tx_desc_ring_pa);
tx_ring->tx_desc_ring = NULL;
}
/* Free memory for the Tx status block */ if (tx_ring->tx_status) {
dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
tx_ring->tx_status,
tx_ring->tx_status_pa);
tx_ring->tx_status = NULL;
} /* Free the memory for the tcb structures */
kfree(tx_ring->tcb_ring);
}
for (i = 0; i < nr_frags; i++) { /* If there is something in this element, lets get a *descriptorfromtheringandgetthenecessarydata
*/ if (i == 0) { /* If the fragments are smaller than a standard MTU, *thenmapthemtoasingledescriptorintheTx *Descring.However,ifthey'relarger,asis *possiblewithsupportforjumbopackets,then *splitthemeachacross2descriptors. * *Thiswillworkuntilwedeterminewhythehardware *doesn'tseemtolikelargefragments.
*/ if (skb_headlen(skb) <= 1514) { /* Low 16bits are length, high is vlan and *unusedcurrentlysozero
*/
desc[frag].len_vlan = skb_headlen(skb);
dma_addr = dma_map_single(&adapter->pdev->dev,
skb->data,
skb_headlen(skb),
DMA_TO_DEVICE); if (dma_mapping_error(&adapter->pdev->dev,
dma_addr)) return -ENOMEM;
if (tx_ring->send_tail)
tx_ring->send_tail->next = tcb; else
tx_ring->send_head = tcb;
tx_ring->send_tail = tcb;
WARN_ON(tcb->next != NULL);
tx_ring->used++;
spin_unlock(&adapter->tcb_send_qlock);
/* Write the new write pointer back to the device. */
writel(tx_ring->send_idx, &adapter->regs->txdma.service_request);
/* For Gig only, we use Tx Interrupt coalescing. Enable the software *timertowakeusupifthispacketisn'tfollowedbyNmore.
*/ if (phydev && phydev->speed == SPEED_1000) {
writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
&adapter->regs->global.watchdog_timer);
} return0;
unmap_out: // Unmap the body of the packet with map_page while (--i) {
frag--;
dma_addr = desc[frag].addr_lo;
dma_addr |= (u64)desc[frag].addr_hi << 32;
dma_unmap_page(&adapter->pdev->dev, dma_addr,
desc[frag].len_vlan, DMA_TO_DEVICE);
}
unmap_first_out: // Unmap the header with map_single while (frag--) {
dma_addr = desc[frag].addr_lo;
dma_addr |= (u64)desc[frag].addr_hi << 32;
dma_unmap_single(&adapter->pdev->dev, dma_addr,
desc[frag].len_vlan, DMA_TO_DEVICE);
}
/* Iterate through the TX descriptors on the ring *correspondingtothispacketandumapthefragments *theypointto
*/ do {
desc = tx_ring->tx_desc_ring +
INDEX10(tcb->index_start);
serviced = readl(&adapter->regs->txdma.new_service_complete);
index = INDEX10(serviced);
/* Has the ring wrapped? Process any descriptors that do not have *thesame"wrap"indicatorasthecurrentcompletionindicator
*/
spin_lock_irqsave(&adapter->tcb_send_qlock, flags);
tcb = tx_ring->send_head;
while (tcb &&
((serviced ^ tcb->index) & ET_DMA10_WRAP) &&
index < INDEX10(tcb->index)) {
tx_ring->used--;
tx_ring->send_head = tcb->next; if (tcb->next == NULL)
tx_ring->send_tail = NULL;
/* et131x_hwaddr_init - set up the MAC Address */ staticvoid et131x_hwaddr_init(struct et131x_adapter *adapter)
{ /* If have our default mac from init and no mac address from *EEPROMthenweneedtogeneratethelastoctetandsetitonthe *device
*/ if (is_zero_ether_addr(adapter->rom_addr)) { /* We need to randomly generate the last octet so we *decreaseourchancesofsettingthemacaddressto *sameasanotheroneofourcardsinthesystem
*/
get_random_bytes(&adapter->addr[5], 1); /* We have the default value in the register we are *workingwithsoweneedtocopythecurrent *addressintothepermanentaddress
*/
ether_addr_copy(adapter->rom_addr, adapter->addr);
} else { /* We do not have an override address, so set the *currentaddresstothepermanentaddressandadd *ittothedevice
*/
ether_addr_copy(adapter->addr, adapter->rom_addr);
}
}
staticint et131x_pci_init(struct et131x_adapter *adapter, struct pci_dev *pdev)
{
u16 max_payload; int i, rc;
rc = et131x_init_eeprom(adapter); if (rc < 0) goto out;
if (!pci_is_pcie(pdev)) {
dev_err(&pdev->dev, "Missing PCIe capabilities\n"); goto err_out;
}
/* Program the Ack/Nak latency and replay timers */
max_payload = pdev->pcie_mpss;
if (pci_write_config_word(pdev, ET1310_PCI_ACK_NACK,
acknak[max_payload])) {
dev_err(&pdev->dev, "Could not write PCI config space for ACK/NAK\n"); goto err_out;
} if (pci_write_config_word(pdev, ET1310_PCI_REPLAY,
replay[max_payload])) {
dev_err(&pdev->dev, "Could not write PCI config space for Replay Timer\n"); goto err_out;
}
}
/* l0s and l1 latency timers. We are using default values. *Representing001forL0sand010forL1
*/ if (pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11)) {
dev_err(&pdev->dev, "Could not write PCI config space for Latency Timers\n"); goto err_out;
}
/* Change the max read size to 2k */ if (pcie_set_readrq(pdev, 2048)) {
dev_err(&pdev->dev, "Couldn't change PCI config space for Max read size\n"); goto err_out;
}
/* Get MAC address from config space if an eeprom exists, otherwise *theMACaddresstherewillnotbevalid
*/ if (!adapter->has_eeprom) {
et131x_hwaddr_init(adapter); return0;
}
for (i = 0; i < ETH_ALEN; i++) { if (pci_read_config_byte(pdev, ET1310_PCI_MAC_ADDRESS + i,
adapter->rom_addr + i)) {
dev_err(&pdev->dev, "Could not read PCI config space for MAC address\n"); goto err_out;
}
}
ether_addr_copy(adapter->addr, adapter->rom_addr);
out: return rc;
err_out:
rc = -EIO; goto out;
}
if (et1310_in_phy_coma(adapter)) { /* Bring the device immediately out of coma, to *preventitfromsleepingindefinitely,this *mechanismcouldbeimproved!
*/
et1310_disable_phy_coma(adapter);
adapter->boot_coma = 20;
} else {
et1310_update_macstat_host_counters(adapter);
}
if (!phydev->link && adapter->boot_coma < 11)
adapter->boot_coma++;
if (adapter->boot_coma == 10) { if (!phydev->link) { if (!et1310_in_phy_coma(adapter)) { /* NOTE - This was originally a 'sync with *interrupt'.HowtodothatunderLinux?
*/
et131x_enable_interrupts(adapter);
et1310_enable_phy_coma(adapter);
}
}
}
/* This is a periodic timer, so reschedule */
mod_timer(&adapter->error_timer, jiffies +
msecs_to_jiffies(TX_ERROR_PERIOD));
}
if (!phydev) return; if (phydev->link == adapter->link) return;
/* Check to see if we are in coma mode and if *so,disableitbecausewewillnotbeable *toreadPHYvaluesuntilweareout.
*/ if (et1310_in_phy_coma(adapter))
et1310_disable_phy_coma(adapter);
/* Bring the device back to the state it was during *initpriortoautonegotiationbeingcomplete.This *way,whenwegettheauto-negcompleteinterrupt, *wecancompleteinitbycallingconfig_mac_regs2.
*/
et131x_soft_reset(adapter);
if (status & (ET_INTR_RXDMA_FB_R0_LOW | ET_INTR_RXDMA_FB_R1_LOW)) { /* This indicates the number of unused buffers in RXDMA free *bufferring0is<=thelimityouprogrammed.Freebuffer *resourcesneedtobereturned.Freebuffersareconsumedas *packetsarepassedfromthenetworktothehost.Thehost *becomesawareofthepacketsfromthecontentsofthepacket *statusring.Thisringisqueriedwhenthepacketdone *interruptoccurs.PacketsarethenpassedtotheOS.When *theOSisdonewiththepacketstheresourcescanbe *returnedtotheET1310forre-use.Thisinterruptisone *methodofreturningresources.
*/
/* If the user has flow control on, then we will *sendapausepacket,otherwisejustexit
*/ if (adapter->flow == FLOW_TXONLY || adapter->flow == FLOW_BOTH) { /* Tell the device to send a pause packet via the back *pressureregister(bpreqandbpxon/xoff)
*/ if (!et1310_in_phy_coma(adapter))
writel(3, &iomem->txmac.bp_ctrl);
}
}
/* Handle Packet Status Ring Low Interrupt */ if (status & ET_INTR_RXDMA_STAT_LOW) { /* Same idea as with the two Free Buffer Rings. Packets going *fromthenetworktothehosteachconsumeafreebuffer *resourceandapacketstatusresource.Theseresourcesare *passedtotheOS.WhentheOSisdonewiththeresources, *theyneedtobereturnedtotheET1310.Thisisonemethod *ofreturningtheresources.
*/
}
if (status & ET_INTR_RXDMA_ERR) { /* The rxdma_error interrupt is sent when a time-out on a *requestissuedbytheJAGCorehasoccurredoracompletionis *returnedwithanun-successfulstatus.Inbothcasesthe *requestisconsideredcomplete.TheJAGCorewill *automaticallyre-trytherequestinquestion.Normally *informationoneventslikethesearesenttothehostusing *the"AdvancedErrorReporting"capability.Thisinterruptis *anotherwayofgettingsimilarinformation.Theonlything *requiredistocleartheinterruptbyreadingtheISRinthe *globalresources.TheJAGCorewilldoare-tryonthe *request.Normallyyoushouldneverseethisinterrupt.If *youstarttoseethisinterruptoccurringfrequentlythen *somethingbadhasoccurred.Aresetmightbethethingtodo.
*/ /* TRAP();*/
/* Handle the Wake on LAN Event */ if (status & ET_INTR_WOL) { /* This is a secondary interrupt for wake on LAN. The driver *shouldneverseethis,ifitdoes,somethingseriousis *wrong.
*/
dev_err(&adapter->pdev->dev, "WAKE_ON_LAN interrupt\n");
}
if (status & ET_INTR_TXMAC) {
u32 err = readl(&iomem->txmac.err);
/* When any of the errors occur and TXMAC generates an *interrupttoreporttheseerrors,itusuallymeansthat *TXMAChasdetectedanerrorinthedatastreamretrieved *fromtheon-chipTxQ.Alloftheseerrorsarecatastrophic *andTXMACwon'tbeabletorecoverdatawhentheseerrors *occur.Inanutshell,thewholeTxpathwillhavetobereset *andre-configuredafterwards.
*/
dev_warn(&adapter->pdev->dev, "TXMAC interrupt, error 0x%08x\n",
err);
/* If we are debugging, we want to see this error, otherwise we *justwantthedevicetoberesetandcontinue
*/
}
if (status & ET_INTR_RXMAC) { /* These interrupts are catastrophic to the device, what we need *todoisdisabletheinterruptsandsettheflagtocauseus *toresetsowecansolvethisissue.
*/
dev_warn(&adapter->pdev->dev, "RXMAC interrupt, error 0x%08x. Requesting reset\n",
readl(&iomem->rxmac.err_reg));
/* If we are debugging, we want to see this error, otherwise we *justwantthedevicetoberesetandcontinue
*/
}
if (status & ET_INTR_MAC_STAT) { /* This means at least one of the un-masked counters in the *MAC_STATblockhasrolledover.Usethistomaintainthetop, *softwaremanagedbitsofthecounter(s).
*/
et1310_handle_macstat_interrupt(adapter);
}
if (status & ET_INTR_SLV_TIMEOUT) { /* This means a timeout has occurred on a read or write request *tooneoftheJAGCoreregisters.TheGlobalResourcesblock *hasterminatedtherequestandonareadrequest,returneda *"fake"value.Themostlikelyreasonsare:BadAddressorthe *addressedmoduleisinapower-downstateandcan'trespond.
*/
}
out: if (enable_interrupts)
et131x_enable_interrupts(adapter);
return IRQ_RETVAL(handled);
}
staticint et131x_poll(struct napi_struct *napi, int budget)
{ struct et131x_adapter *adapter =
container_of(napi, struct et131x_adapter, napi); int work_done = et131x_handle_recv_pkts(adapter, budget);
et131x_handle_send_pkts(adapter);
if (work_done < budget) {
napi_complete_done(&adapter->napi, work_done);
et131x_enable_interrupts(adapter);
}
/* Default to disabled packet filtering */
ctrl |= 0x04;
/* Set us to be in promiscuous mode so we receive everything, this *isalsotruewhenwegetapacketfilterof0
*/ if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0)
pf_ctrl &= ~7; /* Clear filter bits */ else { /* Set us up with Multicast packet filtering. Three cases are *possible-(1)wehaveamulti-castlist,(2)wereceiveALL *multicastentriesor(3)wereceivenone.
*/ if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST)
pf_ctrl &= ~2; /* Multicast filter bit */ else {
et1310_setup_device_for_multicast(adapter);
pf_ctrl |= 2;
ctrl &= ~0x04;
}
/* Set us up with Unicast packet filtering */ if (filter & ET131X_PACKET_TYPE_DIRECTED) {
et1310_setup_device_for_unicast(adapter);
pf_ctrl |= 4;
ctrl &= ~0x04;
}
/* Set us up with Broadcast packet filtering */ if (filter & ET131X_PACKET_TYPE_BROADCAST) {
pf_ctrl |= 1; /* Broadcast filter bit */
ctrl &= ~0x04;
} else {
pf_ctrl &= ~1;
}
/* Setup the receive mac configuration registers - Packet *Filtercontrol+theenable/disableforpacketfilter *inthecontrolreg.
*/
writel(pf_ctrl, &adapter->regs->rxmac.pf_ctrl);
writel(ctrl, &adapter->regs->rxmac.ctrl);
} return0;
}
staticvoid et131x_multicast(struct net_device *netdev)
{ struct et131x_adapter *adapter = netdev_priv(netdev); int packet_filter; struct netdev_hw_addr *ha; int i;
/* Before we modify the platform-independent filter flags, store them *locally.Thisallowsustodetermineifanything'schangedandif *weevenneedtobotherthehardware
*/
packet_filter = adapter->packet_filter;
/* Clear the 'multicast' flag locally; because we only have a single *flagtocheckmulticast,andmultiplemulticastaddressescanbe *set,thisistheeasiestwaytodetermineifmorethanone *multicastaddressisbeingset.
*/
packet_filter &= ~ET131X_PACKET_TYPE_MULTICAST;
/* Check the net_device flags and set the device independent flags *accordingly
*/ if (netdev->flags & IFF_PROMISC)
adapter->packet_filter |= ET131X_PACKET_TYPE_PROMISCUOUS; else
adapter->packet_filter &= ~ET131X_PACKET_TYPE_PROMISCUOUS;
/* Set values in the private adapter struct */
i = 0;
netdev_for_each_mc_addr(ha, netdev) { if (i == NIC_MAX_MCAST_LIST) break;
ether_addr_copy(adapter->multicast_list[i++], ha->addr);
}
adapter->multicast_addr_count = i;
/* Are the new flags different from the previous ones? If not, then no *actionisrequired * *NOTE-Thisblockwillalwaysupdatethemulticast_listwiththe *hardware,eveniftheaddressesaren'tthesame.
*/ if (packet_filter != adapter->packet_filter)
et131x_set_packet_filter(adapter);
}
/* This driver does not support TSO, it is very unlikely *thisconditionistrue.
*/ if (unlikely(skb_shinfo(skb)->nr_frags > MAX_TX_DESC_PER_PKT - 2)) { if (skb_linearize(skb)) goto drop_err;
} /* stop the queue if it's getting full */ if (tx_ring->used >= NUM_TCB - 1 && !netif_queue_stopped(netdev))
netif_stop_queue(netdev);
/* Save the timestamp for the TX timeout watchdog */
netif_trans_update(netdev);
/* TCB is not available */ if (tx_ring->used >= NUM_TCB) goto drop_err;
if ((adapter->flags & FMP_ADAPTER_FAIL_SEND_MASK) ||
!netif_carrier_ok(netdev)) goto drop_err;
/* Perform some basic PCI checks */ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "Can't find PCI device's base address\n");
rc = -ENODEV; goto err_disable;
}
rc = pci_request_regions(pdev, DRIVER_NAME); if (rc < 0) {
dev_err(&pdev->dev, "Can't get PCI resources\n"); goto err_disable;
}
pci_set_master(pdev);
/* Check the DMA addressing support of this device */
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (rc) {
dev_err(&pdev->dev, "No usable DMA addressing method\n"); goto err_release_res;
}
/* Register the net_device struct with the PCI subsystem. Save a copy *ofthePCIconfigspaceforthisdevicenowthatthedevicehas *beeninitialized,justincaseitneedstobequicklyrestored.
*/
pci_set_drvdata(pdev, netdev);
out: return rc;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.118Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.