aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/ethernet/qlogic/qlge/qlge_main.c
blob: 059ba9429e51a3193f3af73c16a20ce94ef42844 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                          
                         

























                              
                          
                         


                          
                           
                             

















                                                      

                                                                 


                                     

                                            




                                                           
                                    
                                       
                                                                   
 



                                                      






                                                               
 
                                                    
                                                                
                                                                





                                       



                                                         
 

































                                                                
                                                                               








                                                          
                                     


                                                    

                               























                                                                           


                                                                                         





                                      

                                                                          









































                                                                       
                                                                              


                               



                                                     

                                        

                                                                        


                          

                                                   









                                                        
                                                                    










                                                                            





                                                 
                                                              






                                                                                 
                                                              




                                                                  
                                                              






                                                                                 
                                                              





                                                                  
                                                                      






                                                                                         
                                                                    








                                                                          

                                                                         


                                











                                                                           

                                     






























                                                                       






                                                                                

                                                 
                                                              







                                                                                
                                                              







                                                                                
                                                              








                                                                                    



                                                                    
                                                                           


                                                                    









                                                                        

                                                 
                                                              









                                                                                   

                                                                         


                                


                      










                                                            
                                                  

                                                                
                
                                             
                                         

                                                                







                                                                    

                                                           


                      

                                        
                                                           





                                         
                                                             



                                      






                                                                      
                                                             




                                                                               
                                                             



                                          










                                                                                
                                                                  

                      





















                                                                                     















                                                                         








                                                                               
                                                                  





                                                                                  
                                                                  


















                                                                                     

                                                                     












                                                                     















                                                                          
                                                                      

                                                                 
                                                                     
 







                                                                      
                                         


                                              
         








                                                         




                                                                             
                                 
 






                                                                    
                                  
                                          
                                         
                                    

                                           
                                  
                                    










                                                                        


                                                                        




                                                        







                                                                                
                                                                                






                                              

                                                                             



                    
                                                                                













                                                                    




                                                         



                      





                                                            
                       



                                                   
                        










                                                               

                                                            







                                                                       
                                                                      



                                 












                                                                
                                                                            




                                    
                         






                                            
                                                            


                   
                                           
                       
                                                                  



                                                        
                       
                              



                                                  
                                         
                                                               
                             

                                                            



                                  




                                                                       
                                                                      












                                                                           





































































                                                                         

                                                           
                   






                                                     






                                                                         

 





                                                          
                                                           







                                                            

                                                                                                                 

                                                                        

                                                                   



                              
                                                                      






















































                                                                                          




                                                                     
                                
                                                                








                                                                        





                                                                  
                                                                          














                                                                   
                                
                                                                
























                                                                        




                                                                              
                                                                             

                                                                     

                                                               








                                                                      
                                                      

                                                           
























                                                                            


                                                                           

                                               
                                 


                
                                            
                                                                      


                                                                             
                                                            
                                                                         
                                                                   
                                                                 

                                                                                                      

                                       


                                                            

                                                                           
                                                               
                                                                   



                                                                       








                                                              



                                            


                                                                     

                                                              





                                                                           

                                               
                                 



                                            
                                                                      
                                                            


                                                                             
                                                      



                                                                                    

                                                                
                                                                        
                                                              





                                                                           

                                                                           
                                                                             

                                                                           
                                                                           

                                                                           

                                               

                                                                           
                                                                         
                                                                   









                                                              



                                            


                                                                     

                                                              




























                                                                        


                                                                       

                                                    
                                                                              
                                                                 
                                                                             


                                                               

                                                                           
                                                  
                                                                            
                                                               
                                                                           



















                                                                                

                                                                     







                                                                           

                                                                      





                                      

                                                                      




































                                                                            


                                                                                               











                                                                             
                                                                                
                                                
                                                                              




                                                                       
                                                                                      
                                                      
 
                                                               
                          


                                                                               



                                             
                                                            

                                                                              
                                                       


















                                                                  
                                                

                                                                    



                                                   
                             























                                                    






















                                                                         
                                                    







                                                                           

                                                  





                                                                        



                                   

                                                             




                                                    



                                                            









                                                 
                              
                                                                         
                             


                                                    










                                                                           
                               


                                             







                                                    





                                                                        


                                                             


                                                                   
                                          

                                                            


                                      
                                      


                                                                                                     
                                                             




                                                                   



                                                  
                                      
 
                                                


                                                               

                                                                             



                                                                            
                                           
                                                                    
                                             
                                                          
                                                                      

                                                                         
                                                                     




                                                 
                              
                                                                         



                                                   





















                                                                           



                                           





                                                                      
                                                 




                                                                         

                      






                                                                        
















                                                                   
                                                          







                                                                             

                                                   

                                                                     



                                                  
                                      



                                                 
                                                


                                                               

                                                                             





                                                                            
                                                          
                                                                      

                                                                         
                                                                     




                                                 
                              
                                                                         



                                                      

 
                                                        








                                                     
                                           














                                                                          

                                                       





                                                      

                                                                               




                                                          

                                                                  










                                                                

                                                                     




                                                              


                                                                                                    








                                                                             
                                                                  
                                                                        
                                                                 

                                                                        
                                                                         
                                                                  
                                                                     

                                                                 
                                                                    



                                                                           


                                                                             




                                                             
                                                                 
                                                                 
                                                                





                                                               


                                                                                                   




                                                                      
                                                                     


                                                                                             


                                                                             


                                                





                                                                                   
                                                                     

                                                                   

                                                                                     

                                            
                                                  
                                                               
                                                               
                                                                       
                                                           
                                                       


                                                                                                                     



                                                                            


                                                



                                                                      












                                                                     
                                

                                                     

                                                                   










                                                                   


                                                                                       
                                              

                                                       
                 
                    


                                                                          
 


                                                                             



                                                                            



                                              
                            
                                     


                                                                                




                                                    
                                                                 
                                                           

                                                                      







                                                         

                                                                     
                                      


                       






                                                                        




                                                                   
                                      


                       






                                                  
                            
                                                          






                                                                                        
                                        

                                                     

                                                                     
         
 
                                                  
                                      



                                                 
                                                


                                                               

                                                                             





                                                                            
                                                          
                                                                      

                                                                                     

                         
         
 

                                      
                                                 
                              
                                                                         



                                                      

 





                                                                           

                                                                           

















                                                                       







                                                                      






                                                                 




                                                                        




                                     










                                                                   

                                                      







                                                                                  

                                                                                               

                                                          

                                                                               

                                                          

                                                                         

                                                          

                                                                             







                                                   
                          




                                                                      
                          
                                    




                                                          



                                                                      







                                                                       

                                                                 



                                        

                                                                               



                                          
                                                                     



                                          


                                                                               



                                          

                                                                          







                                                             
                                                            


                                               
                                


                                                              
                                                                     
                                                                   
                                                                       









                                                                        


                                                                                                          


                                      
                                                                
         

                         
                                 
                                                   
                                                                   
                                                                              



                                                                              
                                                                        







                                                                        
                                                            





                                                              
                                                                     
                                                                   
                                                                       














                                                                               



                                                                                                          


                                      
                                                                











                                                                           


                                                                       
 

                                                                       
 









                                                                        


                                                                              








                                                             


                                                                      


                                                                      
                                 
                                                    




                                                                   
                                                                               


                                                    
                                                 
                                                                     
                                                                 
                



                                                                     








                                                                            
                                                
 






                                                                        




                                                    






                                                                      
         
 


                      

                                                     
 
                                                              






                                                                      
 
                                               
         



                 
                                                                   
 
                                    
                
 


                                                           

                                                            
                   

 
                                                                               

                                                    
                   
                


                                                          
                              
 
                                                


                                               

                   

 
                                                                    

                           
                
 


                                                           

                                                             
                   

 
                                                                                


                                                    
                
 

                                                          
                              
 
                                                 


                                               

                   

 

                                                      










                                                             

 



                                                                      
                                      


                           










                                                                   

                          

                                                          

                                                                

                                            
         
                                    
 
                                                                        





                                          
                                                                            
                                               

                                                                               





                                        

                                                              



                                                                   

                                                            
                                                                          


                                                                     



                            


                                                                 
           

                                           

                                                               
                                                                          


                                              
                                                                 







                                                                                
                                                         



                                           











                                                                             
                                                          






                                                                               
                                                           















                                                                      
                       
























                                                                         
                                                                          





                                                    
                                                   


                                              


                                     
                                                            
                                                       
                                                                                            
                                                  
                                                          
                                     



                                                      
                                                               










                                                                             
                                        
                                                                     
                                                                               
                                                      
                                                                            








                                                                             

                                                                 

                                                           
                                     

                                      





                                                 

                                                                             


                                                             

                                       









                                                                              


                            
 




















                                                                  

                                                                     
                                                    

                                                                     

                               
 
                                       

                                                                     
                                                    

                                                                     



























                                                                             




















                                                                            
                                         


                                                 
                    

                                                                       






                                                                    


                                                                     


                       
                                                                                 
 

                                 







                                                     
                                                  

                                                         
                                                           
                                                           
                 






                                                    
         





                                                                     

 
                                                                                 






                                                

                                                               



                                                    

                                                                           



                                                             


         














































                                                                           



                                                        
                                       
 
                                                                           

                                                
                                                       
                                    
                                    

                     




                                                         














































                                                                              
                                                                             











                                                                       

                                                                             





                                                              



                                                                    
                                     
 
                                                










                                                                       

                                                                             




                                                              



                                                                    
                                     
 
                                                























                                                                



                                                                                            








                                                                     




















                                                                          

                                                                      





                                                                          

                                                                      

















                                                                             
                                                        
                                                           
                                                        



                                                                          
                

                                  



                                                        
                                      



                                                        

                                                                                



                                                                      
                                                                  






                                                                    
                                                                              

                                          
                                                                              



                                                       

                                                                        
 
                                                        
 
                                                                         








                                                                     
                                                 
                                                               






                                                                               

                                                                




                                                               
                                                     
                                          
                                          

                                                         


                                                                     
                                                 
                                                               






                                                                               

                                                                
                                     
                                                              

                                                          
                                                     
                                          
                                          

                                                         


                                


                                                                              









                                                                              

                                                                             
         


                                                             
                                                                             

                           

















                                                                             
                                                                 














                                                                             
                                                        
 
                                                                           


                                       
                                                                

                                                 
                                                                               

                           















                                                            



                                                   

                                                   
                   
 
                                   
                                        


                                                          
                                                             


                                                                      
                                                


                                 
                                                      

                                                       

                                                                          
                              

                                                 

                                                                         
                                                

                                               
                                                               


                                                                      
                               


                 
                             
                                       

                                                              

                                                                     


                               
                                

                                                          

 





                                                         
                                                       

























































                                                                              










                                                                   



                                                              




                                                                        



                                                                       















                                                                                 




                                                                         
                                   
                                                                 


                                                                       
                                  
                                                                             
                                   

                                                                         
                                                             
























                                                                                





                                                                  
         



                                                         











                                                                      

                                                                             























                                                                         


                                                                                    
                                             

                         









                                                                             








                                                                               







                                                                                   




                                         
                                                                               





                                                






                                                               




                                              
                                               
 
                                
                     

                                                                         



                                          

                                                              
 

                                                                    
 
                                                                    
                     
                                                                            

                              


                      
                                                            
 
                          
 


                                                        



                                                           

                                                                                        
                              

                 








                                                       

                                                         


                              
                                                        
                   
                              
 









                                                                       
                     
                                                 

                                                             
                          


                                                                              

                                                                                      
                          







                                                                          

                                                                                              
                                  




                                                              
                   

                                                                                

                                             


                      
                                                    
 
                        
 






                                                  
                     
                                                                                   




                                           
                                                                                     



                      












                                                         
                                                       





                                                             






                                                                         

                                    





                                                          
                                             
 





                                                                         















                                                               
 



                                                                   

                                                                       









                                                             
                                                                                    







                                                                   

                                                                       



                                      

                                                            
                   
                                                                             
 

                                                              
                     

                                                                  



                                            
                                                  
                                                    







                                                    
                       
                                  
 


                                                         
                                                                                     


                              










                                                                       
 
                                                                
 
                                                     



                                                

                                                    
 
                                

                                                                               
                                    

         

                                                                 




                                                        
                                                    
 










                                                                       

 
                                          












                                                                              
                                                   
                                                                           
                                     





                                                      


                                                                        

                                      


                                                                                




                                        

                                                   

                                                           
                                                                        
                                                 




                      
                                                            
 
 




                                                                 

                                                        
                                                      
                                                         
                                                           








                                                   
 

                                                     






                                               

                                                   
                                                  

                                                       

                                        

                                                                                

                                 






                                                 

                                          
                                                                                      

                              
                                             
                                  




                                                                    
                                 




                                                


                                   

                                                  
                                              






                               










                                                                 
                                                                                   


                                      






                                                    




                                                   
                                                                            



                                                      







                                                      







                                                      
                                                            



                                                              






                                                                       
           



                                                                   
                                      
                                                                         
 

                                                   
                                                             







                                                                     
                                                   
                   
                                                          



                                                   
                                                             


                                                                            
                                               


                                                




                                                                             
                                                              
                                                                 

                                                             
                                                              
                                                                   

                                             













                                                                              









                                                    



                                     















                                             


                   





                                                        
                                                        
                                                     


                                                                       

                                                                 



                                  

                                                                        
























                                                              

                                                                      




                                             


                                                                
                   

                                                   
                                                                              
                                                          
                                                                               

                               



                                                        

                            
                                         


                         

                                            

                                                    


                      




                                                                






























                                                               
                            

 
                                                            
 
                                                    
                                  
                      
 


                                                        







                                                                               
                                                               
                                                                               







                                                                               
                                                               
                                                                                 










                                                                        
                                                              


                                                                            

                                                                             







                                                                            

                                                                               





                                                                     
                                     


                                                                  
                      

                                                                      
                                                                              

                                                                                
                                                                       

                                          

                            
                                                       

                                                                             

                                                                           




                                                           
                                             



                                                                 
                                                    
                                  
                   
 


                                                              

                                                                       
 


                                                          

                                                                    
                   
                                                                                 

                                               



                                                    
                                                    
                                  





                                                                        
                   
                    






                                       





                                                
                      

               

                                                                     
 


                                             

 
                                                      



                                                           
                                                      



                                                           































                                                              
 
                                                     
 
                   

                                                                           








                                                           












                                                                             


                                                   

                                                        
                      










                                                        
 
                           
                                        

                                             
                                  
                                  

 

                                                                        

                                                    
                    
 
                                               





                                                                   


                                    
 



                                                            
                              

         


                                                                    
                           


                             
                                                        
                                                
                                                                          
                
                                                               
                         
                                                                                 



                                                                      
                              

         

                                                         
                             





                                                                  
                              








                                                                           
                              

         



                                                                 
                              
         



                                                              



                                                                
                                      
                                      
                 

                                                               
         
                                          
                                             

                                                        
                              

         

                                                                       













                                                              

                                                                       


                                                                      
                                                                          
                                                                
                                                                      
                                               
                                     






                                                                       
         
                             
         



                                 





                                                      
                                                          


                                                       
                                                    

                                                        

  
                                          
 
                                                             



                                              
                                                                               


                       
                                                  

 
                                           
                                                            





                                       
                                                           
                                                                           










                                                      








                                                         
                                                
                                                          


                                                              








                                                  

                                            
                                              
                                       
 






                                                                          




                                                                         
                                  

                           


                                               

                                                              
                          
                                  
                                       



                      









                                                                    
                                             

                                                        

                                                    
                                      





                                 










                                                    
                                 
                                      









                                                       







                                                                            
                                                    
 




                                                  
                                             






                                                                        
                                             

                                                    
                                                 
         















                                                                  


                                                  
                                      

                                                                        

                                                 
                             

                                     
                                                                    
                                                    


                                                 






                                                        
                    
 
                                  

                                      

                                                                                 

                               
                

                                                                    
         
                                                  


                                  
                                                           








                                                                 
                

                                  
                                     






                                            
                     










                                                                 
                









                                                        
                                                                                             












                                             
                                                  



                                  
                      









                                               
                              







                                        
                               
/*
 * QLogic qlge NIC HBA Driver
 * Copyright (c)  2003-2008 QLogic Corporation
 * See LICENSE.qlge for copyright and licensing details.
 * Author:     Linux qlge network device driver by
 *                      Ron Mercer <ron.mercer@qlogic.com>
 */
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/pagemap.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/dmapool.h>
#include <linux/mempool.h>
#include <linux/spinlock.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/prefetch.h>
#include <net/ip6_checksum.h>

#include "qlge.h"

char qlge_driver_name[] = DRV_NAME;
const char qlge_driver_version[] = DRV_VERSION;

MODULE_AUTHOR("Ron Mercer <ron.mercer@qlogic.com>");
MODULE_DESCRIPTION(DRV_STRING " ");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

static const u32 default_msg =
    NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK |
/* NETIF_MSG_TIMER |	*/
    NETIF_MSG_IFDOWN |
    NETIF_MSG_IFUP |
    NETIF_MSG_RX_ERR |
    NETIF_MSG_TX_ERR |
/*  NETIF_MSG_TX_QUEUED | */
/*  NETIF_MSG_INTR | NETIF_MSG_TX_DONE | NETIF_MSG_RX_STATUS | */
/* NETIF_MSG_PKTDATA | */
    NETIF_MSG_HW | NETIF_MSG_WOL | 0;

