X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fmv643xx_eth.c;h=b3bf86422734a07eb7ec37da30bd1cd1acdb0b95;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=411f4d809c477d99175ee0eaa10257938a08d407;hpb=43bc926fffd92024b46cafaf7350d669ba9ca884;p=linux-2.6.git diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 411f4d809..b3bf86422 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -74,7 +74,7 @@ static int ethernet_phy_detect(unsigned int eth_port_num); static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location); static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val); static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static struct ethtool_ops mv643xx_ethtool_ops; +static const struct ethtool_ops mv643xx_ethtool_ops; static char mv643xx_driver_name[] = "mv643xx_eth"; static char mv643xx_driver_version[] = "1.0"; @@ -277,9 +277,11 @@ static void mv643xx_eth_tx_timeout(struct net_device *dev) * * Actual routine to reset the adapter when a timeout on Tx has occurred */ -static void mv643xx_eth_tx_timeout_task(struct net_device *dev) +static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly) { - struct mv643xx_private *mp = netdev_priv(dev); + struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private, + tx_timeout_task); + struct net_device *dev = mp->mii.dev; /* yuck */ if (!netif_running(dev)) return; @@ -312,6 +314,13 @@ int mv643xx_eth_free_tx_descs(struct net_device *dev, int force) while (mp->tx_desc_count > 0) { spin_lock_irqsave(&mp->lock, flags); + + /* tx_desc_count might have changed before acquiring the lock */ + if (mp->tx_desc_count <= 0) { + spin_unlock_irqrestore(&mp->lock, flags); + return released; + } + tx_index = mp->tx_used_desc_q; desc = &mp->p_tx_desc_area[tx_index]; cmd_sts = desc->cmd_sts; @@ -330,13 +339,13 @@ int mv643xx_eth_free_tx_descs(struct net_device *dev, int force) if (skb) mp->tx_skb[tx_index] = NULL; - spin_unlock_irqrestore(&mp->lock, flags); - if (cmd_sts & ETH_ERROR_SUMMARY) { printk("%s: Error in TX\n", dev->name); mp->stats.tx_errors++; } + spin_unlock_irqrestore(&mp->lock, flags); + if (cmd_sts & ETH_TX_FIRST_DESC) dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); else @@ -385,6 +394,8 @@ static int mv643xx_eth_receive_queue(struct net_device *dev, int budget) struct pkt_info pkt_info; while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { + dma_unmap_single(NULL, pkt_info.buf_ptr, ETH_RX_SKB_SIZE, + DMA_FROM_DEVICE); mp->rx_desc_count--; received_packets++; @@ -505,8 +516,7 @@ static void mv643xx_eth_update_pscr(struct net_device *dev, * Output : N/A */ -static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct mv643xx_private *mp = netdev_priv(dev); @@ -778,7 +788,7 @@ static int mv643xx_eth_open(struct net_device *dev) int err; err = request_irq(dev->irq, mv643xx_eth_int_handler, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (err) { printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n", port_num); @@ -1097,7 +1107,7 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, ETH_TX_ENABLE_INTERRUPT; mp->tx_skb[tx_index] = skb; } else - mp->tx_skb[tx_index] = 0; + mp->tx_skb[tx_index] = NULL; desc = &mp->p_tx_desc_area[tx_index]; desc->l4i_chk = 0; @@ -1133,7 +1143,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, eth_tx_fill_frag_descs(mp, skb); length = skb_headlen(skb); - mp->tx_skb[tx_index] = 0; + mp->tx_skb[tx_index] = NULL; } else { cmd_sts |= ETH_ZERO_PADDING | ETH_TX_LAST_DESC | @@ -1145,7 +1155,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, desc->byte_cnt = length; desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); - if (skb->ip_summed == CHECKSUM_HW) { + if (skb->ip_summed == CHECKSUM_PARTIAL) { BUG_ON(skb->protocol != ETH_P_IP); cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | @@ -1200,7 +1210,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (has_tiny_unaligned_frags(skb)) { - if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { + if (__skb_linearize(skb)) { stats->tx_dropped++; printk(KERN_DEBUG "%s: failed to linearize tiny " "unaligned fragment\n", dev->name); @@ -1250,7 +1260,7 @@ static void mv643xx_netpoll(struct net_device *netdev) /* wait for previous write to complete */ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); - mv643xx_eth_int_handler(netdev->irq, netdev, NULL); + mv643xx_eth_int_handler(netdev->irq, netdev); mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL); } @@ -1359,8 +1369,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) #endif /* Configure the timeout task */ - INIT_WORK(&mp->tx_timeout_task, - (void (*)(void *))mv643xx_eth_tx_timeout_task, dev); + INIT_WORK(&mp->tx_timeout_task, mv643xx_eth_tx_timeout_task); spin_lock_init(&mp->lock); @@ -2154,7 +2163,7 @@ static void eth_update_mib_counters(struct mv643xx_private *mp) for (offset = ETH_MIB_BAD_OCTETS_RECEIVED; offset <= ETH_MIB_FRAMES_1024_TO_MAX_OCTETS; offset += 4) - *(u32 *)((char *)p + offset) = read_mib(mp, offset); + *(u32 *)((char *)p + offset) += read_mib(mp, offset); p->good_octets_sent += read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_LOW); p->good_octets_sent += @@ -2163,7 +2172,7 @@ static void eth_update_mib_counters(struct mv643xx_private *mp) for (offset = ETH_MIB_GOOD_FRAMES_SENT; offset <= ETH_MIB_LATE_COLLISION; offset += 4) - *(u32 *)((char *)p + offset) = read_mib(mp, offset); + *(u32 *)((char *)p + offset) += read_mib(mp, offset); } /* @@ -2721,7 +2730,7 @@ static void mv643xx_get_ethtool_stats(struct net_device *netdev, eth_update_mib_counters(mp); for (i = 0; i < MV643XX_STATS_LEN; i++) { - char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset; + char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset; data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; } @@ -2764,7 +2773,7 @@ static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int c return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); } -static struct ethtool_ops mv643xx_ethtool_ops = { +static const struct ethtool_ops mv643xx_ethtool_ops = { .get_settings = mv643xx_get_settings, .set_settings = mv643xx_set_settings, .get_drvinfo = mv643xx_get_drvinfo,