he pandaboard.
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/pci/pci-sysfs.c
blob: 7bcf12adced7249674ec931ea034066fb6ef3d64 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                           
                         
                        



                           
                     
                             
                           
                           
                       






                                                                         
                                                                                                         













                                                                         












                                                                        
                          
 





                                             

 

                                                                 
                
                                   

                
                  

                                                                            
     
                                                       
      
                                                        








                                                                 
                                   

                
                  

                                                                            
     
                                                       
      
                                                        


                          

 

































                                                                      

                    
                                                                             



                                                   
                
                                   


                                            

                                           

                                   





                                                                     



                           
                                                                                          








                                                                             



                                                                               

                                               




                                                      


                                                                        
                              
 
                   
                                         


                                                 
              
                                                 
 






                                                                        
 

                                                                     

 







                                                                            
              














                                                                                















                                                                                



                                             



                                                              
                              
 

                                                                                


                               



                                                                            
 

                                                                               



                     
 























                                                                      
 

















                                                                   














                                                                



                                             








                                                                         


















                                                                       

      








                                           
                                 
                            


                             

                                            
                                                                

                                                                      
                                                           

                                                              
                                                                  
      


                    



                                                                      

                                                                             


                    
              










                                                                           

                                                        
                                                    



                                                                                
                             

                                                                         
                                                                                













                                                              

                                
                                                          
                                           
                      




                                    
                                                          



                                                             


                          
                        
                                                           



                                                              



                          

                        
                                                          







                                                             
                                                          
                                           







                       

                                                         
                                                     



                                                                                
                             






                                           

                                
                                                                           
                      
                       
         



                                                           
                                                          


                          

                          



                                                            
                                                           


                          



                                                           
                                                          


                          
 
                   
                                                                           






                       
              

                                                      
                                                  


                                                                    




                                              
 
                                                  


              

                                                       
                                                   


                                                                    




                                              
 
                                                   

 


                                                               
                         
                                                    
                                                






                                                                           
              

                                                           
                                                       

                                                           
                                                                    










                                                               
                         
                                                    
                                                






                                                                            
              

                                                            
                                                        

                                                           
                                                                    









                                                                     
                         



                                                      
                                                                          


                                                                        
          

                                                            


                                                           
                                                                    

                                                             




                                                                  
                         








                                                                         

                                                           









                                                                    












                                                                        






                                                                         
                                                               










                                                                
                                          





                                                    
                                               





                                                              
                                           



                                                     
                                                























                                                                             



                            
 

                                                                              
 
                                                 
 

                                               

                                                         
                                                                       
                                                   


                                                                          
                         


                 




                                                                
                                              

                                                                             


                                                                   
                                                                


                                                                             
                                             
                                      
                                   
              
 





                                              




                                                                                       

                                                         
                               
         
 





                                                                            

                                                                             


                                                                     



                                                                        

                                                             





                                                     

                                                             


                                                     

 































































                                                                             
   
                                                     
                        
  
                                                                     














                                                                         





                                                                         


         










                                                                            
                                              








                                                                     



                                                                    










                                                                          
   
                                                                      
                         
  
                                                                          
   
                                                          

              
                   


                                                                




                                               







                                                                             

                 
                 

                          

                                                                       



                                                               
                    
                              
                                                






                                       

                                                      
                                                  












                                                                                   
                    
                              
                                                







                                                                      

                                                     
                                                 








                                                                                   

                            

















                                                     
          
                                   







                                                
          
                                       



                                  
                                                                            
 
                 

 












                                                                          





                                          



                                                                                   










                                                               
                                          


                                                    

                                             

                                                                     
                                    







                                              





                                                                    
                 








                                                                      

 
                                                                  
 
                   

                                   
 


                               
                                                    
                                                                                  
            


                                                                                   
 

                                                 





                                                                                

                                                                 
                       
                                                          
                            
                                         
                                                
                 
                                          

                                        
                                                    







                                                                      
         
 





                                                                   
                                              

                                                    
                                  
 


                                                        
                                  
 

                                              
                 
 


                                                          
             
                       
                                                                       


                                      

                                        
                
                                                    




                                                                          

 







                                                                      



                                                           

 







                                                                

                         


                               
                                            
 
                                                    





                                                                          







                                                                                
         


                                              




                                      

                   
                              

                                                          

                                          
                                      
                 
         



                 
                              
/*
 * drivers/pci/pci-sysfs.c
 *
 * (C) Copyright 2002-2004 Greg Kroah-Hartman <greg@kroah.com>
 * (C) Copyright 2002-2004 IBM Corp.
 * (C) Copyright 2003 Matthew Wilcox
 * (C) Copyright 2003 Hewlett-Packard
 * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
 * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
 *
 * File attributes for PCI devices
 *
 * Modeled after usb's driverfs.c 
 *
 */


#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/topology.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/capability.h>
#include <linux/security.h>
#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include "pci.h"

static int sysfs_initialized;	/* = 0 */

/* show configuration fields */
#define pci_config_attr(field, format_string)				\
static ssize_t								\
field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\
{									\
	struct pci_dev *pdev;						\
									\
	pdev = to_pci_dev (dev);					\
	return sprintf (buf, format_string, pdev->field);		\
}

pci_config_attr(vendor, "0x%04x\n");
pci_config_attr(device, "0x%04x\n");
pci_config_attr(subsystem_vendor, "0x%04x\n");
pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");

static ssize_t broken_parity_status_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	return sprintf (buf, "%u\n", pdev->broken_parity_status);
}

static ssize_t broken_parity_status_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	unsigned long val;

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	pdev->broken_parity_status = !!val;

	return count;
}

static ssize_t local_cpus_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{		
	const struct cpumask *mask;
	int len;

#ifdef CONFIG_NUMA
	mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
					  cpumask_of_node(dev_to_node(dev));
#else
	mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
#endif
	len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
	buf[len++] = '\n';
	buf[len] = '\0';
	return len;
}


static ssize_t local_cpulist_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	const struct cpumask *mask;
	int len;

#ifdef CONFIG_NUMA
	mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
					  cpumask_of_node(dev_to_node(dev));
#else
	mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
#endif
	len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
	buf[len++] = '\n';
	buf[len] = '\0';
	return len;
}

/*
 * PCI Bus Class Devices
 */
static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
					int type,
					struct device_attribute *attr,
					char *buf)
{
	int ret;
	const struct cpumask *cpumask;

	cpumask = cpumask_of_pcibus(to_pci_bus(dev));
	ret = type ?
		cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask) :
		cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
	buf[ret++] = '\n';
	buf[ret] = '\0';
	return ret;
}

static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
}

static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
}

/* show resources */
static ssize_t
resource_show(struct device * dev, struct device_attribute *attr, char * buf)
{
	struct pci_dev * pci_dev = to_pci_dev(dev);
	char * str = buf;
	int i;
	int max;
	resource_size_t start, end;

	if (pci_dev->subordinate)
		max = DEVICE_COUNT_RESOURCE;
	else
		max = PCI_BRIDGE_RESOURCES;

	for (i = 0; i < max; i++) {
		struct resource *res =  &pci_dev->resource[i];
		pci_resource_to_user(pci_dev, i, res, &start, &end);
		str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
			       (unsigned long long)start,
			       (unsigned long long)end,
			       (unsigned long long)res->flags);
	}
	return (str - buf);
}

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct pci_dev *pci_dev = to_pci_dev(dev);

	return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
		       pci_dev->vendor, pci_dev->device,
		       pci_dev->subsystem_vendor, pci_dev->subsystem_device,
		       (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
		       (u8)(pci_dev->class));
}

static ssize_t is_enabled_store(struct device *dev,
				struct device_attribute *attr, const char *buf,
				size_t count)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	unsigned long val;
	ssize_t result = strict_strtoul(buf, 0, &val);

	if (result < 0)
		return result;

	/* this can crash the machine when done on the "wrong" device */
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (!val) {
		if (pci_is_enabled(pdev))
			pci_disable_device(pdev);
		else
			result = -EIO;
	} else
		result = pci_enable_device(pdev);

	return result < 0 ? result : count;
}

static ssize_t is_enabled_show(struct device *dev,
			       struct device_attribute *attr, char *buf)
{
	struct pci_dev *pdev;

	pdev = to_pci_dev (dev);
	return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
}

#ifdef CONFIG_NUMA
static ssize_t
numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	return sprintf (buf, "%d\n", dev->numa_node);
}
#endif

static ssize_t
dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct pci_dev *pdev = to_pci_dev(dev);

	return sprintf (buf, "%d\n", fls64(pdev->dma_mask));
}

static ssize_t
consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr,
				 char *buf)
{
	return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask));
}

static ssize_t
msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct pci_dev *pdev = to_pci_dev(dev);

	if (!pdev->subordinate)
		return 0;

	return sprintf (buf, "%u\n",
			!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
}

static ssize_t
msi_bus_store(struct device *dev, struct device_attribute *attr,
	      const char *buf, size_t count)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	unsigned long val;

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	/* bad things may happen if the no_msi flag is changed
	 * while some drivers are loaded */
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	/* Maybe pci devices without subordinate busses shouldn't even have this
	 * attribute in the first place?  */
	if (!pdev->subordinate)
		return count;

	/* Is the flag going to change, or keep the value it already had? */
	if (!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) ^
	    !!val) {
		pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI;

		dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI,"
			 " bad things could happen\n", val ? "" : " not");
	}

	return count;
}

#ifdef CONFIG_HOTPLUG
static DEFINE_MUTEX(pci_remove_rescan_mutex);
static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
				size_t count)
{
	unsigned long val;
	struct pci_bus *b = NULL;

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	if (val) {
		mutex_lock(&pci_remove_rescan_mutex);
		while ((b = pci_find_next_bus(b)) != NULL)
			pci_rescan_bus(b);
		mutex_unlock(&pci_remove_rescan_mutex);
	}
	return count;
}

struct bus_attribute pci_bus_attrs[] = {
	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
	__ATTR_NULL
};

static ssize_t
dev_rescan_store(struct device *dev, struct device_attribute *attr,
		 const char *buf, size_t count)
{
	unsigned long val;
	struct pci_dev *pdev = to_pci_dev(dev);

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	if (val) {
		mutex_lock(&pci_remove_rescan_mutex);
		pci_rescan_bus(pdev->bus);
		mutex_unlock(&pci_remove_rescan_mutex);
	}
	return count;
}

static void remove_callback(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);

	mutex_lock(&pci_remove_rescan_mutex);
	pci_remove_bus_device(pdev);
	mutex_unlock(&pci_remove_rescan_mutex);
}

static ssize_t
remove_store(struct device *dev, struct device_attribute *dummy,
	     const char *buf, size_t count)
{
	int ret = 0;
	unsigned long val;

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	/* An attribute cannot be unregistered by one of its own methods,
	 * so we have to use this roundabout approach.
	 */
	if (val)
		ret = device_schedule_callback(dev, remove_callback);
	if (ret)
		count = ret;
	return count;
}

static ssize_t
dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
		 const char *buf, size_t count)
{
	unsigned long val;
	struct pci_bus *bus = to_pci_bus(dev);

	if (strict_strtoul(buf, 0, &val) < 0)
		return -EINVAL;

	if (val) {
		mutex_lock(&pci_remove_rescan_mutex);
		pci_rescan_bus(bus);
		mutex_unlock(&pci_remove_rescan_mutex);
	}
	return count;
}

#endif

struct device_attribute pci_dev_attrs[] = {
	__ATTR_RO(resource),
	__ATTR_RO(vendor),
	__ATTR_RO(device),
	__ATTR_RO(subsystem_vendor),
	__ATTR_RO(subsystem_device),
	__ATTR_RO(class),
	__ATTR_RO(irq),
	__ATTR_RO(local_cpus),
	__ATTR_RO(local_cpulist),
	__ATTR_RO(modalias),
#ifdef CONFIG_NUMA
	__ATTR_RO(numa_node),
#endif
	__ATTR_RO(dma_mask_bits),
	__ATTR_RO(consistent_dma_mask_bits),
	__ATTR(enable, 0600, is_enabled_show, is_enabled_store),
	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
		broken_parity_status_show,broken_parity_status_store),
	__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
#ifdef CONFIG_HOTPLUG
	__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
#endif
	__ATTR_NULL,
};

struct device_attribute pcibus_dev_attrs[] = {
#ifdef CONFIG_HOTPLUG
	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
#endif
	__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
	__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
	__ATTR_NULL,
};

static ssize_t
boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct pci_dev *pdev = to_pci_dev(dev);

	return sprintf(buf, "%u\n",
		!!(pdev->resource[PCI_ROM_RESOURCE].flags &
		   IORESOURCE_ROM_SHADOW));
}
struct device_attribute vga_attr = __ATTR_RO(boot_vga);

static ssize_t
pci_read_config(struct file *filp, struct kobject *kobj,
		struct bin_attribute *bin_attr,