ta name='generator' content='cgit v1.2.2'/>
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/spider_net.c
blob: 218524857bfc9d01b4b1ef7c132712c6e5bebdb6 (plain) (tree)
1
2
3
4
5
  
                                                                           

                               
                                         


















                                                                       






                              
                     












                            
                          

                            
                         








                                                                        
                        
                                          



                                                              

                                        






















                                                                    
                 

                                                          




                                                                               







                                                               
                  

                                                                      




                                                                               

 






















































                                                                            







                                                         
                        
 

                                                                            




















                                                                  
                                                                

                          
                                                                     

           
                                                   

                     
 

                                                                    


   
                                                              

                          
                                                                 

           
                                                  

                     
 

                                                                    




































































                                                                               
                 
                                                                
 
                                                                         













                                                           

                            
                                    
                                                    



                                                            
                                            


   
                                                          

                           
  
                                                                 

                                               
                                      


                                                   
                                                            


                                       
                                            
                       
                          
 
                                                                          
 
                                                                        
                                              
 
                           
                               
 
                                                                                  

                                                             

                                
                              


                                                                       
 
                                         
                                      


                                        
                                                          

                                     

                                      
 
                                     

                                  
                 













                                                                       
            
                                 
                                                                              
                                                              
                                                                

                                                  

                                    
                                               


   
                                                           


                                
                                      
  

                                                               




                                                           
                                                             
                       



                                                                      
                                                                       




                                                                           

                                                                            
                          
                                                              

                                                                             
                                                        

                               




                                    




                                                                         
                               
                                                          
                                                                  
                                                     
                                              
                                  
                                                              
                                                                                       
                                                        
                                                                       
                
                                        
                      
                                                                       
                                                                         

         
                 


   
                                                                  

                        
                                                                          


                                                                 
                  













                                                                           
                  

                                                      
              




                                                          













                                                                        


                                                                         
                                                                           



                                                        

                                                               
 



                                                                           


                                                       
                                                                   




                                                                   
 
                                                    


   
                                                                       

                        
                                       



                                                      


                                                               
 




                                                                        
 


                                                                  




                                                           

                                                         
                                         
                                       



                                                
                       


   










                                                                              

                






                                                                           
 
                                                           



                           
                     




























































                                                                               

                                                                 








                                                                         

                                                
                                                               
                                       
                                            
                       
                            
 
                                                                                
                                                     
                                                              
                                                                                           
                                                                            
                                                        


                               
                                               
                                    




                                                                              
                                 
                                  
 
                         



                                     
 
                                  
                                                                             
                                                    
 
                                               
                                                
                                 
                                                                        

                                 
                                                                        


                              
                                                                             

                                                                
 
                                                                            


                 
          

                                                          

                                                             
                            


                   
 

                                                                
                                              
                                                                                       






                                                                     
                                            
                           







                                                                  
                                                       





                                                                           
                                    
                                                            
                   

 









                                                                              
                                                                       



                                                                     
                                              
                                                               
                                       
                                            


                            

                   
                   
                                                       



                                                                    
                                    
                                         
 
                                                              

                                               

                                                               


                                                

                                                                            
                                         

                         







                                                                     

                                                                                           
                                               


                              
                                                

                                                                            
                                         
                         
                 
 
                                          
                                                                        
                                 
                                  
                                             



                                                            

                                                                        


                                           





                                                     
  





                                                          
   

                                                    
 
                                       
 


                                                               
 

                                    
                                                                  













                                                                          






                                                      
                                      



                                                               
                
                                                           
 
                                             
 
                                                          
                                           

                                         
         
 


                                                 
                            
 
 



                                                     



                                                              



                                                        
                                                          
                                             
                                             

                                               
























                                                                             

                                                            
   
           
                                                      
                                                    
 




                                                             
 
                                          








                                                         


                                                                           


                                                              
              
                                               






                                                      
                                         

                                           


                                  

 




                                                               


                                                         

                   
                    
                    










                                                                      


                       


















                                                                                          
                                      



                                                                                   


                                       
 
                       


























                                                                         

                                    

      

 
   



























































                                                                     
                                                           

                        
                                                                 
  



                                                                  

          
                                                         
 
                                              

                                                               
                                                             
                        
                   
 
                                                      
 


                                                              
                         
 
                                                          

                                  
                              


                                                 

                                                                  



                                                             
                                          
                                                                                 
                                        
                              



                                                       
                                           

                                                                                
                                                       
                              

         
                                                               
                                                                
                                           

                                                                     
                                                                       
                                                                          
                              

         
                                                                     
                                                                             
                                                         
                                                        





                                                                            





                                                                   

                                             
                          
                                                               


                 

                                    
                                      
                          
                                                               
                 













                                                                             
                                                                
 
                                                                                        



                                                       
                              

                               

         
                                                              

                                                      



                                                 
                                         
                                       
 

                                         

                                                                             
                                    
                                    
                                           
                                            

         
                            


   





























                                                                        
                                 

                                  


                                                





                                                                   





                                                                 




                                                                   











                                                                    




















                                                                             

                                      





                                                                      







                                                                      

                                                                         
 


                           









                                                                      




                                 



                                













                                                                            
                                                                              










































                                                                      
                                                               
                                                     

                               












                                                                    

                                                          

                               



                                                     
                                  
                                                        





                                                         
                                                   
                 
                               






                                                                 





                                                    
                                                 
                                                 
                                               
                                     
                                           







                                                     

                                                        
                                                 
                                               
                                     
                                           





















































                                                                         
                                                                      
                                                                                    









                                                                      
                         
                              







                                                                       
                                        


                                                           
                                               

                                                                      

                                                                      
 


                                                         

                                

                                             
                                           
                                     
         
                                          
                                           
 


                                              
                                            

                                                                    

















                                                                        
                                                  




                                       




                                                         
           















                                                            
           








                                                             













                                                                        




                                                                       
                                            









































                                                                            

                                                   





































                                                                               

                                                         


                                                        
                                                          
                                                 


   












































































                                                                                

                                                                           
















                                                                            
                                                            




                                                    

                                                                                  








                                                          

                                                                          




                                             











                                                                      
                   
 



                                                
                                       

                                      



                                                                              

                                                              
                                     

                                   

                                                              

                                     
                              








                                                           
                                                                



                                         

                                  
                                 
 

                                           








                                                     
                                          
                     



                      











                                                                                         

                                                                    
 

                                       


                                                                     
                                                     

                              
                                   


                                                                                
                                                       

                              
                                     


                                                                 
                                                      




























                                                                              



                                                               




               




                                      
                                                            









                                                        
 



                                               









                                                                              




                 














                                                             

                                                                 
                                                                 
                                                         
                                                                    













                                                                         









                                                           
                                  


                                        
                                          
 
                                            
 
                                      







                                                           
                                             
                                                







                                                     






                                                                      
                                                    
 


                                                                            











                                              

                                
                                     






















                                                                        
                                         

 
                                                     







                                                        
                                                    


                                 
                                                             


                                       








                                                                        
                                             
                                                             


















                                                               
                      
 


                                                 
 



                                                                     

                                      




                                                        

                                                           


                                                                

                                            
                                                          



                                                               
                              
                                    

                                               


                            
                                                             

                            



                                                   

                                                                   



                                          

                                                                              




















                                                                  
                          
 


                                                                               





                                                  
                                                                      


                                                      




                                                            

















                                                                           
















                                                                     
                                                                    



                                                              

                                                                           



                                                                

                                                                      






                                       

                                                                               












                                                             

                                                                      







































                                                                       


































                                                                       






                                                            

                                        


                                              












                                                            

                                                             































                                                                             
/*
 * Network device driver for Cell Processor-Based Blade and Celleb platform
 *
 * (C) Copyright IBM Corp. 2005
 * (C) Copyright 2006 TOSHIBA CORPORATION
 *
 * Authors : Utz Bacher <utz.bacher@de.ibm.com>
 *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/compiler.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/firmware.h>
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/mii.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <asm/pci-bridge.h>
#include <net/checksum.h>

#include "spider_net.h"

MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com> and Jens Osterkamp " \
	      "<Jens.Osterkamp@de.ibm.com>");
MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(VERSION);
MODULE_FIRMWARE(SPIDER_NET_FIRMWARE_NAME);

static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;

module_param(rx_descriptors, int, 0444);
module_param(tx_descriptors, int, 0444);

MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \
		 "in rx chains");
MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \
		 "in tx chain");

char spider_net_driver_name[] = "spidernet";

static struct pci_device_id spider_net_pci_tbl[] = {
	{ PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET,
	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
	{ 0, }
};

MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);

/**
 * spider_net_read_reg - reads an SMMIO register of a card
 * @card: device structure
 * @reg: register to read from
 *
 * returns the content of the specified SMMIO register.
 */