static int debug = -1;	/* defaults above */
module_param(debug, int, 0664);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");

#define MSIX_IRQ 0
#define MSI_IRQ 1
#define LEG_IRQ 2
static int qlge_irq_type = MSIX_IRQ;
module_param(qlge_irq_type, int, 0664);
MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");

static int qlge_mpi_coredump;
module_param(qlge_mpi_coredump, int, 0);
MODULE_PARM_DESC(qlge_mpi_coredump,
		"Option to enable MPI firmware dump. "
		"Default is OFF - Do Not allocate memory. ");

static int qlge_force_coredump;
module_param(qlge_force_coredump, int, 0);
MODULE_PARM_DESC(qlge_force_coredump,
		"Option to allow force of firmware core dump. "
		"Default is OFF - Do not allow.");

static const struct pci_device_id qlge_pci_tbl[] = {
	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)},
	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)},
	/* required last entry */
	{0,}
};

MODULE_DEVICE_TABLE(pci, qlge_pci_tbl);

static int ql_wol(struct ql_adapter *);
static void qlge_set_multicast_list(struct net_device *);
static int ql_adapter_down(struct ql_adapter *);
static int ql_adapter_up(struct ql_adapter *);

/* This hardware semaphore causes exclusive access to
 * resources shared between the NIC driver, MPI firmware,
 * FCOE firmware and the FC driver.
 */
