Skip to contentSkip to conversation

dmaenginge.c: class_device_register() return value

PATCH New Johannes Weiner 1 participant 1 message Mar 19, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 dmaenginge.c: class_device_register() return value

Hi,

this patch makes dma_async_device_register() in drivers/dma/dmaengine.c handle a failing class_device_register(). Patched against Linus' git tree, compile-tested.

I also thought about calling dma_async_device_unregister on failure, but I was not quite sure if this would work. And I noticed that memory is allocated for chan->local in dma_async_device_register() but I couldn't find where it is released again.

I am quite new to this all, please give me feedback!

drivers/dma/dmaengine.c +27 -3
index 322ee29..5560e39 100644
@@ -316,8 +316,8 @@ EXPORT_SYMBOL(dma_async_client_chan_request);
 int dma_async_device_register(struct dma_device *device)
 {
 	static int id;
-	int chancnt = 0;
-	struct dma_chan* chan;
+	int chancnt, err;
+	struct dma_chan *chan, *last;
 
 	if (!device)
 		return -ENODEV;
@@ -326,9 +326,13 @@ int dma_async_device_register(struct dma_device *device)
 	kref_init(&device->refcount);
 	device->dev_id = id++;
 
+	err = chancnt = 0;
+
 	/* represent channels in sysfs. Probably want devs too */
 	list_for_each_entry(chan, &device->channels, device_node) {
 		chan->local = alloc_percpu(typeof(*chan->local));
+
+		/* Should this be handled less relaxed? */
 		if (chan->local == NULL)
 			continue;
 
@@ -339,7 +343,11 @@ int dma_async_device_register(struct dma_device *device)
 		         device->dev_id, chan->chan_id);
 
 		kref_get(&device->refcount);
-		class_device_register(&chan->class_dev);
+		err = class_device_register(&chan->class_dev);
+		if (err) {
+			last = chan;
+			goto err_dev_reg;
+		}
 	}
 
 	mutex_lock(&dma_list_mutex);
@@ -349,6 +357,22 @@ int dma_async_device_register(struct dma_device *device)
 	dma_chans_rebalance();
 
 	return 0;
+
+err_dev_reg:
+	list_for_each_entry(chan, &device->channels, device_node) {
+		kref_put(&device->refcount, dma_async_device_cleanup);
+
+		if (chan->local)
+			free_percpu(chan->local);
+
+		if (chan == last)
+			break;
+
+		class_device_unregister(&chan->class_dev);
+	}
+	wait_for_completion(&device->done);
+	device->dev_id = 0;
+	return err;
 }
 EXPORT_SYMBOL(dma_async_device_register);
 
drivers/dma/ioatdma.c +4 -1
index 8e87261..c25f548 100644
@@ -768,10 +768,13 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_self_test;
 
-	dma_async_device_register(&device->common);
+	err = dma_async_device_register(&device->common)
+	if (err)
+		goto err_dev_reg;
 
 	return 0;
 
+err_dev_reg:
 err_self_test:
 err_irq:
 	pci_pool_destroy(device->completion_pool);