static inline u32
spider_net_read_reg(struct spider_net_card *card, u32 reg)
{
	/* We use the powerpc specific variants instead of readl_be() because
	 * we know spidernet is not a real PCI device and we can thus avoid the
	 * performance hit caused by the PCI workarounds.
	 */
	return in_be32(card->regs + reg);
}

/**
 * spider_net_write_reg - writes to an SMMIO register of a card
 * @card: device structure
 * @reg: register to write to
 * @value: value to write into the specified SMMIO register
 */
static inline void
spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
{
	/* We use the powerpc specific variants instead of writel_be() because
	 * we know spidernet is not a real PCI device and we can thus avoid the
	 * performance hit caused by the PCI workarounds.
	 */
	out_be32(card->regs + reg, value);
}

/** spider_net_write_phy - write to phy register
 * @netdev: adapter to be written to
 * @mii_id: id of MII
 * @reg: PHY register
 * @val: value to be written to phy register
 *
 * spider_net_write_phy_register writes to an arbitrary PHY
 * register via the spider GPCWOPCMD register. We assume the queue does
 * not run full (not more than 15 commands outstanding).
 **/
static void
spider_net_write_phy(struct net_device *netdev, int mii_id,
		     int reg, int val)
{
	struct spider_net_card *card = netdev_priv(netdev);
	u32 writevalue;

	writevalue = ((u32)mii_id << 21) |
		((u32)reg << 16) | ((u32)val);

	spider_net_write_reg(card, SPIDER_NET_GPCWOPCMD, writevalue);
}