static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask)
{
	u32 sem_bits = 0;

	switch (sem_mask) {
	case SEM_XGMAC0_MASK:
		sem_bits = SEM_SET << SEM_XGMAC0_SHIFT;
		break;
	case SEM_XGMAC1_MASK:
		sem_bits = SEM_SET << SEM_XGMAC1_SHIFT;
		break;
	case SEM_ICB_MASK:
		sem_bits = SEM_SET << SEM_ICB_SHIFT;
		break;
	case SEM_MAC_ADDR_MASK:
		sem_bits = SEM_SET << SEM_MAC_ADDR_SHIFT;
		break;
	case SEM_FLASH_MASK:
		sem_bits = SEM_SET << SEM_FLASH_SHIFT;
		break;
	case SEM_PROBE_MASK:
		sem_bits = SEM_SET << SEM_PROBE_SHIFT;
		break;
	case SEM_RT_IDX_MASK:
		sem_bits = SEM_SET << SEM_RT_IDX_SHIFT;
		break;
	case SEM_PROC_REG_MASK:
		sem_bits = SEM_SET << SEM_PROC_REG_SHIFT;
		break;
	default:
		netif_alert(qdev, probe, qdev->ndev, "bad Semaphore mask!.\n");
		return -EINVAL;
	}

	ql_write32(qdev, SEM, sem_bits | sem_mask);
	return !(ql_read32(qdev, SEM) & sem_bits);
}

