dmaenginge.c: class_device_register() return value
Subsystems (2)
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!
Signed-off-by Johannes Weiner <[email protected]>
drivers/dma/dmaengine.c +27 -3
@@ -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
@@ -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);