/** spider_net_read_phy - read from phy register
 * @netdev: network device to be read from
 * @mii_id: id of MII
 * @reg: PHY register
 *
 * Returns value read from PHY register
 *
 * spider_net_write_phy reads from an arbitrary PHY
 * register via the spider GPCROPCMD register
 **/
static int
spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
{
	struct spider_net_card *card = netdev_priv(netdev);
	u32 readvalue;

	readvalue = ((u32)mii_id << 21) | ((u32)reg << 16);
	spider_net_write_reg(card, SPIDER_NET_GPCROPCMD, readvalue);

	/* we don't use semaphores to wait for an SPIDER_NET_GPROPCMPINT
	 * interrupt, as we poll for the completion of the read operation
	 * in spider_net_read_phy. Should take about 50 us */
	do {
		readvalue = spider_net_read_reg(card, SPIDER_NET_GPCROPCMD);
	} while (readvalue & SPIDER_NET_GPREXEC);

	readvalue &= SPIDER_NET_GPRDAT_MASK;

	return readvalue;
}

/**
 * spider_net_setup_aneg - initial auto-negotiation setup
 * @card: device structure
 **/
static void
spider_net_setup_aneg(struct spider_net_card *card)
{
	struct mii_phy *phy = &card->phy;
	u32 advertise = 0;
	u16 bmsr, estat;

	bmsr  = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
	estat = spider_net_read_phy(card->netdev, phy->mii_id, MII_ESTATUS);

	if (bmsr & BMSR_10HALF)
		advertise |= ADVERTISED_10baseT_Half;
	if (bmsr & BMSR_10FULL)
		advertise |= ADVERTISED_10baseT_Full;
	if (bmsr & BMSR_100HALF)
		advertise |= ADVERTISED_100baseT_Half;
	if (bmsr & BMSR_100FULL)
		advertise |= ADVERTISED_100baseT_Full;

	if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_TFULL))
		advertise |= SUPPORTED_1000baseT_Full;
	if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
		advertise |= SUPPORTED_1000baseT_Half;

	mii_phy_probe(phy, phy->mii_id);
	phy->def->ops->setup_aneg(phy, advertise);

}

/**
 * spider_net_rx_irq_off - switch off rx irq on this spider card
 * @card: device structure
 *
 * switches off rx irq by masking them out in the GHIINTnMSK register
 */
static void
spider_net_rx_irq_off(struct spider_net_card *card)
{
	u32 regvalue;

	regvalue = SPIDER_NET_INT0_MASK_VALUE & (~SPIDER_NET_RXINT);
	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}

/**
 * spider_net_rx_irq_on - switch on rx irq on this spider card
 * @card: device structure
 *
 * switches on rx irq by enabling them in the GHIINTnMSK register
 */
static void
spider_net_rx_irq_on(struct spider_net_card *card)
{
	u32 regvalue;

	regvalue = SPIDER_NET_INT0_MASK_VALUE | SPIDER_NET_RXINT;
	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}