int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask)
{
	unsigned int wait_count = 30;
	do {
		if (!ql_sem_trylock(qdev, sem_mask))
			return 0;
		udelay(100);
	} while (--wait_count);
	return -ETIMEDOUT;
}

void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask)
{
	ql_write32(qdev, SEM, sem_mask);
	ql_read32(qdev, SEM);	/* flush */
}

/* This function waits for a specific bit to come ready
 * in a given register.  It is used mostly by the initialize
 * process, but is also used in kernel thread API such as
 * netdev->set_multi, netdev->set_mac_address, netdev->vlan_rx_add_vid.
 */
int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit)
{
	u32 temp;
	int count = UDELAY_COUNT;

	while (count) {
		temp = ql_read32(qdev, reg);

		/* check for errors */
		if (temp & err_bit) {
			netif_alert(qdev, probe, qdev->ndev,
				    "register 0x%.08x access error, value = 0x%.08x!.\n",
				    reg, temp);
			return -EIO;
		} else if (temp & bit)
			return 0;
		udelay(UDELAY_DELAY);
		count--;
	}
	netif_alert(qdev, probe, qdev->ndev,
		    "Timed out waiting for reg %x to come ready.\n", reg);
	return -ETIMEDOUT;
}

/* The CFG register is used to download TX and RX control blocks
 * to the chip. This function waits for an operation to complete.
 */
static int ql_wait_cfg(struct ql_adapter *qdev, u32 bit)
{
	int count = UDELAY_COUNT;
	u32 temp;

	while (count) {
		temp = ql_read32(qdev, CFG);
		if (temp & CFG_LE)
			return -EIO;
		if (!(temp & bit))
			return 0;
		udelay(UDELAY_DELAY);
		count--;
	}
	return -ETIMEDOUT;
}


/* Used to issue init control blocks to hw. Maps control block,
 * sets address, triggers download, waits for completion.
 */
int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
		 u16 q_id)
{
	u64 map;
	int status = 0;
	int direction;
	u32 mask;
	u32 value;

	direction =
	    (bit & (CFG_LRQ | CFG_LR | CFG_LCQ)) ? PCI_DMA_TODEVICE :
	    PCI_DMA_FROMDEVICE;

	map = pci_map_single(qdev->pdev, ptr, size, direction);
	if (pci_dma_mapping_error(qdev->pdev, map)) {
		netif_err(qdev, ifup, qdev->ndev, "Couldn't map DMA area.\n");
		return -ENOMEM;
	}

	status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
	if (status)
		return status;

	status = ql_wait_cfg(qdev, bit);
	if (status) {
		netif_err(qdev, ifup, qdev->ndev,
			  "Timed out waiting for CFG to come ready.\n");
		goto exit;
	}

	ql_write32(qdev, ICB_L, (u32) map);
	ql_write32(qdev, ICB_H, (u32) (map >> 32));

	mask = CFG_Q_MASK | (bit << 16);
	value = bit | (q_id << CFG_Q_SHIFT);
	ql_write32(qdev, CFG, (mask | value));

	/*
	 * Wait for the bit to clear after signaling hw.
	 */
	status = ql_wait_cfg(qdev, bit);
exit:
	ql_sem_unlock(qdev, SEM_ICB_MASK);	/* does flush too */
	pci_unmap_single(qdev->pdev, map, size, direction);
	return status;
}

/* Get a specific MAC address from the CAM.  Used for debug and reg dump. */
int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
			u32 *value)
{
	u32 offset = 0;
	int status;

	switch (type) {
	case MAC_ADDR_TYPE_MULTI_MAC:
	case MAC_ADDR_TYPE_CAM_MAC:
		{
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
				   (index << MAC_ADDR_IDX_SHIFT) | /* index */
				   MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MR, 0);
			if (status)
				goto exit;
			*value++ = ql_read32(qdev, MAC_ADDR_DATA);
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
				   (index << MAC_ADDR_IDX_SHIFT) | /* index */
				   MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MR, 0);
			if (status)
				goto exit;
			*value++ = ql_read32(qdev, MAC_ADDR_DATA);
			if (type == MAC_ADDR_TYPE_CAM_MAC) {
				status =
				    ql_wait_reg_rdy(qdev,
					MAC_ADDR_IDX, MAC_ADDR_MW, 0);
				if (status)
					goto exit;
				ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
					   (index << MAC_ADDR_IDX_SHIFT) | /* index */
					   MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
				status =
				    ql_wait_reg_rdy(qdev, MAC_ADDR_IDX,
						    MAC_ADDR_MR, 0);
				if (status)
					goto exit;
				*value++ = ql_read32(qdev, MAC_ADDR_DATA);
			}
			break;
		}
	case MAC_ADDR_TYPE_VLAN:
	case MAC_ADDR_TYPE_MULTI_FLTR:
	default:
		netif_crit(qdev, ifup, qdev->ndev,
			   "Address type %d not yet supported.\n", type);
		status = -EPERM;
	}
exit:
	return status;
}

/* Set up a MAC, multicast or VLAN address for the
 * inbound frame matching.
 */
static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
			       u16 index)
{
	u32 offset = 0;
	int status = 0;

	switch (type) {
	case MAC_ADDR_TYPE_MULTI_MAC:
		{
			u32 upper = (addr[0] << 8) | addr[1];
			u32 lower = (addr[2] << 24) | (addr[3] << 16) |
					(addr[4] << 8) | (addr[5]);

			status =
				ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) |
				(index << MAC_ADDR_IDX_SHIFT) |
				type | MAC_ADDR_E);
			ql_write32(qdev, MAC_ADDR_DATA, lower);
			status =
				ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) |
				(index << MAC_ADDR_IDX_SHIFT) |
				type | MAC_ADDR_E);

			ql_write32(qdev, MAC_ADDR_DATA, upper);
			status =
				ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			break;
		}
	case MAC_ADDR_TYPE_CAM_MAC:
		{
			u32 cam_output;
			u32 upper = (addr[0] << 8) | addr[1];
			u32 lower =
			    (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
			    (addr[5]);
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
				   (index << MAC_ADDR_IDX_SHIFT) | /* index */
				   type);	/* type */
			ql_write32(qdev, MAC_ADDR_DATA, lower);
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
				   (index << MAC_ADDR_IDX_SHIFT) | /* index */
				   type);	/* type */
			ql_write32(qdev, MAC_ADDR_DATA, upper);
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, (offset) |	/* offset */
				   (index << MAC_ADDR_IDX_SHIFT) |	/* index */
				   type);	/* type */
			/* This field should also include the queue id
			   and possibly the function id.  Right now we hardcode
			   the route field to NIC core.
			 */
			cam_output = (CAM_OUT_ROUTE_NIC |
				      (qdev->
				       func << CAM_OUT_FUNC_SHIFT) |
					(0 << CAM_OUT_CQ_ID_SHIFT));
			if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
				cam_output |= CAM_OUT_RV;
			/* route to NIC core */
			ql_write32(qdev, MAC_ADDR_DATA, cam_output);
			break;
		}
	case MAC_ADDR_TYPE_VLAN:
		{
			u32 enable_bit = *((u32 *) &addr[0]);
			/* For VLAN, the addr actually holds a bit that
			 * either enables or disables the vlan id we are
			 * addressing. It's either MAC_ADDR_E on or off.
			 * That's bit-27 we're talking about.
			 */
			status =
			    ql_wait_reg_rdy(qdev,
				MAC_ADDR_IDX, MAC_ADDR_MW, 0);
			if (status)
				goto exit;
			ql_write32(qdev, MAC_ADDR_IDX, offset |	/* offset */
				   (index << MAC_ADDR_IDX_SHIFT) |	/* index */
				   type |	/* type */
				   enable_bit);	/* enable/disable */
			break;
		}
	case MAC_ADDR_TYPE_MULTI_FLTR:
	default:
		netif_crit(qdev, ifup, qdev->ndev,
			   "Address type %d not yet supported.\n", type);
		status = -EPERM;
	}
exit:
	return status;
}

/* Set or clear MAC address in hardware. We sometimes
 * have to clear it to prevent wrong frame routing
 * especially in a bonding environment.
 */
static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
{
	int status;
	char zero_mac_addr[ETH_ALEN];
	char *addr;

	if (set) {
		addr = &qdev->current_mac_addr[0];
		netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
			     "Set Mac addr %pM\n", addr);
	} else {
		eth_zero_addr(zero_mac_addr);
		addr = &zero_mac_addr[0];
		netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
			     "Clearing MAC address\n");
	}
	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
	if (status)
		return status;
	status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
			MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
	if (status)
		netif_err(qdev, ifup, qdev->ndev,
			  "Failed to init mac address.\n");
	return status;
}

void ql_link_on(struct ql_adapter *qdev)
{
	netif_err(qdev, link, qdev->ndev, "Link is up.\n");
	netif_carrier_on(qdev->ndev);
	ql_set_mac_addr(qdev, 1);
}

void ql_link_off(struct ql_adapter *qdev)
{
	netif_err(qdev, link, qdev->ndev, "Link is down.\n");
	netif_carrier_off(qdev->ndev);
	ql_set_mac_addr(qdev, 0);
}

