[...] > /* Writes a packet to the TX_DATA_FIFO */ > static inline void > smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, > unsigned int wordcount) > { > while (wordcount--) { > smsc911x_reg_write(*buf++, pdata, TX_DATA_FIFO); > }
Curly braces are not needed around single line blocks. [...] > /* waits for MAC not busy, with timeout. Assumes MacPhyAccessLock has > * already been acquired */ > static int smsc911x_mac_notbusy(struct smsc911x_data *pdata) > { > int i; > > for (i = 0; i < 40; i++) { > if ((smsc911x_reg_read(pdata, MAC_CSR_CMD) > & MAC_CSR_CMD_CSR_BUSY_) == 0) { > return 1; > } > } > SMSC_WARNING("Timed out waiting for MAC not BUSY. " > "MAC_CSR_CMD: 0x%08X", smsc911x_reg_read(pdata, > MAC_CSR_CMD)); > return 0; u32 val; for (i = 0; i < 40; i++) { val = smsc911x_reg_read(pdata, MAC_CSR_CMD); if (!(val & MAC_CSR_CMD_CSR_BUSY_)) return 1; } SMSC_WARNING("Timed out waiting for MAC not BUSY. " "MAC_CSR_CMD: 0x%08X", val); -> no painful line-breaking (s/val/{reg/cmd}/ at will). > } > > /* Fetches a MAC register value. Assumes phy_lock is acquired */ > static unsigned int > smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset) > { > unsigned int result = 0xFFFFFFFF; > unsigned int temp; > > /* Wait until not busy */ > if (unlikely > (smsc911x_reg_read(pdata, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_)) { > SMSC_WARNING("smsc911x_mac_read failed, " > "MAC already busy at entry"); > return result; > } > > /* Send the MAC cmd */ > smsc911x_reg_write(((offset & 0x000000FF) | MAC_CSR_CMD_CSR_BUSY_ > | MAC_CSR_CMD_R_NOT_W_), pdata, MAC_CSR_CMD); > > /* Workaround for hardware read-after-write restriction */ > temp = smsc911x_reg_read(pdata, BYTE_TEST); > > /* Wait for the read to happen */ > if (unlikely(!smsc911x_mac_notbusy(pdata))) Double negation (at least :o) ). [...] > /* Gets a phy register, phy_lock must be acquired before calling */ > static unsigned int > smsc911x_phy_read(struct smsc911x_data *pdata, unsigned int index) > { > unsigned int addr; > unsigned int result = 0xFFFF; > int i; > > /* Confirm MII not busy */ > if (unlikely > ((smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_) != 0)) { > SMSC_WARNING("MII is busy in smsc911x_phy_read???"); > return 0; > } > > /* Set the address, index & direction (read from PHY) */ > addr = (((pdata->phy_address) & 0x1F) << 11) > | ((index & 0x1F) << 6); > smsc911x_mac_write(pdata, MII_ACC, addr); > > /* Wait for read to complete w/ timeout */ > for (i = 0; i < 100; i++) { > /* See if MII is finished yet */ > if ((smsc911x_mac_read(pdata, MII_ACC) > & MII_ACC_MII_BUSY_) == 0) { > result = smsc911x_mac_read(pdata, MII_DATA); > return result; > } if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) return smsc911x_mac_read(pdata, MII_DATA); > } > SMSC_WARNING("Timed out waiting for MII write to finish"); > > return result; I'd go with return 0xffff; here and remove 'result' altogether. > } > > /* Sets a phy register, phy_lock must be acquired before calling */ > static void smsc911x_phy_write(struct smsc911x_data *pdata, > unsigned int index, unsigned int val) > { > unsigned int addr; > int i; > > /* Confirm MII not busy */ > if (unlikely > ((smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_) != 0)) { Factor through a smsc911x_mac_busy(pdata) helper ? [...] > static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata) > { > unsigned int address; > unsigned int hwcfg; > unsigned int phyid1; > unsigned int phyid2; > > hwcfg = smsc911x_reg_read(pdata, HW_CFG); > > /* External phy is requested, supported, and detected */ > if (hwcfg & HW_CFG_EXT_PHY_DET_) { > > /* Attempt to switch to external phy for auto-detecting > * its address. Assuming tx and rx are stopped because > * smsc911x_phy_initialise is called before > * smsc911x_rx_initialise and tx_initialise. > */ > > /* Disable phy clocks to the MAC */ > hwcfg &= (~HW_CFG_PHY_CLK_SEL_); > hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; > smsc911x_reg_write(hwcfg, pdata, HW_CFG); > udelay(10); /* Enough time for clocks to stop */ > > /* Switch to external phy */ > hwcfg |= HW_CFG_EXT_PHY_EN_; > smsc911x_reg_write(hwcfg, pdata, HW_CFG); > > /* Enable phy clocks to the MAC */ > hwcfg &= (~HW_CFG_PHY_CLK_SEL_); > hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; > smsc911x_reg_write(hwcfg, pdata, HW_CFG); > udelay(10); /* Enough time for clocks to restart */ (back to my original question that I should have reworded in a different thread) Does the platform guarantees that the register write has actually reached the real register when the udelay is issued ? > > hwcfg |= HW_CFG_SMI_SEL_; > smsc911x_reg_write(hwcfg, pdata, HW_CFG); > > /* Auto-detect PHY */ > for (address = 0; address <= 31; address++) { > pdata->phy_address = address; > phyid1 = smsc911x_phy_read(pdata, MII_PHYSID1); > phyid2 = smsc911x_phy_read(pdata, MII_PHYSID2); > if ((phyid1 != 0xFFFFU) || (phyid2 != 0xFFFFU)) { > SMSC_TRACE("Detected PHY at address = " > "0x%02X = %d", address, address); > break; > } > } > > if ((phyid1 == 0xFFFFU) && (phyid2 == 0xFFFFU)) { > SMSC_WARNING("External PHY is not accessable, " > "using internal PHY instead"); > /* Revert back to interal phy settings. */ s/interal/internal/ [...] > static int smsc911x_phy_reset(struct smsc911x_data *pdata) > { > unsigned int temp; > unsigned int lcount = 100000; > > SMSC_TRACE("Performing PHY BCR Reset"); > smsc911x_phy_write(pdata, MII_BMCR, BMCR_RESET); > do { > udelay(10); > temp = smsc911x_phy_read(pdata, MII_BMCR); > lcount--; > } while ((lcount > 0) && (temp & BMCR_RESET)); > > if (temp & BMCR_RESET) { > SMSC_WARNING("PHY reset failed to complete."); > return 0; > } > /* Extra delay required because the phy may not be completed with > * its reset when BMCR_RESET is cleared. Specs say 256 uS is > * enough delay but using 500 here to be safe > */ > udelay(500); It would be nice to turn the udelay() into msleep() but this code is issued from at least one spnlock-protected section. [...] > #ifdef USE_PHY_WORK_AROUND > static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) > { > unsigned int tries = 0; > unsigned int lcount = 0; > u32 wrsz; > u32 rdsz; > u32 bufp; > > for (tries = 0; tries < 10; tries++) { Wrong visibility whence an useless initialization of 'lcount'. [...] > /* Update link mode if any thing has changed */ > static void smsc911x_phy_update_linkmode(struct net_device *dev) > { > struct smsc911x_data *pdata = netdev_priv(dev); > unsigned int old_link_speed = pdata->link_speed; > unsigned int temp; > unsigned long flags; > > spin_lock_irqsave(&pdata->phy_lock, flags); > smsc911x_phy_getlinkmode(pdata); > > if (old_link_speed != pdata->link_speed) { > if (pdata->link_speed != LINK_OFF) { > unsigned int phy_reg = 0; > switch (pdata->link_speed) { > case LINK_SPEED_10HD: > SMSC_TRACE("Link is now UP at 10Mbps HD"); > break; > case LINK_SPEED_10FD: > SMSC_TRACE("Link is now UP at 10Mbps FD"); > break; > case LINK_SPEED_100HD: > SMSC_TRACE("Link is now UP at 100Mbps HD"); > break; > case LINK_SPEED_100FD: > SMSC_TRACE("Link is now UP at 100Mbps FD"); > break; > default: > SMSC_WARNING("Link is now UP at unknown link " > "speed: 0x%08X", > pdata->link_speed); > break; > } > phy_reg = smsc911x_mac_read(pdata, MAC_CR); > phy_reg &= ~(MAC_CR_FDPX_ | MAC_CR_RCVOWN_); > > switch (pdata->link_speed) { > case LINK_SPEED_10HD: > case LINK_SPEED_100HD: > phy_reg |= MAC_CR_RCVOWN_; > break; > > case LINK_SPEED_10FD: > case LINK_SPEED_100FD: > phy_reg |= MAC_CR_FDPX_; > break; > > default: > SMSC_WARNING("Unknown link speed: 0x%08X", > pdata->link_speed); > break; > } > > smsc911x_mac_write(pdata, MAC_CR, phy_reg); > > if (pdata->link_settings & LINK_AUTO_NEGOTIATE) { > unsigned int linkpartner = 0; > unsigned int locallink = 0; > locallink = smsc911x_phy_read(pdata, 4); > linkpartner = smsc911x_phy_read(pdata, 5); > switch (pdata->link_speed) { > case LINK_SPEED_10FD: > case LINK_SPEED_100FD: > if (((locallink & linkpartner) & > LPA_PAUSE_CAP) != 0) { > /* Enable PAUSE receive and > transmit */ > smsc911x_mac_write(pdata, FLOW, > 0xFFFF0002); > temp = > smsc911x_reg_read(pdata, > AFC_CFG); > temp |= 0xF; > smsc911x_reg_write(temp, pdata, > AFC_CFG); > } else if (((locallink & > (ADVERTISE_PAUSE_CAP | > ADVERTISE_PAUSE_ASYM)) == > (ADVERTISE_PAUSE_CAP | > ADVERTISE_PAUSE_ASYM)) && > ((linkpartner & > (LPA_PAUSE_CAP | > LPA_PAUSE_ASYM)) == > LPA_PAUSE_ASYM)) { Wow... [...] > /* Increments the Rx error counters */ > static void > smsc911x_rx_counterrors(struct smsc911x_data *pdata, unsigned int rxstat) > { > int crc_err; > > crc_err = 0; Merge declaration/initialization. [...] > /* Quickly dumps bad packets */ > static void > smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int count) > { > if (likely(count >= 4)) { > unsigned int timeout = 500; > smsc911x_reg_write(RX_DP_CTRL_RX_FFWD_, pdata, RX_DP_CTRL); > while (timeout && (smsc911x_reg_read(pdata, RX_DP_CTRL) > & RX_DP_CTRL_RX_FFWD_)) { > udelay(1); > timeout--; > } > if (unlikely(timeout == 0)) { > SMSC_WARNING("Timed out waiting for RX FFWD " > "to finish, RX_DP_CTRL: 0x%08X", > smsc911x_reg_read(pdata, RX_DP_CTRL)); > } > } else { > while (count) { > volatile unsigned int temp; > temp = smsc911x_reg_read(pdata, RX_DATA_FIFO); Kill the volatile: there is an implicit readl(). > /* NAPI poll function */ > static int smsc911x_poll(struct net_device *dev, int *budget) > { > struct smsc911x_data *pdata = netdev_priv(dev); > int npackets = 0; > int quota = min(dev->quota, *budget); > > while (npackets < quota) { > unsigned int pktlength; > unsigned int rxstat; > rxstat = smsc911x_rx_get_rxstatus(pdata); > > /* break out of while loop if there are no more packets waiting > */ > if (rxstat == 0) > break; > > pktlength = ((rxstat & 0x3FFF0000) >> 16); > smsc911x_rx_counterrors(pdata, rxstat); > > if (likely((rxstat & RX_STS_ES_) == 0)) { > struct sk_buff *skb = NULL; Useless initialization. > skb = dev_alloc_skb(pktlength + 2); s/2/NET_IP_ALIGN/ > if (likely(skb)) { > skb->data = skb->head; > skb->tail = skb->head; > /* Align IP on 16B boundary */ > skb_reserve(skb, 2); s/2/NET_IP_ALIGN/ [...] > static int smsc911x_open(struct net_device *dev) > { > struct smsc911x_data *pdata = netdev_priv(dev); > unsigned int mac_high16; > unsigned int mac_low32; > unsigned int timeout; > unsigned int temp; > unsigned long flags; > > spin_lock_init(&pdata->phy_lock); > > /* Reset the LAN911x */ > smsc911x_reg_write(HW_CFG_SRST_, pdata, HW_CFG); > timeout = 10; > do { > udelay(10); > temp = smsc911x_reg_read(pdata, HW_CFG); > } while ((--timeout) && (temp & HW_CFG_SRST_)); > > if (unlikely(temp & HW_CFG_SRST_)) { > SMSC_WARNING("Failed to complete reset"); > return -ENODEV; > } > > smsc911x_reg_write(0x00050000, pdata, HW_CFG); > smsc911x_reg_write(0x006E3740, pdata, AFC_CFG); > > /* Make sure EEPROM has finished loading before setting GPIO_CFG */ > timeout = 50; > while ((timeout--) && > (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_)) { > udelay(10); > } > > if (unlikely(timeout == 0)) { > SMSC_WARNING("Timed out waiting for EEPROM " > "busy bit to clear\n"); > } > #if USE_DEBUG >= 1 > smsc911x_reg_write(0x00670700, pdata, GPIO_CFG); > #else > smsc911x_reg_write(0x70070000, pdata, GPIO_CFG); > #endif > > /* Initialise irqs, but leave all sources disabled */ > smsc911x_reg_write(0, pdata, INT_EN); > smsc911x_reg_write(0xFFFFFFFF, pdata, INT_STS); > /* Set interrupt deassertion to 100uS */ > smsc911x_reg_write(((10 << 24) | INT_CFG_IRQ_EN_), pdata, INT_CFG); > > /* > * intcfg |= INT_CFG_IRQ_POL_; use this to set IRQ_POL bit > * intcfg |= INT_CFG_IRQ_TYPE_; use this to set IRQ_TYPE bit > */ > > SMSC_TRACE("Testing irq handler using IRQ %d", dev->irq); > pdata->request_irq_disable = 0; > pdata->software_irq_signal = 0; > temp = smsc911x_reg_read(pdata, INT_EN); > temp |= INT_EN_SW_INT_EN_; > smsc911x_reg_write(temp, pdata, INT_EN); > timeout = 1000; > do { > udelay(10); > } while ((--timeout) && (!pdata->software_irq_signal)); while (timeout--) { smp_rmb(); if (pdata->software_irq_signal) break; msleep(1); } + smp_wmb() in the irq handler. > > if (!pdata->software_irq_signal) { > printk(KERN_WARNING "%s: ISR failed signaling test (IRQ %d)\n", > dev->name, dev->irq); > return -ENODEV; > } > SMSC_TRACE("IRQ handler passed test using IRQ %d", dev->irq); > > printk(KERN_INFO "%s: SMSC911x/921x identified at %#08lx, IRQ: %d\n", > dev->name, (unsigned long)pdata->ioaddr, dev->irq); > > spin_lock_irqsave(&pdata->phy_lock, flags); flags useless: ->open() is issued in irq-enabled context. > > /* Read mac address from EEPROM */ > mac_high16 = smsc911x_mac_read(pdata, ADDRH); > mac_low32 = smsc911x_mac_read(pdata, ADDRL); > > /* Generate random MAC address if eeprom values are invalid */ > if ((mac_high16 == 0x0000FFFF) && (mac_low32 == 0xFFFFFFFF)) { > u8 random_mac[6]; > random_ether_addr(random_mac); > mac_high16 = (random_mac[5] << 8) | random_mac[4]; > mac_low32 = (random_mac[3] << 24) | (random_mac[2] << 16) | > (random_mac[1] << 8) | random_mac[0]; > > smsc911x_mac_write(pdata, ADDRH, mac_high16); > smsc911x_mac_write(pdata, ADDRL, mac_low32); > SMSC_TRACE("MAC Address is set to random_ether_addr"); > } else { > SMSC_TRACE("Mac Address is read from LAN911x EEPROM"); > } > > dev->dev_addr[0] = (u8)(mac_low32); > dev->dev_addr[1] = (u8)(mac_low32 >> 8); > dev->dev_addr[2] = (u8)(mac_low32 >> 16); > dev->dev_addr[3] = (u8)(mac_low32 >> 24); > dev->dev_addr[4] = (u8)(mac_high16); > dev->dev_addr[5] = (u8)(mac_high16 >> 8); > printk(KERN_INFO > "%s: SMSC911x MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", > dev->name, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], > dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); > > netif_carrier_off(dev); > if (!smsc911x_phy_initialise(dev)) { > SMSC_WARNING("Failed to initialize PHY"); > return -ENODEV; return with spinlock held (mantra: use goto). Any chance you could avoid the spinlock ? It would help turning udelay into sleep (namely smsc911x_phy_reset). [...] > #ifdef CONFIG_NET_POLL_CONTROLLER > void smsc911x_poll_controller(struct net_device *dev) > { > disable_irq(dev->irq); > smsc911x_irqhandler(0, (void *)dev, NULL); No need to cast to (void *) > enable_irq(dev->irq); > } > #endif /* CONFIG_NET_POLL_CONTROLLER */ > > /* Standard ioctls for mii-tool */ > int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int > { > struct smsc911x_data *pdata = netdev_priv(dev); > struct mii_ioctl_data *const data = > (struct mii_ioctl_data *)&ifr->ifr_data; Use if_mii() > unsigned long flags; > > SMSC_TRACE("ioctl cmd 0x%x", cmd); > switch (cmd) { > case SIOCGMIIPHY: > case SIOCDEVPRIVATE: The SIOCDEVPRIVATE can/should be removed. [...] > static int smsc911x_drv_probe(struct platform_device *pdev) > { > struct net_device *dev; > struct smsc911x_data *pdata; > struct resource *res; > int res_size; > int retval; > > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, > "smsc911x-memory"); > if (!res) > res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > if (!res) { > retval = -ENODEV; > goto out; > } > res_size = res->end - res->start; > > if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) { > retval = -EBUSY; > goto out; > } > > dev = alloc_etherdev(sizeof(struct smsc911x_data)); > if (!dev) { > printk(KERN_WARNING "%s: Could not allocate device.\n", > SMSC_CHIPNAME); > retval = -ENOMEM; > goto out_release_io; > } > SET_MODULE_OWNER(dev); > SET_NETDEV_DEV(dev, &pdev->dev); > > pdata = netdev_priv(dev); > memset(pdata, 0, sizeof(struct smsc911x_data)); > > dev->irq = platform_get_irq(pdev, 0); > pdata->ioaddr = ioremap_nocache(res->start, res_size); > > if (pdata->ioaddr == NULL) { > SMSC_WARNING("Error smsc911x base address invalid"); > retval = -ENOMEM; > goto out_free_netdev; > } > > if ((retval = smsc911x_init(dev)) < 0) > goto out_unmap_io; > > if (request_irq(dev->irq, smsc911x_irqhandler, > SA_INTERRUPT, SMSC_CHIPNAME, dev) != 0) { > SMSC_WARNING("Unable to claim requested irq: %d", dev->irq); > retval = -ENODEV; Should be retval = request_irq(...) > goto out_unmap_io; > } > > platform_set_drvdata(pdev, dev); > retval = register_netdev(dev); > > if (retval) { > SMSC_WARNING("Error %i registering device", retval); > retval = -ENODEV; No need to overwrite retval. > goto out_unset_drvdata; > } else { > SMSC_TRACE("Network interface: \"%s\"", dev->name); > } > > return 0; > > out_unset_drvdata: > platform_set_drvdata(pdev, NULL); Missing free_irq(). Please number the label: out_0, out_release_io_1, etc... It's easier to check. > out_unmap_io: > iounmap(pdata->ioaddr); > out_free_netdev: > free_netdev(dev); > out_release_io: > release_mem_region(res->start, res->end - res->start); > out: > return retval; > } [...] > /* Entry point for loading the module */ > static int __init smsc911x_init_module(void) > { > platform_driver_register(&smsc911x_driver); > return 0; return platform_driver_register(...); > --- /dev/null > ++ b/drivers/net/smsc911x.h |...] > static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) > { > u32 reg_val; > unsigned long flags; > > /* these two 16-bit reads must be performed consecutively, so must > * not be interrupted by our own ISR (which would start another > * read operation) */ > local_irq_save(flags); > reg_val = > ((readw((u16 *)(((unsigned int)pdata->ioaddr) + reg)) & 0xFFFF) | pdata->ioaddr is void * now. Please simplify. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html