/**
 * spider_net_set_promisc - sets the unicast address or the promiscuous mode
 * @card: card structure
 *
 * spider_net_set_promisc sets the unicast destination address filter and
 * thus either allows for non-promisc mode or promisc mode
 */
static void
spider_net_set_promisc(struct spider_net_card *card)
{
	u32 macu, macl;
	struct net_device *netdev = card->netdev;

	if (netdev->flags & IFF_PROMISC) {
		/* clear destination entry 0 */
		spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, 0);
		spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, 0);
		spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
				     SPIDER_NET_PROMISC_VALUE);
	} else {
		macu = netdev->dev_addr[0];
		macu <<= 8;
		macu |= netdev->dev_addr[1];
		memcpy(&macl, &netdev->dev_addr[2], sizeof(macl));

		macu |= SPIDER_NET_UA_DESCR_VALUE;
		spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, macu);
		spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, macl);
		spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
				     SPIDER_NET_NONPROMISC_VALUE);
	}
}

/**
 * spider_net_get_mac_address - read mac address from spider card
 * @card: device structure
 *
 * reads MAC address from GMACUNIMACU and GMACUNIMACL registers
 */
static int
spider_net_get_mac_address(struct net_device *netdev)
{
	struct spider_net_card *card = netdev_priv(netdev);
	u32 macl, macu;

	macl = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACL);
	macu = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACU);

	netdev->dev_addr[0] = (macu >> 24) & 0xff;
	netdev->dev_addr[1] = (macu >> 16) & 0xff;
	netdev->dev_addr[2] = (macu >> 8) & 0xff;
	netdev->dev_addr[3] = macu & 0xff;
	netdev->dev_addr[4] = (macl >> 8) & 0xff;
	netdev->dev_addr[5] = macl & 0xff;

	if (!is_valid_ether_addr(&netdev->dev_addr[0]))
		return -EINVAL;

	return 0;
}

/**
 * spider_net_get_descr_status -- returns the status of a descriptor
 * @descr: descriptor to look at
 *
 * returns the status as in the dmac_cmd_status field of the descriptor
 */
static inline int
spider_net_get_descr_status(struct spider_net_hw_descr *hwdescr)
{
	return hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
}

/**
 * spider_net_free_chain - free descriptor chain
 * @card: card structure
 * @chain: address of chain
 *
 */
static void
spider_net_free_chain(struct spider_net_card *card,
		      struct spider_net_descr_chain *chain)
{
	struct spider_net_descr *descr;

	descr = chain->ring;
	do {
		descr->bus_addr = 0;
		descr->hwdescr->next_descr_addr = 0;
		descr = descr->next;
	} while (descr != chain->ring);

	dma_free_coherent(&card->pdev->dev, chain->num_desc,
	    chain->hwring, chain->dma_addr);
}

/**
 * spider_net_init_chain - alloc and link descriptor chain
 * @card: card structure
 * @chain: address of chain
 *
 * We manage a circular list that mirrors the hardware structure,
 * except that the hardware uses bus addresses.
 *
 * Returns 0 on success, <0 on failure
 */
static int
spider_net_init_chain(struct spider_net_card *card,
		       struct spider_net_descr_chain *chain)
{
	int i;
	struct spider_net_descr *descr;
	struct spider_net_hw_descr *hwdescr;
	dma_addr_t buf;
	size_t alloc_size;

	alloc_size = chain->num_desc * sizeof(struct spider_net_hw_descr);

	chain->hwring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
		&chain->dma_addr, GFP_KERNEL);

	if (!chain->hwring)
		return -ENOMEM;

	memset(chain->ring, 0, chain->num_desc * sizeof(struct spider_net_descr));

	/* Set up the hardware pointers in each descriptor */
	descr = chain->ring;
	hwdescr = chain->hwring;
	buf = chain->dma_addr;
	for (i=0; i < chain->num_desc; i++, descr++, hwdescr++) {
		hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
		hwdescr->next_descr_addr = 0;

		descr->hwdescr = hwdescr;
		descr->bus_addr = buf;
		descr->next = descr + 1;
		descr->prev = descr - 1;

		buf += sizeof(struct spider_net_hw_descr);
	}
	/* do actual circular list */
	(descr-1)->next = chain->ring;
	chain->ring->prev = descr-1;

	spin_lock_init(&chain->lock);