/* Get a specific frame routing value from the CAM.
 * Used for debug and reg dump.
 */
int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value)
{
	int status = 0;

	status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0);
	if (status)
		goto exit;

	ql_write32(qdev, RT_IDX,
		   RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT));
	status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, 0);
	if (status)
		goto exit;
	*value = ql_read32(qdev, RT_DATA);
exit:
	return status;
}

/* The NIC function for this chip has 16 routing indexes.  Each one can be used
 * to route different frame types to various inbound queues.  We send broadcast/
 * multicast/error frames to the default queue for slow handling,
 * and CAM hit/RSS frames to the fast handling queues.
 */
static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask,
			      int enable)
{
	int status = -EINVAL; /* Return error if no mask match. */
	u32 value = 0;

	switch (mask) {
	case RT_IDX_CAM_HIT:
		{
			value = RT_IDX_DST_CAM_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_CAM_HIT_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_VALID:	/* Promiscuous Mode frames. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_PROMISCUOUS_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_ERR:	/* Pass up MAC,IP,TCP/UDP error frames. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_ALL_ERR_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_IP_CSUM_ERR: /* Pass up IP CSUM error frames. */
		{
			value = RT_IDX_DST_DFLT_Q | /* dest */
				RT_IDX_TYPE_NICQ | /* type */
				(RT_IDX_IP_CSUM_ERR_SLOT <<
				RT_IDX_IDX_SHIFT); /* index */
			break;
		}
	case RT_IDX_TU_CSUM_ERR: /* Pass up TCP/UDP CSUM error frames. */
		{
			value = RT_IDX_DST_DFLT_Q | /* dest */
				RT_IDX_TYPE_NICQ | /* type */
				(RT_IDX_TCP_UDP_CSUM_ERR_SLOT <<
				RT_IDX_IDX_SHIFT); /* index */
			break;
		}
	case RT_IDX_BCAST:	/* Pass up Broadcast frames to default Q. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_BCAST_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_MCAST:	/* Pass up All Multicast frames. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_MCAST_MATCH:	/* Pass up matched Multicast frames. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case RT_IDX_RSS_MATCH:	/* Pass up matched RSS frames. */
		{
			value = RT_IDX_DST_RSS |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (RT_IDX_RSS_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	case 0:		/* Clear the E-bit on an entry. */
		{
			value = RT_IDX_DST_DFLT_Q |	/* dest */
			    RT_IDX_TYPE_NICQ |	/* type */
			    (index << RT_IDX_IDX_SHIFT);/* index */
			break;
		}
	default:
		netif_err(qdev, ifup, qdev->ndev,
			  "Mask type %d not yet supported.\n", mask);
		status = -EPERM;
		goto exit;
	}

	if (value) {
		status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0);
		if (status)
			goto exit;
		value |= (enable ? RT_IDX_E : 0);
		ql_write32(qdev, RT_IDX, value);
		ql_write32(qdev, RT_DATA, enable ? mask : 0);
	}
exit:
	return status;
}

static void ql_enable_interrupts(struct ql_adapter *qdev)
{
	ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16) | INTR_EN_EI);
}

static void ql_disable_interrupts(struct ql_adapter *qdev)
{
	ql_write32(qdev, INTR_EN, (INTR_EN_EI << 16));
}

/* If we're running with multiple MSI-X vectors then we enable on the fly.
 * Otherwise, we may have multiple outstanding workers and don't want to
 * enable until the last one finishes. In this case, the irq_cnt gets
 * incremented every time we queue a worker and decremented every time
 * a worker finishes.  Once it hits zero we enable the interrupt.
 */
u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
	u32 var = 0;
	unsigned long hw_flags = 0;
	struct intr_context *ctx = qdev->intr_context + intr;

	if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) {
		/* Always enable if we're MSIX multi interrupts and
		 * it's not the default (zeroeth) interrupt.
		 */
		ql_write32(qdev, INTR_EN,
			   ctx->intr_en_mask);
		var = ql_read32(qdev, STS);
		return var;
	}

	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
	if (atomic_dec_and_test(&ctx->irq_cnt)) {
		ql_write32(qdev, INTR_EN,
			   ctx->intr_en_mask);
		var = ql_read32(qdev, STS);
	}
	spin_unlock_irqrestore(&qdev->hw_lock,