mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure
@ 2026-09-15 17:31 Guangshuo Li
  2026-09-16 17:30 ` kernel test robot
  2026-09-16 19:07 ` kernel test robot
  0 siblings, 2 replies; 3+ messages in thread
From: Guangshuo Li @ 2026-09-15 17:31 UTC (permalink / raw)
  To: Marc Kleine-Budde, Vincent Mailhol, Stéphane Grosjean,
	Kees Cook, Guangshuo Li, Wolfgang Grandegger, linux-can,
	linux-kernel
  Cc: stable

peak_pci_probe() initializes the PCIeC resources before registering the
SJA1000 network device.

On the probe error path, the registered channels are freed with
free_sja1000dev() before peak_pciec_remove() is called. Since chan is
part of the netdev private data, accessing chan->pciec_card after
free_sja1000dev() results in a use-after-free.

There is also a similar cleanup issue when peak_pciec_probe() succeeds
for the first channel but register_sja1000dev() subsequently fails. In
that case, the netdev is freed without releasing the PCIeC resources.

Clean up the PCIeC resources before freeing the first channel, matching
the ordering used by peak_pci_remove(), and also release them when
registration of the first channel fails.

This issue was found by manual code inspection.

Fixes: e6d9c80b7ca1 ("can: peak_pci: add support of some new PEAK-System PCI cards")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
 drivers/net/can/sja1000/peak_pci.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index 69c61ccf621d..28b94e642170 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -697,6 +697,8 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return 0;
 
 failure_free_dev:
+if (!chan->prev_dev && chan->pciec_card)
+	peak_pciec_remove(chan->pciec_card);
 	pci_set_drvdata(pdev, chan->prev_dev);
 	free_sja1000dev(dev);
 
@@ -704,20 +706,18 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* Disable interrupts */
 	writew(0x0, cfg_base + PITA_ICR + 2);
 
-	chan = NULL;
 	for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
 		priv = netdev_priv(dev);
 		chan = priv->priv;
 		prev_dev = chan->prev_dev;
 
+		/* do that only for first channel */
+		if (!prev_dev && chan->pciec_card)
+			peak_pciec_remove(chan->pciec_card);
 		unregister_sja1000dev(dev);
 		free_sja1000dev(dev);
 	}
 
-	/* free any PCIeC resources too */
-	if (chan && chan->pciec_card)
-		peak_pciec_remove(chan->pciec_card);
-
 	pci_iounmap(pdev, reg_base);
 
 failure_unmap_cfg_base:
