LinCAN PCI cards support updated to support PCI devices reference counting.
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Sat, 1 Oct 2011 15:38:33 +0000 (17:38 +0200)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Sat, 1 Oct 2011 15:38:33 +0000 (17:38 +0200)
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
13 files changed:
lincan/include/can_sysdep.h
lincan/include/main.h
lincan/src/adlink7841.c
lincan/src/ems_cpcpci.c
lincan/src/esdpci200.c
lincan/src/esdpci266.c
lincan/src/finish.c
lincan/src/ipci165.c
lincan/src/kv_pcican.c
lincan/src/nsi_canpci.c
lincan/src/pcan_pci.c
lincan/src/sysdep_lnx.c
lincan/src/unican.c

index 7248249..a2a8218 100644 (file)
   #endif
 #endif
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+  #define can_pci_dev_get(_M_pdev) (_M_pdev)
+  #define can_pci_dev_put(_M_pdev) do {} while(0)
+  #define can_pci_get_device pci_find_device
+  #define can_pci_get_subsys pci_find_subsys
+#else /* > 2.6.0 */
+  #define can_pci_dev_get pci_dev_get
+  #define can_pci_dev_put pci_dev_put
+  #define can_pci_get_device pci_get_device
+  #define can_pci_get_subsys pci_get_subsys
+#endif
+
 #ifndef CAN_WITH_RTL
 /* Standard LINUX kernel */
 
