[RFC 5/7][PATCH] AMBA DMA: Check the result of a probe of the pl080.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As a general rule, the kernel must allow probes to fail,
but we should not insert the PL080 driver if it's probe fails.

Signed-off-by: Peter M Pearse <[email protected]> 

---

diff -purN arm_amba_pl080/drivers/amba/dma.c
arm_amba_pl080err/drivers/amba/dma.c
--- arm_amba_pl080/drivers/amba/dma.c	2006-10-17 17:14:06.000000000 +0100
+++ arm_amba_pl080err/drivers/amba/dma.c	2006-10-18
08:24:03.000000000 +0100
@@ -116,7 +116,7 @@ static struct dma_ops amba_dma_ops = {
 /*
  * Initialize the dma channels, as far as we can
  */
-void amba_init_dma(dma_t *channels)
+int amba_init_dma(dma_t *channels)
 {
 	int i;
 
@@ -135,6 +135,7 @@ void amba_init_dma(dma_t *channels)
 		channels[i].state = 0;
 		channels[i].d_ops = &amba_dma_ops;
 	}
+	return 1;
 }
 EXPORT_SYMBOL(amba_init_dma);
 
diff -purN arm_amba_pl080/drivers/amba/pl080.c
arm_amba_pl080err/drivers/amba/pl080.c
--- arm_amba_pl080/drivers/amba/pl080.c	2006-10-17 17:14:20.000000000 +0100
+++ arm_amba_pl080err/drivers/amba/pl080.c	2006-10-18
08:24:03.000000000 +0100
@@ -237,7 +237,11 @@ pl080_extra_ops pl080_ops = {
  * Complete the DMA channel initialization
  * started by the AMBA DMA code
  * - Set the dma ops for the board to call
+ * Since driver registration disregards any probe errors we 
+ * store the result to prevent registration of an invalid driver
+ * and possible insertion of an invalid module
  */
+static int probe_err = 0;	/* Protected by the device lock */
 static int __devinit pl080_probe(struct amba_device *dev, void *id)
 {
 	int ret,i;
@@ -271,19 +275,25 @@ static int __devinit pl080_probe(struct 
 	if(!(pl080.pool = dma_pool_create(pl080_driver.drv.name, (struct
device *)dev,
 			PL080_MAX_LLIS_SIZE, PL080_ALIGN, PL080_ALLOC))){
 
-		kfree(pl080.chanllis);
 		ret = -ENOMEM;
-		goto out;
+		goto out2;
+	}
+	/* TODO:: Get the parameters from amba_device */
+	if(!pl080_init_dma(dev->chans, dev->dmac_ops)){
+		ret = -EPERM;
+		goto out2;
 	}
-	/* TODO:: Get the parameters from amb_device */
-	pl080_init_dma(dev->chans, dev->dmac_ops);
+
 	pl080_driver.drv.owner = try_find_module(MODULE_NAME);
 	
-	return ret;
+	return (probe_err = ret);
+
+ out2:
+      	kfree(pl080.chanllis);
 
  out:
 	amba_release_regions(dev);
-	return ret;
+	return (probe_err = ret);
 }
 
 static struct amba_id pl080_ids[] = {
@@ -309,26 +319,32 @@ static struct amba_driver pl080_driver =
 
 int pl080_init_dma(dma_t * dma_chan, struct dma_ops * ops){
 	int i;
+	int retval = 0;
 
-	for(i = 0; i < MAX_DMA_CHANNELS; i++){
-		dma_chan[i].dma_base = (unsigned int)pl080.base;
-	}
-	ops->request 	= pl080_request;
-	ops->free	= pl080_free;
-	ops->enable	= pl080_enable ;
-	ops->disable 	= pl080_disable;
-	ops->residue 	= pl080_residue;
-	ops->setspeed 	= pl080_setspeed;
-	ops->type 	= pl080_type;
+	if(ops){
+
+		for(i = 0; i < MAX_DMA_CHANNELS; i++){
+			dma_chan[i].dma_base = (unsigned int)pl080.base;
+		}
+		ops->request 	= pl080_request;
+		ops->free	= pl080_free;
+		ops->enable	= pl080_enable ;
+		ops->disable 	= pl080_disable;
+		ops->residue 	= pl080_residue;
+		ops->setspeed 	= pl080_setspeed;
+		ops->type 	= pl080_type;
 	
-	/* PL080 specific */
-	ops->extra_ops = &pl080_ops;
+		/* PL080 specific */
+		ops->extra_ops = &pl080_ops;
 
-	pl080_driver.dmac_ops = ops;
+		pl080_driver.dmac_ops = ops;
 
-	amba_init_dma(dma_chan);
+		retval = amba_init_dma(dma_chan);
+	} else {
+		printk(KERN_ERR "pl080_init_dma() board has not supplied
operations\n"); 
+	}
 
-	return 0;
+	return retval;
 }
 
 /*
@@ -355,14 +371,20 @@ static int __devexit pl080_remove(struct
 
 /*
  * Module initialization
+ * - probe errors are ignored by driver registration
+ * - force the initialization to fail if the probe fails
  */
 static int __init pl080_init(void)
 {
 	pl080.base = NULL;
 	pl080.chanllis = NULL; /* LLI details for each DMA channel */
 	pl080.pool = NULL;
-	
-	return amba_driver_register(&pl080_driver);
+
+	probe_err = 0;
+
+	amba_driver_register(&pl080_driver);
+
+	return probe_err;
 }
 /*
  * Module destruction
diff -purN arm_amba_pl080/include/linux/amba/dma.h
arm_amba_pl080err/include/linux/amba/dma.h
--- arm_amba_pl080/include/linux/amba/dma.h	2006-10-17
17:14:06.000000000 +0100
+++ arm_amba_pl080err/include/linux/amba/dma.h	2006-10-18
08:24:03.000000000 +0100
@@ -26,7 +26,7 @@ struct amba_dma_data {
 };
 
 extern dma_t *		amba_get_chans	(void);
-extern void		amba_init_dma	(dma_t *channels);
+extern int		amba_init_dma	(dma_t *channels);
 struct amba_device *	amba_get_device_with_name(char * name);
 void			amba_set_ops	(struct dma_ops * ops);



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux