Francois, Thanks for your comments. I have absorbed almost all of your suggestions. You skimmed through 33% of the file before you dozed off... Waiting for the rest! Kiran -----Original Message----- From: netdev-owner@xxxxxxxxxxxxxxx [mailto:netdev-owner@xxxxxxxxxxxxxxx] On Behalf Of Francois Romieu Sent: Monday, June 26, 2006 3:31 PM To: Kiran Thota Cc: 'Yoichi Yuasa'; linux-mips@xxxxxxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; Raj Palani; ralf@xxxxxxxxxxxxxx Subject: Re: [Repost PATCH 6/6] PMC MSP85x0 gigabit ethernet driver Kiran Thota <Kiran_Thota@xxxxxxxxxxxxxx> : [...] > - Based on linux-2.6.12 from > > http://www.linux-mips.org/pub/linux/mips/kernel/v2.6/linux-2.6.12.tar. > gz Is there a reason why the patch is not diffed against a more recent version of the mips tree ? The patch includes ~130 lines ending with a tab or space delimiter. They could be removed. [...] > diff -Naur a/drivers/net/msp85x0_ge.c b/drivers/net/msp85x0_ge.c > --- a/drivers/net/msp85x0_ge.c 1969-12-31 16:00:00.000000000 -0800 > +++ b/drivers/net/msp85x0_ge.c 2006-06-26 12:12:39.000000000 -0700 [...] > +/* Static Function Declarations */ > +static int msp85x0_ge_eth_open(struct net_device *); static int > +msp85x0_ge_eth_reopen(struct net_device *netdev); static void > +msp85x0_ge_eth_stop(struct net_device *); static struct > +net_device_stats *msp85x0_ge_get_stats(struct net_device *); static > +int msp85x0_ge_init_rx_desc_ring(msp85x0_ge_port_info *, int, int, > + unsigned long, unsigned long, > + unsigned long); > +static int msp85x0_ge_init_tx_desc_ring(msp85x0_ge_port_info *, int, > + unsigned long, unsigned long); > + > +static int msp85x0_ge_open(struct net_device *); static int > +msp85x0_ge_start_xmit(struct sk_buff *, struct net_device *); static > +int msp85x0_ge_stop(struct net_device *); > + > +static unsigned int msp85x0_ge_tx_coal(int); > + > +static void msp85x0_ge_port_reset(unsigned int); static int > +msp85x0_ge_free_tx_queue(struct net_device *); static int > +msp85x0_ge_rx_task(struct net_device *, msp85x0_ge_port_info *); > +static int msp85x0_ge_port_start(struct net_device *); static int > +msp85x0_eth_setup_tx_rx_fifo(struct net_device *dev); static int > +msp85x0_ge_xdma_reset(void); You should be able to remove the forward declarations by correctly reordering the code. [...] > +static struct platform_device *msp85x0_ge_device[NO_PORTS]; static > +struct net_device *msp85x0_eth[NO_PORTS]; static unsigned int > +msp85x0_ge_sram; static unsigned int port_number; The way it is used, port_number should be a local variable. > + > +/* > + * The MSP85x0 GE has two alignment requirements: > + * -> skb->data to be cacheline aligned (32 byte) > + * -> IP header alignment to 16 bytes > + * > + * The latter is not implemented. So, that results in an extra copy > +on > + * the Rx. This is a big performance hog. For the former case, the > + * dev_alloc_skb() has been replaced with msp85x0_ge_alloc_skb(). The > +size > + * requested is calculated: > + * > + * Ethernet Frame Size : 1518 > + * Ethernet Header : 14 > + * Future MSP85x0 change for IP header alignment : 2 > + * > + * Hence, we allocate (1518 + 14 + 2+ 64) = 1580 bytes. For IP > +header > + * alignment, we use skb_reserve(). > + */ > +#define ALIGNED_RX_SKB_ADDR(addr) \ > + ((((unsigned long)(addr) + (32UL - 1UL)) \ > + & ~(32UL - 1UL)) - (unsigned long)(addr)) #define > +msp85x0_ge_alloc_skb(__length, __gfp_flags) \ > +({ struct sk_buff *__skb; \ > + __skb = alloc_skb((__length),(__gfp_flags)); \ > + if(__skb){ \ > + int __offset = (int) ALIGNED_RX_SKB_ADDR(__skb->data); \ > + if(__offset) \ > + skb_reserve(__skb, __offset); \ > + } \ > + __skb; \ > +}) Please use a function for msp85x0_ge_alloc_skb. > + > +int increment_tx_pkt_count(unsigned int port) static > +{ > + unsigned int flags; > + spin_lock_irqsave(&msp85x0_lock,flags); > + if(port==0){ CodingStyle: if (port == 0) { (or 'if (!port)') > + port0_pkt_count++; > + } > + else{ } else { > + port1_pkt_count++; > + } > + spin_unlock_irqrestore(&msp85x0_lock,flags); increment_tx_pkt_count() is only issued from msp85x0_ge_tx_queue(), itself only issued from msp85x0_ge_start_xmit and xmit handlers run with irq enabled. The save/restore is not needed. > + return 0; Useless return. > +} > + > +unsigned int get_tx_pkt_count(unsigned int port) static > +{ > + unsigned int flags,pktCount,tx_pending_pkt; Mixed case can be avoided here. > + spin_lock_irqsave(&msp85x0_lock,flags); See above. > + tx_pending_pkt=MSP85x0_GE_READ(MSP85x0_GE_CHANNEL0_TX_DMA_STS + (port << XDMA_PORT_OFFSET)); > + if(port==0){ > + pktCount=port0_pkt_count - tx_pending_pkt; > + } > + else{ Sic. > + pktCount=port1_pkt_count - tx_pending_pkt; > + } > + spin_unlock_irqrestore(&msp85x0_lock,flags); > + return pktCount; > +} > + > +unsigned int decrement_tx_pkt_count(unsigned int port) static [...] > +void msp85x0_bringup_sequence(int port) static > +{ > + unsigned int reg_data; > + > + /* SDQPF */ > + reg_data=MSP85x0_GE_READ(MSP85x0_GE_SDQPF_RXFIFO_CTL + (port << 8)); reg_data = MSP85x0_GE_READ(MSP85x0_GE_... [...] > +static void msp85x0_ge_gmii_config(int port_num) { [...] > + if (phy_reg & 0x8000) { > + if (phy_reg & 0x2000) { > + /* Full Duplex and 1000 Mbps */ > + MSP85x0_GE_WRITE((MSP85x0_GE_GMII_CONFIG_MODE + > + (port_num << MII_PORT_OFFSET)), 0x201); > + } else { > + /* Half Duplex and 1000 Mbps */ > + MSP85x0_GE_WRITE((MSP85x0_GE_GMII_CONFIG_MODE + > + (port_num << MII_PORT_OFFSET)), 0x2201); > + } > + } :o( mode = (phy_reg & 0x2000) ? 0x0201 : 0x2201; MSP85x0_GE_WRITE((MSP85x0_GE_GMII_CONFIG_MODE + (port_num << MII_PORT_OFFSET)), mode); > + if (phy_reg & 0x4000) { > + if (phy_reg & 0x2000) { > + /* Full Duplex and 100 Mbps */ > + MSP85x0_GE_WRITE((MSP85x0_GE_GMII_CONFIG_MODE + > + (port_num << MII_PORT_OFFSET)), 0x100); > + } else { > + /* Half Duplex and 100 Mbps */ > + MSP85x0_GE_WRITE((MSP85x0_GE_GMII_CONFIG_MODE + > + (port_num << MII_PORT_OFFSET)), 0x2100); > + } > + } I'd bet you could make a single MSP85x0_GE_WRITE for this one and the two above. [...] > +static void msp85x0_ge_update_afx(msp85x0_ge_port_info * > +msp85x0_ge_eth) { > + int port = msp85x0_ge_eth->port_num; > + unsigned int i; > + volatile unsigned long reg_data = 0; Mantra: volatile is not the answer. Now, what's the question ? :o) [...] > +static void msp85x0_ge_tx_timeout_task(struct net_device *netdev) { > + msp85x0_ge_port_info *msp85x0_ge_eth = netdev_priv(netdev); > + int port = msp85x0_ge_eth->port_num; > + > + printk("MSP85x0 GE: Transmit timed out. Resetting ... \n"); Missing KERN_xyz [...] > +static int msp85x0_ge_change_mtu(struct net_device *netdev, int > +new_mtu) { [...] > + if (netif_running(netdev)) { > + msp85x0_ge_eth_stop(netdev); > + MSP85x0_GE_WRITE((MSP85x0_GE_RMAC_MAX_FRAME_LEN + > +(msp85x0_ge_eth->port_num << MAC_PORT_OFFSET)), new_mtu + 2); // for > +the padded bytes > + > + if (msp85x0_ge_eth_reopen(netdev) != 0) { > + printk(KERN_ERR > + "%s: Fatal error on opening device\n", > + netdev->name); > + spin_unlock_irqrestore(&msp85x0_ge_eth->lock, flags); > + return -1; Please use -Esomething. You may consider goto to balance spin_{lock/unlock}. [...] > +static irqreturn_t msp85x0_ge_sequoia_int_handler(int irq, void *dev_id, > + struct pt_regs *regs) > +{ > + struct net_device *netdev = (struct net_device *) dev_id; Useless cast from void *. [...] > + /* Handle the Rx next */ > + if (eth_int_cause1 & (RX_INT << (port_num * 16))) { > + clear_xdma_interrupts(port_num,RX_INT); > + if (netif_rx_schedule_prep(netdev)) { > + msp85x0_ge_disable_rx_int(port_num); > + __netif_rx_schedule(netdev); The indentation went badly wrong. [...] > +static int msp85x0_ge_open(struct net_device *netdev) { > + msp85x0_ge_port_info *msp85x0_ge_eth = netdev_priv(netdev); > + unsigned int port_num = msp85x0_ge_eth->port_num; > + unsigned int irq; > + int retval; > + > + spin_lock_irq(&(msp85x0_ge_eth->lock)); > + > + if (msp85x0_ge_eth_open(netdev) != MSP85x0_OK) { > + spin_unlock_irq(&(msp85x0_ge_eth->lock)); > + printk("%s: Error opening interface \n", netdev->name); Missing KERN_xyz > + free_irq(netdev->irq, netdev); request_irq() comes later. > + return -EBUSY; Why not propagate an usual return status code from msp85x0_ge_eth_open ? > + } > + > + spin_unlock_irq(&(msp85x0_ge_eth->lock)); > + > + irq = MSP85x0_ETH_PORT_IRQ; > + > + retval = request_irq(irq, INTERRUPT_HANDLER, > + SA_SAMPLE_RANDOM | SA_SHIRQ, netdev->name, netdev); > + > + if (retval != 0) { > + printk(KERN_ERR "Cannot assign IRQ number to MSP85x0 GE \n"); > + return -1; - msp85x0_ge_eth_open() should be balanced a bit (stop queuing for instance) ; - no need to throw away retval. (some sleep needed here, sorry) -- Ueimor - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html