index e896e27..5b4e0e0 100644 (file)
@@ -321,6 +321,7 @@ struct hwspecops_t {
        int (*release_io)(struct candevice_t *candev);
        int (*reset)(struct candevice_t *candev);
        int (*init_hw_data)(struct candevice_t *candev);
+       void (*done_hw_data)(struct candevice_t *candev);
        int (*init_chip_data)(struct candevice_t *candev, int chipnr);
        int (*init_obj_data)(struct canchip_t *chip, int objnr);
        int (*program_irq)(struct candevice_t *candev);
@@ -504,6 +505,12 @@ void can_release_io_region(unsigned long start, unsigned long n);
 int can_request_mem_region(unsigned long start, unsigned long n, const char *name);
 void can_release_mem_region(unsigned long start, unsigned long n);
 
+#ifdef CAN_ENABLE_PCI_SUPPORT
+struct pci_dev *can_pci_get_next_untaken_device(unsigned int vendor, unsigned int device);
+struct pci_dev *can_pci_get_next_untaken_subsyst(unsigned int vendor, unsigned int device,
+                       unsigned int ss_vendor, unsigned int ss_device);
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
 struct boardtype_t {
        const char *boardtype;
        int (*board_register)(struct hwspecops_t *hwspecops);
index 18266b8..5385332 100644 (file)
@@ -176,16 +176,16 @@ int adlink7841_reset(struct candevice_t *candev)
 
 int adlink7841_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
        int i;
 
-       do {
-               pcidev = pci_find_device(ADLINK7841_PCI_VENDOR_ID, ADLINK7841_PCI_PRODUCT_ID, pcidev);
-               if(pcidev == NULL) return -ENODEV;
-       } while(can_check_dev_taken(pcidev));
+       pcidev = can_pci_get_next_untaken_device(ADLINK7841_PCI_VENDOR_ID, ADLINK7841_PCI_PRODUCT_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
        
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of ADLINK7841 failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -193,6 +193,7 @@ int adlink7841_init_hw_data(struct candevice_t *candev)
        for(i=1;i<3;i++){
                if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
                        printk(KERN_CRIT "ADLINK7841 region %d is not IO\n",i);
+                       can_pci_dev_put(pcidev);
                        return -EIO;
                }
        }
@@ -209,6 +210,12 @@ int adlink7841_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void adlink7841_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int adlink7841_init_chip_data(struct candevice_t *candev, int chipnr)
 {
 
@@ -250,6 +257,7 @@ int adlink7841_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = adlink7841_release_io;
        hwspecops->reset = adlink7841_reset;
        hwspecops->init_hw_data = adlink7841_init_hw_data;
+       hwspecops->done_hw_data = adlink7841_done_hw_data;
        hwspecops->init_chip_data = adlink7841_init_chip_data;
        hwspecops->init_obj_data = adlink7841_init_obj_data;
        hwspecops->write_register = adlink7841_write_register;
index ffd1418..55c4d98 100644 (file)
@@ -287,15 +287,17 @@ int ems_cpcpci_reset(struct candevice_t *candev)
 
 int ems_cpcpci_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
        int i;
        unsigned long l;
 
-       pcidev = pci_find_device(EMS_CPCPCI_PCICAN_VENDOR, EMS_CPCPCI_PCICAN_ID, pcidev);
-       if(pcidev == NULL) return -ENODEV;
+       pcidev = can_pci_get_next_untaken_device(EMS_CPCPCI_PCICAN_VENDOR, EMS_CPCPCI_PCICAN_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
        
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of EMS_CPCPCI failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -303,13 +305,16 @@ int ems_cpcpci_init_hw_data(struct candevice_t *candev)
        for(i=0;i<2;i++){
                if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
                        printk(KERN_CRIT "EMS_CPCPCI region %d is not memory\n",i);
+                       can_pci_dev_put(pcidev);
                        return -EIO;
                }
        }
 
        /*request IO access temporarily to check card presence*/
-       if(ems_cpcpci_request_io(candev)<0)
+       if(ems_cpcpci_request_io(candev)<0) {
+               can_pci_dev_put(pcidev);
                return -ENODEV;
+       }
 
        /*** candev->aux_base_addr=pci_resource_start(pcidev,0); ***/
        /* some control registers */
@@ -340,10 +345,16 @@ int ems_cpcpci_init_hw_data(struct candevice_t *candev)
        candev->nr_all_chips=2;
 
        ems_cpcpci_release_io(candev);
-        
+
        return 0;
 }
 
+void ems_cpcpci_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int ems_cpcpci_init_chip_data(struct candevice_t *candev, int chipnr)
 {
        if(candev->sysdevptr.pcidev==NULL)
@@ -390,6 +401,7 @@ int ems_cpcpci_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = ems_cpcpci_release_io;
        hwspecops->reset = ems_cpcpci_reset;
        hwspecops->init_hw_data = ems_cpcpci_init_hw_data;
+       hwspecops->done_hw_data = ems_cpcpci_done_hw_data;
        hwspecops->init_chip_data = ems_cpcpci_init_chip_data;
        hwspecops->init_obj_data = ems_cpcpci_init_obj_data;
        hwspecops->write_register = ems_cpcpci_write_register;
index 718db1e..292ae90 100644 (file)
@@ -290,15 +290,15 @@ int esdpci200_reset(struct candevice_t *candev)
 
 int esdpci200_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
+
+       pcidev = can_pci_get_next_untaken_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
 
-       do {
-               pcidev = pci_find_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID, pcidev);
-               if(pcidev == NULL) return -ENODEV;
-       } while(can_check_dev_taken(pcidev));
-       
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of ESDPCI200 failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -308,17 +308,20 @@ int esdpci200_init_hw_data(struct candevice_t *candev)
        if(!(pci_resource_flags(pcidev, 0)&IORESOURCE_MEM))
        {
           printk(KERN_CRIT "PCI200 region %d is not MEM\n",0);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
        if(!(pci_resource_flags(pcidev, 1)&IORESOURCE_IO))
        {
           printk(KERN_CRIT "PCI200 region %d is not IO\n",1);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
 
        if(!(pci_resource_flags(pcidev,2)&IORESOURCE_MEM))
        {
           printk(KERN_CRIT "PCI200 region %d is not MEM\n",2);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
 
@@ -339,6 +342,12 @@ int esdpci200_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void esdpci200_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
 {
 
@@ -389,6 +398,7 @@ int esdpci200_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = esdpci200_release_io;
        hwspecops->reset = esdpci200_reset;
        hwspecops->init_hw_data = esdpci200_init_hw_data;
+       hwspecops->done_hw_data = esdpci200_done_hw_data;
        hwspecops->init_chip_data = esdpci200_init_chip_data;
        hwspecops->init_obj_data = esdpci200_init_obj_data;
        hwspecops->write_register = esdpci200_write_register;
index 770ffd8..fc043bc 100644 (file)
@@ -203,28 +203,18 @@ int esdpci266_reset(struct candevice_t *candev)
 
 int esdpci266_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
 
        printk("lincan: search for ESD PCI/PMC 266 board ...\n");
 
-       do {
-               pcidev =
-                   pci_find_device(PLX_9056_VENDOR_ID, PLX_9056_DEVICE_ID,
-                                   pcidev);
-               if (pcidev == NULL)
-                       return -ENODEV;
-               if (pcidev->subsystem_vendor != ESDPCI266_PCI_VENDOR_ID
-                   || pcidev->subsystem_device != ESDPCI266_PCI_PRODUCT_ID) {
-                       printk
-                           ("PLX9056 found, subvendor/subdevice mismatch (%04d:%04d)\n",
-                            pcidev->subsystem_vendor,
-                            pcidev->subsystem_device);
-                       continue;
-               }
-       } while (can_check_dev_taken(pcidev));
+       pcidev = can_pci_get_next_untaken_subsyst(PLX_9056_VENDOR_ID, PLX_9056_DEVICE_ID,
+                                               ESDPCI266_PCI_VENDOR_ID, ESDPCI266_PCI_PRODUCT_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
 
        if (pci_enable_device(pcidev)) {
                printk("lincan: pci_enable_device() failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
 
@@ -242,6 +232,12 @@ int esdpci266_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void esdpci266_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int esdpci266_init_chip_data(struct candevice_t *candev, int chipnr)
 {
        if (candev->sysdevptr.pcidev == NULL)
@@ -277,6 +273,7 @@ int esdpci266_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = esdpci266_release_io;
        hwspecops->reset = esdpci266_reset;
        hwspecops->init_hw_data = esdpci266_init_hw_data;
+       hwspecops->done_hw_data = esdpci266_done_hw_data;
        hwspecops->init_chip_data = esdpci266_init_chip_data;
        hwspecops->init_obj_data = esdpci266_init_obj_data;
        hwspecops->write_register = esdpci266_write_register;
index 93fb927..be30f84 100644 (file)
@@ -139,6 +139,9 @@ void candevice_done(struct candevice_t *candev)
                candev->hwspecops->release_io(candev);
                candev->flags &= ~CANDEV_IO_RESERVED;
        }
+       if(candev->hwspecops->done_hw_data != NULL)
+               candev->hwspecops->done_hw_data(candev);
+
        can_checked_free(candev->hwspecops);
        candev->hwspecops=NULL;
 }
index dcbfdad..6b90ed0 100644 (file)
@@ -1383,21 +1383,20 @@ int ipci165_reset(struct candevice_t *candev)
 int ipci165_init_hw_data(struct candevice_t *candev)
 {
   struct pci_dev *pcidev = NULL;
-  unsigned short SubsystemID;
 
   DEBUGMSG ("ipci165_init_hw_data\n");
 
   /* find iPC-I 165 on PCI bus */
   do
   {
-    pcidev = pci_find_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev);
-    if(pcidev == NULL) return -ENODEV;
+    pcidev = can_pci_get_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev);
+    if(pcidev == NULL)
+      return -ENODEV;
 
     /* check subvendor ID */
-    pci_read_config_word (pcidev, PCI_SUBSYSTEM_ID, &SubsystemID);
-    if ((SubsystemID != IPCI165_SUBSYSTEM_ID) &&
-        (SubsystemID != CP350_SUBSYSTEM_ID))
-      break;
+    if ((pcidev->subsystem_vendor != IPCI165_SUBSYSTEM_ID) &&
+        (pcidev->subsystem_vendor != CP350_SUBSYSTEM_ID))
+      continue;
   }
   while(can_check_dev_taken(pcidev));
 
@@ -1405,6 +1404,7 @@ int ipci165_init_hw_data(struct candevice_t *candev)
   if (pci_enable_device (pcidev))
   {
     CANMSG ("Cannot enable PCI device\n");
+    can_pci_dev_put(pcidev);
     return -EIO;
   }
 
@@ -1423,6 +1423,12 @@ int ipci165_init_hw_data(struct candevice_t *candev)
   return 0;
 }
 
+void ipci165_done_hw_data(struct candevice_t *candev)
+{
+  struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+  can_pci_dev_put(pcidev);
+}
+
 #define CHIP_TYPE "ipci165"
 
 /**
@@ -1547,6 +1553,7 @@ int ipci165_register(struct hwspecops_t *hwspecops)
   hwspecops->release_io = ipci165_release_io;
   hwspecops->reset = ipci165_reset;
   hwspecops->init_hw_data = ipci165_init_hw_data;
+  hwspecops->done_hw_data = ipci165_done_hw_data;
   hwspecops->init_chip_data = ipci165_init_chip_data;
   hwspecops->init_obj_data = ipci165_init_obj_data;
   hwspecops->write_register = NULL;
index 758b8fb..30ac377 100644 (file)
@@ -205,16 +205,16 @@ int kv_pcican_reset(struct candevice_t *candev)
 
 int kv_pcican_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
        int i;
 
-       do {
-               pcidev = pci_find_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID, pcidev);
-               if(pcidev == NULL) return -ENODEV;
-       } while(can_check_dev_taken(pcidev));
+       pcidev = can_pci_get_next_untaken_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
        
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of PCICAN failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -222,6 +222,7 @@ int kv_pcican_init_hw_data(struct candevice_t *candev)
        for(i=0;i<3;i++){
                if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
                        printk(KERN_CRIT "PCICAN region %d is not IO\n",i);
+                       can_pci_dev_put(pcidev);
                        return -EIO;
                }
        }
@@ -250,6 +251,12 @@ int kv_pcican_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void kv_pcican_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int kv_pcican_init_chip_data(struct candevice_t *candev, int chipnr)
 {
 
@@ -291,6 +298,7 @@ int kv_pcican_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = kv_pcican_release_io;
        hwspecops->reset = kv_pcican_reset;
        hwspecops->init_hw_data = kv_pcican_init_hw_data;
+       hwspecops->done_hw_data = kv_pcican_done_hw_data;
        hwspecops->init_chip_data = kv_pcican_init_chip_data;
        hwspecops->init_obj_data = kv_pcican_init_obj_data;
        hwspecops->write_register = kv_pcican_write_register;
index d8194be..1fee227 100644 (file)
@@ -375,43 +375,25 @@ int nsi_canpci_reset(struct candevice_t *candev)
  */
 
 int nsi_canpci_init_hw_data(struct candevice_t *candev) 
-     {
-  struct pci_dev *pcidev = NULL;
+{
+       struct pci_dev *pcidev;
 
-  /* looking for NSI CANPCI ident on the pci bus*/
-  do
-  {
-    pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID, pcidev);
-  }
-  while(can_check_dev_taken(pcidev));
-  
-  if(pcidev == NULL) 
-  {
-       do
-       {
-       pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1, pcidev);
-       }
-       while(can_check_dev_taken(pcidev));
-       if(pcidev == NULL) 
-       {
+       /* looking for NSI CANPCI ident on the pci bus*/
+       pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID);
+       if(pcidev == NULL)
+               pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1);
+       if(pcidev == NULL) {
                CANMSG ("Error : NSI CAN PCI device not found\n");
                return -ENODEV;
        }
-       else
-       {
-               CANMSG ("NSI CANPCI OPTO device found\n");
-       }
-  }
-  else
-  {
+
        CANMSG ("NSI CANPCI device found\n");  
-  }
-    
+
   /* enable it */
   if (pci_enable_device (pcidev))
   {
     CANMSG ("Cannot enable PCI device\n");
-    return -EIO;
+    goto error_io;
   }
   CANMSG ("NSI CANPCI device started\n");
   candev->sysdevptr.pcidev = pcidev;
@@ -436,30 +418,30 @@ int nsi_canpci_init_hw_data(struct candevice_t *candev)
                        pci_release_region(pcidev,0);
                        pci_release_region(pcidev,1);
                        pci_release_region(pcidev,2);                   
-                       return -EIO;
+                       goto error_io;
                        }
                }
                else
                {
                pci_release_region(pcidev,0);
                pci_release_region(pcidev,1);
-               return -EIO;
+               goto error_io;
                }
        }
        else
        {
        pci_release_region(pcidev,0);
-       return -EIO;
+       goto error_io;
        }
   }  
   else
   {
-       return -EIO;
+       goto error_io;
   }
   candev->dev_base_addr=(unsigned long)(kmalloc(sizeof(t_CardArray),GFP_ATOMIC));  
   
   if((unsigned long)candev->dev_base_addr==0)
-       return -EIO;
+       goto error_io;
   //PLX register 
   ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]=ioremap(pci_resource_start(pcidev,0),pci_resource_len(pcidev,0) );
   //PLX IO
@@ -472,8 +454,20 @@ int nsi_canpci_init_hw_data(struct candevice_t *candev)
   //Short acces to plx register
   candev->io_addr=(unsigned long)(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]);
   return 0;  
+
+error_io:
+       can_pci_dev_put(pcidev);
+       return -EIO;
 }
 
+
+void nsi_canpci_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
+
 /* The function template_init_chip_data is used to initialize the hardware
  * structure containing information about the CAN chips.
  * CHIP_TYPE represents the type of CAN chip. CHIP_TYPE can be "i82527" or
@@ -564,6 +558,7 @@ int nsi_canpci_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = nsi_canpci_release_io;
        hwspecops->reset = nsi_canpci_reset;
        hwspecops->init_hw_data = nsi_canpci_init_hw_data;
+       hwspecops->done_hw_data = nsi_canpci_done_hw_data;
        hwspecops->init_chip_data = nsi_canpci_init_chip_data;
        hwspecops->init_obj_data = nsi_canpci_init_obj_data;
        hwspecops->write_register = nsi_canpci_write_register;
index e40db7c..95ac94f 100644 (file)
@@ -270,18 +270,15 @@ int pcan_pci_init_hw_data(struct candevice_t *candev)
        int nr_chips;
        u16 subsysid;
 
-       i = 0;
-       do {
-               pcidev = pci_find_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID, pcidev);
-               if(pcidev == NULL) {
-                       printk(KERN_ERR "No unused PCAN_PCI #%d card found\n", i);
-                       return -ENODEV;
-               }
-               i++;
-       } while(can_check_dev_taken(pcidev));
+       pcidev = can_pci_get_next_untaken_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID);
+       if(pcidev == NULL) {
+               printk(KERN_ERR "No unused PCAN_PCI card found\n");
+               return -ENODEV;
+       }
 
        if (pci_enable_device (pcidev)){
                printk(KERN_ERR "Enable PCAN_PCI failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -331,9 +328,16 @@ error_ret:
 
        printk(KERN_CRIT "Setup of PCAN_PCI failed\n");
        pci_disable_device (pcidev);
+       can_pci_dev_put(pcidev);
        return -EIO;
 }
 
+void pcan_pci_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int pcan_pci_init_chip_data(struct candevice_t *candev, int chipnr)
 {
 
@@ -379,6 +383,7 @@ int pcan_pci_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = pcan_pci_release_io;
        hwspecops->reset = pcan_pci_reset;
        hwspecops->init_hw_data = pcan_pci_init_hw_data;
+       hwspecops->done_hw_data = pcan_pci_done_hw_data;
        hwspecops->init_chip_data = pcan_pci_init_chip_data;
        hwspecops->init_obj_data = pcan_pci_init_obj_data;
        hwspecops->write_register = pcan_pci_write_register;
index 2220890..1033a5f 100644 (file)
@@ -214,6 +214,37 @@ void can_release_mem_region(unsigned long start, unsigned long n)
     #endif
 }
 
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+struct pci_dev *can_pci_get_next_untaken_device(unsigned int vendor, unsigned int device)
+{
+       struct pci_dev *pcidev = NULL;
+
+       do {
+               pcidev = can_pci_get_device(vendor, device, pcidev);
+               if(pcidev == NULL)
+                       return NULL;
+       } while(can_check_dev_taken(pcidev));
+
+       return pcidev;
+}
+
+struct pci_dev *can_pci_get_next_untaken_subsyst(unsigned int vendor, unsigned int device,
+                       unsigned int ss_vendor, unsigned int ss_device)
+{
+       struct pci_dev *pcidev = NULL;
+
+       do {
+               pcidev = can_pci_get_subsys(vendor, device, ss_vendor, ss_device, pcidev);
+               if(pcidev == NULL)
+                       return NULL;
+       } while(can_check_dev_taken(pcidev));
+
+       return pcidev;
+}
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
 #ifndef CAN_WITH_RTL
 
 /**
index 2ec2aaa..10cc185 100644 (file)
@@ -970,19 +970,20 @@ int unican_pci_init_hw_data(struct candevice_t *candev)
 {
        struct pci_dev *pcidev = NULL;
 
-       do {
-               pcidev = pci_find_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID, pcidev);
-               if(pcidev == NULL) return -ENODEV;
-       } while(can_check_dev_taken(pcidev));
-       
+       pcidev = can_pci_get_next_untaken_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
+
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of Unican PCI failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
        
        if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
                printk(KERN_CRIT "Unican PCI region 0 is not MEM\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->io_addr=pci_resource_start(pcidev,0);
@@ -998,6 +999,11 @@ int unican_pci_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void unican_pci_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
 
 int unican_pci_init_chip_data(struct candevice_t *candev, int chipnr)
 {
@@ -1014,6 +1020,7 @@ int unican_pci_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = unican_pci_release_io;
        hwspecops->reset = unican_reset;
        hwspecops->init_hw_data = unican_pci_init_hw_data;
+       hwspecops->done_hw_data = unican_pci_done_hw_data;
        hwspecops->init_chip_data = unican_pci_init_chip_data;
        hwspecops->init_obj_data = unican_init_obj_data;
        hwspecops->write_register = NULL;