-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure
  2026-09-15 17:31 [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure Guangshuo Li
@ 2026-09-16 17:30 ` kernel test robot
  2026-09-16 19:07 ` kernel test robot
  1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2026-09-16 17:30 UTC (permalink / raw)
  To: Guangshuo Li, Marc Kleine-Budde, Vincent Mailhol,
	Stéphane Grosjean, Kees Cook, Wolfgang Grandegger,
	linux-can, linux-kernel
  Cc: oe-kbuild-all, stable

Hi Guangshuo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkl-can-next/testing]
[also build test WARNING on linus/master v7.3-rc3 next-20260914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Guangshuo-Li/can-peak_pci-fix-PCIeC-cleanup-on-probe-failure/20260916-013157
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git testing
patch link:    https://lore.kernel.org/r/20260915173157.2510375-1-lgs201920130244%40gmail.com
patch subject: [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure
config: sparc64-randconfig-1000-20260916 (https://download.01.org/0day-ci/archive/20260917/202609170102.yZBQuFMY-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260917/202609170102.yZBQuFMY-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609170102.yZBQuFMY-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/net/can/sja1000/peak_pci.c: In function 'peak_pci_probe':
>> drivers/net/can/sja1000/peak_pci.c:700:1: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
    if (!chan->prev_dev && chan->pciec_card)
    ^~
   drivers/net/can/sja1000/peak_pci.c:702:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
     pci_set_drvdata(pdev, chan->prev_dev);
     ^~~~~~~~~~~~~~~


vim +/if +700 drivers/net/can/sja1000/peak_pci.c

   550	
   551	static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
   552	{
   553		struct sja1000_priv *priv;
   554		struct peak_pci_chan *chan;
   555		struct net_device *dev, *prev_dev;
   556		void __iomem *cfg_base, *reg_base;
   557		u16 sub_sys_id, icr;
   558		int i, err, channels;
   559		char fw_str[14] = "";
   560	
   561		err = pci_enable_device(pdev);
   562		if (err)
   563			return err;
   564	
   565		err = pci_request_regions(pdev, DRV_NAME);
   566		if (err)
   567			goto failure_disable_pci;
   568	
   569		err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
   570		if (err)
   571			goto failure_release_regions;
   572	
   573		dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
   574			pdev->vendor, pdev->device, sub_sys_id);
   575	
   576		err = pci_write_config_word(pdev, 0x44, 0);
   577		if (err)
   578			goto failure_release_regions;
   579	
   580		if (sub_sys_id >= 12)
   581			channels = 4;
   582		else if (sub_sys_id >= 10)
   583			channels = 3;
   584		else if (sub_sys_id >= 4)
   585			channels = 2;
   586		else
   587			channels = 1;
   588	
   589		cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
   590		if (!cfg_base) {
   591			dev_err(&pdev->dev, "failed to map PCI resource #0\n");
   592			err = -ENOMEM;
   593			goto failure_release_regions;
   594		}
   595	
   596		reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
   597		if (!reg_base) {
   598			dev_err(&pdev->dev, "failed to map PCI resource #1\n");
   599			err = -ENOMEM;
   600			goto failure_unmap_cfg_base;
   601		}
   602	
   603		/* Set GPIO control register */
   604		writew(0x0005, cfg_base + PITA_GPIOICR + 2);
   605		/* Enable all channels of this card */
   606		writeb(0x00, cfg_base + PITA_GPIOICR);
   607		/* Toggle reset */
   608		writeb(0x05, cfg_base + PITA_MISC + 3);
   609		usleep_range(5000, 6000);
   610		/* Leave parport mux mode */
   611		writeb(0x04, cfg_base + PITA_MISC + 3);
   612	
   613		/* FPGA equipped card if not 0 */
   614		if (readl(cfg_base + PEAK_VER_REG1)) {
   615			/* FPGA card: display version of the running firmware */
   616			u32 fw_ver = readl(cfg_base + PEAK_VER_REG2);
   617	
   618			snprintf(fw_str, sizeof(fw_str), " FW v%u.%u.%u",
   619				 (fw_ver >> 12) & 0xf,
   620				 (fw_ver >> 8) & 0xf,
   621				 (fw_ver >> 4) & 0xf);
   622		}
   623	
   624		/* Display commercial name (and, eventually, FW version) of the card */
   625		dev_info(&pdev->dev, "%ux CAN %s%s\n",
   626			 channels, (const char *)ent->driver_data, fw_str);
   627	
   628		icr = readw(cfg_base + PITA_ICR + 2);
   629	
   630		for (i = 0; i < channels; i++) {
   631			dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
   632			if (!dev) {
   633				err = -ENOMEM;
   634				goto failure_remove_channels;
   635			}
   636	
   637			priv = netdev_priv(dev);
   638			chan = priv->priv;
   639	
   640			chan->cfg_base = cfg_base;
   641			priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;
   642	
   643			priv->read_reg = peak_pci_read_reg;
   644			priv->write_reg = peak_pci_write_reg;
   645			priv->post_irq = peak_pci_post_irq;
   646	
   647			priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
   648			priv->ocr = PEAK_PCI_OCR;
   649			priv->cdr = PEAK_PCI_CDR;
   650			/* Neither a slave nor a single device distributes the clock */
   651			if (channels == 1 || i > 0)
   652				priv->cdr |= CDR_CLK_OFF;
   653	
   654			/* Setup interrupt handling */
   655			priv->irq_flags = IRQF_SHARED;
   656			dev->irq = pdev->irq;
   657	
   658			chan->icr_mask = peak_pci_icr_masks[i];
   659			icr |= chan->icr_mask;
   660	
   661			SET_NETDEV_DEV(dev, &pdev->dev);
   662			dev->dev_id = i;
   663	
   664			/* Create chain of SJA1000 devices */
   665			chan->prev_dev = pci_get_drvdata(pdev);
   666			pci_set_drvdata(pdev, dev);
   667	
   668			/* PCAN-ExpressCard needs some additional i2c init.
   669			 * This must be done *before* register_sja1000dev() but
   670			 * *after* devices linkage
   671			 */
   672			if (pdev->device == PEAK_PCIEC_DEVICE_ID ||
   673			    pdev->device == PEAK_PCIEC34_DEVICE_ID) {
   674				err = peak_pciec_probe(pdev, dev);
   675				if (err) {
   676					dev_err(&pdev->dev,
   677						"failed to probe device (err %d)\n",
   678						err);
   679					goto failure_free_dev;
   680				}
   681			}
   682	
   683			err = register_sja1000dev(dev);
   684			if (err) {
   685				dev_err(&pdev->dev, "failed to register device\n");
   686				goto failure_free_dev;
   687			}
   688	
   689			dev_info(&pdev->dev,
   690				 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
   691				 dev->name, priv->reg_base, chan->cfg_base, dev->irq);
   692		}
   693	
   694		/* Enable interrupts */
   695		writew(icr, cfg_base + PITA_ICR + 2);
   696	
   697		return 0;
   698	
   699	failure_free_dev:
 > 700	if (!chan->prev_dev && chan->pciec_card)
   701		peak_pciec_remove(chan->pciec_card);
   702		pci_set_drvdata(pdev, chan->prev_dev);
   703		free_sja1000dev(dev);
   704	
   705	failure_remove_channels:
   706		/* Disable interrupts */
   707		writew(0x0, cfg_base + PITA_ICR + 2);
   708	
   709		for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
   710			priv = netdev_priv(dev);
   711			chan = priv->priv;
   712			prev_dev = chan->prev_dev;
   713	
   714			/* do that only for first channel */
   715			if (!prev_dev && chan->pciec_card)
   716				peak_pciec_remove(chan->pciec_card);
   717			unregister_sja1000dev(dev);
   718			free_sja1000dev(dev);
   719		}
   720	
   721		pci_iounmap(pdev, reg_base);
   722	
   723	failure_unmap_cfg_base:
   724		pci_iounmap(pdev, cfg_base);
   725	
   726	failure_release_regions:
   727		pci_release_regions(pdev);
   728	
   729	failure_disable_pci:
   730		pci_disable_device(pdev);
   731	
   732		/* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while
   733		 * the probe() function must return a negative errno in case of failure
   734		 * (err is unchanged if negative)
   735		 */
   736		return pcibios_err_to_errno(err);
   737	}
   738	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure
  2026-09-15 17:31 [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure Guangshuo Li
  2026-09-16 17:30 ` kernel test robot
@ 2026-09-16 19:07 ` kernel test robot
  1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2026-09-16 19:07 UTC (permalink / raw)
  To: Guangshuo Li, Marc Kleine-Budde, Vincent Mailhol,
	Stéphane Grosjean, Kees Cook, Wolfgang Grandegger,
	linux-can, linux-kernel
  Cc: llvm, oe-kbuild-all, stable

Hi Guangshuo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkl-can-next/testing]
[also build test WARNING on linus/master v7.3-rc3 next-20260914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Guangshuo-Li/can-peak_pci-fix-PCIeC-cleanup-on-probe-failure/20260916-013157
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git testing
patch link:    https://lore.kernel.org/r/20260915173157.2510375-1-lgs201920130244%40gmail.com
patch subject: [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20260917/202609170334.HGvXQS1L-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260917/202609170334.HGvXQS1L-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609170334.HGvXQS1L-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/net/can/sja1000/peak_pci.c:702:2: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
     702 |         pci_set_drvdata(pdev, chan->prev_dev);
         |         ^
   drivers/net/can/sja1000/peak_pci.c:700:1: note: previous statement is here
     700 | if (!chan->prev_dev && chan->pciec_card)
         | ^
   1 warning generated.


vim +/if +702 drivers/net/can/sja1000/peak_pci.c

38034518c086fc Wolfgang Grandegger  2011-09-12  550  
1dd06ae8db716e Greg Kroah-Hartman   2012-12-06  551  static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
38034518c086fc Wolfgang Grandegger  2011-09-12  552  {
38034518c086fc Wolfgang Grandegger  2011-09-12  553  	struct sja1000_priv *priv;
38034518c086fc Wolfgang Grandegger  2011-09-12  554  	struct peak_pci_chan *chan;
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  555  	struct net_device *dev, *prev_dev;
38034518c086fc Wolfgang Grandegger  2011-09-12  556  	void __iomem *cfg_base, *reg_base;
38034518c086fc Wolfgang Grandegger  2011-09-12  557  	u16 sub_sys_id, icr;
38034518c086fc Wolfgang Grandegger  2011-09-12  558  	int i, err, channels;
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  559  	char fw_str[14] = "";
38034518c086fc Wolfgang Grandegger  2011-09-12  560  
38034518c086fc Wolfgang Grandegger  2011-09-12  561  	err = pci_enable_device(pdev);
38034518c086fc Wolfgang Grandegger  2011-09-12  562  	if (err)
38034518c086fc Wolfgang Grandegger  2011-09-12  563  		return err;
38034518c086fc Wolfgang Grandegger  2011-09-12  564  
38034518c086fc Wolfgang Grandegger  2011-09-12  565  	err = pci_request_regions(pdev, DRV_NAME);
38034518c086fc Wolfgang Grandegger  2011-09-12  566  	if (err)
38034518c086fc Wolfgang Grandegger  2011-09-12  567  		goto failure_disable_pci;
38034518c086fc Wolfgang Grandegger  2011-09-12  568  
38034518c086fc Wolfgang Grandegger  2011-09-12  569  	err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
38034518c086fc Wolfgang Grandegger  2011-09-12  570  	if (err)
38034518c086fc Wolfgang Grandegger  2011-09-12  571  		goto failure_release_regions;
38034518c086fc Wolfgang Grandegger  2011-09-12  572  
38034518c086fc Wolfgang Grandegger  2011-09-12  573  	dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
38034518c086fc Wolfgang Grandegger  2011-09-12  574  		pdev->vendor, pdev->device, sub_sys_id);
38034518c086fc Wolfgang Grandegger  2011-09-12  575  
38034518c086fc Wolfgang Grandegger  2011-09-12  576  	err = pci_write_config_word(pdev, 0x44, 0);
38034518c086fc Wolfgang Grandegger  2011-09-12  577  	if (err)
38034518c086fc Wolfgang Grandegger  2011-09-12  578  		goto failure_release_regions;
38034518c086fc Wolfgang Grandegger  2011-09-12  579  
38034518c086fc Wolfgang Grandegger  2011-09-12  580  	if (sub_sys_id >= 12)
38034518c086fc Wolfgang Grandegger  2011-09-12  581  		channels = 4;
38034518c086fc Wolfgang Grandegger  2011-09-12  582  	else if (sub_sys_id >= 10)
38034518c086fc Wolfgang Grandegger  2011-09-12  583  		channels = 3;
38034518c086fc Wolfgang Grandegger  2011-09-12  584  	else if (sub_sys_id >= 4)
38034518c086fc Wolfgang Grandegger  2011-09-12  585  		channels = 2;
38034518c086fc Wolfgang Grandegger  2011-09-12  586  	else
38034518c086fc Wolfgang Grandegger  2011-09-12  587  		channels = 1;
38034518c086fc Wolfgang Grandegger  2011-09-12  588  
38034518c086fc Wolfgang Grandegger  2011-09-12  589  	cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
38034518c086fc Wolfgang Grandegger  2011-09-12  590  	if (!cfg_base) {
38034518c086fc Wolfgang Grandegger  2011-09-12  591  		dev_err(&pdev->dev, "failed to map PCI resource #0\n");
4a4bfdcd295728 Peter Senna Tschudin 2012-10-03  592  		err = -ENOMEM;
38034518c086fc Wolfgang Grandegger  2011-09-12  593  		goto failure_release_regions;
38034518c086fc Wolfgang Grandegger  2011-09-12  594  	}
38034518c086fc Wolfgang Grandegger  2011-09-12  595  
38034518c086fc Wolfgang Grandegger  2011-09-12  596  	reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
38034518c086fc Wolfgang Grandegger  2011-09-12  597  	if (!reg_base) {
38034518c086fc Wolfgang Grandegger  2011-09-12  598  		dev_err(&pdev->dev, "failed to map PCI resource #1\n");
4a4bfdcd295728 Peter Senna Tschudin 2012-10-03  599  		err = -ENOMEM;
38034518c086fc Wolfgang Grandegger  2011-09-12  600  		goto failure_unmap_cfg_base;
38034518c086fc Wolfgang Grandegger  2011-09-12  601  	}
38034518c086fc Wolfgang Grandegger  2011-09-12  602  
38034518c086fc Wolfgang Grandegger  2011-09-12  603  	/* Set GPIO control register */
38034518c086fc Wolfgang Grandegger  2011-09-12  604  	writew(0x0005, cfg_base + PITA_GPIOICR + 2);
38034518c086fc Wolfgang Grandegger  2011-09-12  605  	/* Enable all channels of this card */
38034518c086fc Wolfgang Grandegger  2011-09-12  606  	writeb(0x00, cfg_base + PITA_GPIOICR);
38034518c086fc Wolfgang Grandegger  2011-09-12  607  	/* Toggle reset */
38034518c086fc Wolfgang Grandegger  2011-09-12  608  	writeb(0x05, cfg_base + PITA_MISC + 3);
276b7361bb1be3 Jia-Ju Bai           2018-04-11  609  	usleep_range(5000, 6000);
38034518c086fc Wolfgang Grandegger  2011-09-12  610  	/* Leave parport mux mode */
38034518c086fc Wolfgang Grandegger  2011-09-12  611  	writeb(0x04, cfg_base + PITA_MISC + 3);
38034518c086fc Wolfgang Grandegger  2011-09-12  612  
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  613  	/* FPGA equipped card if not 0 */
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  614  	if (readl(cfg_base + PEAK_VER_REG1)) {
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  615  		/* FPGA card: display version of the running firmware */
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  616  		u32 fw_ver = readl(cfg_base + PEAK_VER_REG2);
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  617  
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  618  		snprintf(fw_str, sizeof(fw_str), " FW v%u.%u.%u",
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  619  			 (fw_ver >> 12) & 0xf,
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  620  			 (fw_ver >> 8) & 0xf,
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  621  			 (fw_ver >> 4) & 0xf);
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  622  	}
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  623  
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  624  	/* Display commercial name (and, eventually, FW version) of the card */
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  625  	dev_info(&pdev->dev, "%ux CAN %s%s\n",
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  626  		 channels, (const char *)ent->driver_data, fw_str);
805ff68c8e7f4d Stéphane Grosjean    2021-06-07  627  
38034518c086fc Wolfgang Grandegger  2011-09-12  628  	icr = readw(cfg_base + PITA_ICR + 2);
38034518c086fc Wolfgang Grandegger  2011-09-12  629  
38034518c086fc Wolfgang Grandegger  2011-09-12  630  	for (i = 0; i < channels; i++) {
38034518c086fc Wolfgang Grandegger  2011-09-12  631  		dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
38034518c086fc Wolfgang Grandegger  2011-09-12  632  		if (!dev) {
38034518c086fc Wolfgang Grandegger  2011-09-12  633  			err = -ENOMEM;
38034518c086fc Wolfgang Grandegger  2011-09-12  634  			goto failure_remove_channels;
38034518c086fc Wolfgang Grandegger  2011-09-12  635  		}
38034518c086fc Wolfgang Grandegger  2011-09-12  636  
38034518c086fc Wolfgang Grandegger  2011-09-12  637  		priv = netdev_priv(dev);
38034518c086fc Wolfgang Grandegger  2011-09-12  638  		chan = priv->priv;
38034518c086fc Wolfgang Grandegger  2011-09-12  639  
38034518c086fc Wolfgang Grandegger  2011-09-12  640  		chan->cfg_base = cfg_base;
38034518c086fc Wolfgang Grandegger  2011-09-12  641  		priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;
38034518c086fc Wolfgang Grandegger  2011-09-12  642  
38034518c086fc Wolfgang Grandegger  2011-09-12  643  		priv->read_reg = peak_pci_read_reg;
38034518c086fc Wolfgang Grandegger  2011-09-12  644  		priv->write_reg = peak_pci_write_reg;
38034518c086fc Wolfgang Grandegger  2011-09-12  645  		priv->post_irq = peak_pci_post_irq;
38034518c086fc Wolfgang Grandegger  2011-09-12  646  
38034518c086fc Wolfgang Grandegger  2011-09-12  647  		priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
38034518c086fc Wolfgang Grandegger  2011-09-12  648  		priv->ocr = PEAK_PCI_OCR;
38034518c086fc Wolfgang Grandegger  2011-09-12  649  		priv->cdr = PEAK_PCI_CDR;
38034518c086fc Wolfgang Grandegger  2011-09-12  650  		/* Neither a slave nor a single device distributes the clock */
38034518c086fc Wolfgang Grandegger  2011-09-12  651  		if (channels == 1 || i > 0)
38034518c086fc Wolfgang Grandegger  2011-09-12  652  			priv->cdr |= CDR_CLK_OFF;
38034518c086fc Wolfgang Grandegger  2011-09-12  653  
38034518c086fc Wolfgang Grandegger  2011-09-12  654  		/* Setup interrupt handling */
38034518c086fc Wolfgang Grandegger  2011-09-12  655  		priv->irq_flags = IRQF_SHARED;
38034518c086fc Wolfgang Grandegger  2011-09-12  656  		dev->irq = pdev->irq;
38034518c086fc Wolfgang Grandegger  2011-09-12  657  
38034518c086fc Wolfgang Grandegger  2011-09-12  658  		chan->icr_mask = peak_pci_icr_masks[i];
38034518c086fc Wolfgang Grandegger  2011-09-12  659  		icr |= chan->icr_mask;
38034518c086fc Wolfgang Grandegger  2011-09-12  660  
38034518c086fc Wolfgang Grandegger  2011-09-12  661  		SET_NETDEV_DEV(dev, &pdev->dev);
3e66d0138c05d9 Christopher R. Baker 2014-03-08  662  		dev->dev_id = i;
38034518c086fc Wolfgang Grandegger  2011-09-12  663  
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  664  		/* Create chain of SJA1000 devices */
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  665  		chan->prev_dev = pci_get_drvdata(pdev);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  666  		pci_set_drvdata(pdev, dev);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  667  
9b69aff9fd1a66 Marc Kleine-Budde    2021-06-11  668  		/* PCAN-ExpressCard needs some additional i2c init.
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  669  		 * This must be done *before* register_sja1000dev() but
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  670  		 * *after* devices linkage
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  671  		 */
4be0015c955a9a Oliver Hartkopp      2014-09-16  672  		if (pdev->device == PEAK_PCIEC_DEVICE_ID ||
4be0015c955a9a Oliver Hartkopp      2014-09-16  673  		    pdev->device == PEAK_PCIEC34_DEVICE_ID) {
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  674  			err = peak_pciec_probe(pdev, dev);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  675  			if (err) {
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  676  				dev_err(&pdev->dev,
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  677  					"failed to probe device (err %d)\n",
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  678  					err);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  679  				goto failure_free_dev;
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  680  			}
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  681  		}
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  682  
38034518c086fc Wolfgang Grandegger  2011-09-12  683  		err = register_sja1000dev(dev);
38034518c086fc Wolfgang Grandegger  2011-09-12  684  		if (err) {
38034518c086fc Wolfgang Grandegger  2011-09-12  685  			dev_err(&pdev->dev, "failed to register device\n");
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  686  			goto failure_free_dev;
38034518c086fc Wolfgang Grandegger  2011-09-12  687  		}
38034518c086fc Wolfgang Grandegger  2011-09-12  688  
38034518c086fc Wolfgang Grandegger  2011-09-12  689  		dev_info(&pdev->dev,
38034518c086fc Wolfgang Grandegger  2011-09-12  690  			 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
38034518c086fc Wolfgang Grandegger  2011-09-12  691  			 dev->name, priv->reg_base, chan->cfg_base, dev->irq);
38034518c086fc Wolfgang Grandegger  2011-09-12  692  	}
38034518c086fc Wolfgang Grandegger  2011-09-12  693  
38034518c086fc Wolfgang Grandegger  2011-09-12  694  	/* Enable interrupts */
38034518c086fc Wolfgang Grandegger  2011-09-12  695  	writew(icr, cfg_base + PITA_ICR + 2);
38034518c086fc Wolfgang Grandegger  2011-09-12  696  
38034518c086fc Wolfgang Grandegger  2011-09-12  697  	return 0;
38034518c086fc Wolfgang Grandegger  2011-09-12  698  
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  699  failure_free_dev:
d0c5c584fb3542 Guangshuo Li         2026-09-16  700  if (!chan->prev_dev && chan->pciec_card)
d0c5c584fb3542 Guangshuo Li         2026-09-16  701  	peak_pciec_remove(chan->pciec_card);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02 @702  	pci_set_drvdata(pdev, chan->prev_dev);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  703  	free_sja1000dev(dev);
e6d9c80b7ca150 Stéphane Grosjean    2012-03-02  704  
38034518c086fc Wolfgang Grandegger  2011-09-12  705  failure_remove_channels:
38034518c086fc Wolfgang Grandegger  2011-09-12  706  	/* Disable interrupts */
38034518c086fc Wolfgang Grandegger  2011-09-12  707  	writew(0x0, cfg_base + PITA_ICR + 2);
38034518c086fc Wolfgang Grandegger  2011-09-12  708  
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  709  	for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
38034518c086fc Wolfgang Grandegger  2011-09-12  710  		priv = netdev_priv(dev);
38034518c086fc Wolfgang Grandegger  2011-09-12  711  		chan = priv->priv;
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  712  		prev_dev = chan->prev_dev;
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  713  
d0c5c584fb3542 Guangshuo Li         2026-09-16  714  		/* do that only for first channel */
d0c5c584fb3542 Guangshuo Li         2026-09-16  715  		if (!prev_dev && chan->pciec_card)
d0c5c584fb3542 Guangshuo Li         2026-09-16  716  			peak_pciec_remove(chan->pciec_card);
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  717  		unregister_sja1000dev(dev);
0b5a958cf4df3a Stéphane Grosjean    2014-05-20  718  		free_sja1000dev(dev);
38034518c086fc Wolfgang Grandegger  2011-09-12  719  	}
38034518c086fc Wolfgang Grandegger  2011-09-12  720  
38034518c086fc Wolfgang Grandegger  2011-09-12  721  	pci_iounmap(pdev, reg_base);
38034518c086fc Wolfgang Grandegger  2011-09-12  722  
38034518c086fc Wolfgang Grandegger  2011-09-12  723  failure_unmap_cfg_base:
38034518c086fc Wolfgang Grandegger  2011-09-12  724  	pci_iounmap(pdev, cfg_base);
38034518c086fc Wolfgang Grandegger  2011-09-12  725  
38034518c086fc Wolfgang Grandegger  2011-09-12  726  failure_release_regions:
38034518c086fc Wolfgang Grandegger  2011-09-12  727  	pci_release_regions(pdev);
38034518c086fc Wolfgang Grandegger  2011-09-12  728  
38034518c086fc Wolfgang Grandegger  2011-09-12  729  failure_disable_pci:
38034518c086fc Wolfgang Grandegger  2011-09-12  730  	pci_disable_device(pdev);
38034518c086fc Wolfgang Grandegger  2011-09-12  731  
5c2cb02edf79ad Stéphane Grosjean    2017-11-23  732  	/* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while
5c2cb02edf79ad Stéphane Grosjean    2017-11-23  733  	 * the probe() function must return a negative errno in case of failure
9b69aff9fd1a66 Marc Kleine-Budde    2021-06-11  734  	 * (err is unchanged if negative)
9b69aff9fd1a66 Marc Kleine-Budde    2021-06-11  735  	 */
5c2cb02edf79ad Stéphane Grosjean    2017-11-23  736  	return pcibios_err_to_errno(err);
38034518c086fc Wolfgang Grandegger  2011-09-12  737  }
38034518c086fc Wolfgang Grandegger  2011-09-12  738  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-16 19:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 17:31 [PATCH] can: peak_pci: fix PCIeC cleanup on probe failure Guangshuo Li
2026-09-16 17:30 ` kernel test robot
2026-09-16 19:07 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®