Skip to content

Commit d2fb0a0

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: break out channel registration
In preparation for dynamic channel registration, the code segment that does the channel registration is broken out to its own function. Signed-off-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/157965022778.73301.8929944324898985438.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <[email protected]>
1 parent 232bb01 commit d2fb0a0

File tree

1 file changed

+81
-54
lines changed

1 file changed

+81
-54
lines changed

drivers/dma/dmaengine.c

Lines changed: 81 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,79 @@ static int get_dma_id(struct dma_device *device)
926926
return 0;
927927
}
928928

929+
static int __dma_async_device_channel_register(struct dma_device *device,
930+
struct dma_chan *chan,
931+
int chan_id)
932+
{
933+
int rc = 0;
934+
int chancnt = device->chancnt;
935+
atomic_t *idr_ref;
936+
struct dma_chan *tchan;
937+
938+
tchan = list_first_entry_or_null(&device->channels,
939+
struct dma_chan, device_node);
940+
if (tchan->dev) {
941+
idr_ref = tchan->dev->idr_ref;
942+
} else {
943+
idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL);
944+
if (!idr_ref)
945+
return -ENOMEM;
946+
atomic_set(idr_ref, 0);
947+
}
948+
949+
chan->local = alloc_percpu(typeof(*chan->local));
950+
if (!chan->local)
951+
goto err_out;
952+
chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL);
953+
if (!chan->dev) {
954+
free_percpu(chan->local);
955+
chan->local = NULL;
956+
goto err_out;
957+
}
958+
959+
/*
960+
* When the chan_id is a negative value, we are dynamically adding
961+
* the channel. Otherwise we are static enumerating.
962+
*/
963+
chan->chan_id = chan_id < 0 ? chancnt : chan_id;
964+
chan->dev->device.class = &dma_devclass;
965+
chan->dev->device.parent = device->dev;
966+
chan->dev->chan = chan;
967+
chan->dev->idr_ref = idr_ref;
968+
chan->dev->dev_id = device->dev_id;
969+
atomic_inc(idr_ref);
970+
dev_set_name(&chan->dev->device, "dma%dchan%d",
971+
device->dev_id, chan->chan_id);
972+
973+
rc = device_register(&chan->dev->device);
974+
if (rc)
975+
goto err_out;
976+
chan->client_count = 0;
977+
device->chancnt = chan->chan_id + 1;
978+
979+
return 0;
980+
981+
err_out:
982+
free_percpu(chan->local);
983+
kfree(chan->dev);
984+
if (atomic_dec_return(idr_ref) == 0)
985+
kfree(idr_ref);
986+
return rc;
987+
}
988+
989+
static void __dma_async_device_channel_unregister(struct dma_device *device,
990+
struct dma_chan *chan)
991+
{
992+
WARN_ONCE(!device->device_release && chan->client_count,
993+
"%s called while %d clients hold a reference\n",
994+
__func__, chan->client_count);
995+
mutex_lock(&dma_list_mutex);
996+
chan->dev->chan = NULL;
997+
mutex_unlock(&dma_list_mutex);
998+
device_unregister(&chan->dev->device);
999+
free_percpu(chan->local);
1000+
}
1001+
9291002
/**
9301003
* dma_async_device_register - registers DMA devices found
9311004
* @device: &dma_device
@@ -936,9 +1009,8 @@ static int get_dma_id(struct dma_device *device)
9361009
*/
9371010
int dma_async_device_register(struct dma_device *device)
9381011
{
939-
int chancnt = 0, rc;
1012+
int rc, i = 0;
9401013
struct dma_chan* chan;
941-
atomic_t *idr_ref;
9421014

9431015
if (!device)
9441016
return -ENODEV;
@@ -1038,59 +1110,23 @@ int dma_async_device_register(struct dma_device *device)
10381110
if (device_has_all_tx_types(device))
10391111
dma_cap_set(DMA_ASYNC_TX, device->cap_mask);
10401112

1041-
idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL);
1042-
if (!idr_ref)
1043-
return -ENOMEM;
10441113
rc = get_dma_id(device);
1045-
if (rc != 0) {
1046-
kfree(idr_ref);
1114+
if (rc != 0)
10471115
return rc;
1048-
}
1049-
1050-
atomic_set(idr_ref, 0);
10511116

10521117
/* represent channels in sysfs. Probably want devs too */
10531118
list_for_each_entry(chan, &device->channels, device_node) {
1054-
rc = -ENOMEM;
1055-
chan->local = alloc_percpu(typeof(*chan->local));
1056-
if (chan->local == NULL)
1119+
rc = __dma_async_device_channel_register(device, chan, i++);
1120+
if (rc < 0)
10571121
goto err_out;
1058-
chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL);
1059-
if (chan->dev == NULL) {
1060-
free_percpu(chan->local);
1061-
chan->local = NULL;
1062-
goto err_out;
1063-
}
1064-
1065-
chan->chan_id = chancnt++;
1066-
chan->dev->device.class = &dma_devclass;
1067-
chan->dev->device.parent = device->dev;
1068-
chan->dev->chan = chan;
1069-
chan->dev->idr_ref = idr_ref;
1070-
chan->dev->dev_id = device->dev_id;
1071-
atomic_inc(idr_ref);
1072-
dev_set_name(&chan->dev->device, "dma%dchan%d",
1073-
device->dev_id, chan->chan_id);
1074-
1075-
rc = device_register(&chan->dev->device);
1076-
if (rc) {
1077-
free_percpu(chan->local);
1078-
chan->local = NULL;
1079-
kfree(chan->dev);
1080-
atomic_dec(idr_ref);
1081-
goto err_out;
1082-
}
1083-
chan->client_count = 0;
10841122
}
10851123

1086-
if (!chancnt) {
1124+
if (!device->chancnt) {
10871125
dev_err(device->dev, "%s: device has no channels!\n", __func__);
10881126
rc = -ENODEV;
10891127
goto err_out;
10901128
}
10911129

1092-
device->chancnt = chancnt;
1093-
10941130
mutex_lock(&dma_list_mutex);
10951131
/* take references on public channels */
10961132
if (dmaengine_ref_count && !dma_has_cap(DMA_PRIVATE, device->cap_mask))
@@ -1118,9 +1154,8 @@ int dma_async_device_register(struct dma_device *device)
11181154

11191155
err_out:
11201156
/* if we never registered a channel just release the idr */
1121-
if (atomic_read(idr_ref) == 0) {
1157+
if (!device->chancnt) {
11221158
ida_free(&dma_ida, device->dev_id);
1123-
kfree(idr_ref);
11241159
return rc;
11251160
}
11261161

@@ -1148,16 +1183,8 @@ void dma_async_device_unregister(struct dma_device *device)
11481183
{
11491184
struct dma_chan *chan;
11501185

1151-
list_for_each_entry(chan, &device->channels, device_node) {
1152-
WARN_ONCE(!device->device_release && chan->client_count,
1153-
"%s called while %d clients hold a reference\n",
1154-
__func__, chan->client_count);
1155-
mutex_lock(&dma_list_mutex);
1156-
chan->dev->chan = NULL;
1157-
mutex_unlock(&dma_list_mutex);
1158-
device_unregister(&chan->dev->device);
1159-
free_percpu(chan->local);
1160-
}
1186+
list_for_each_entry(chan, &device->channels, device_node)
1187+
__dma_async_device_channel_unregister(device, chan);
11611188

11621189
mutex_lock(&dma_list_mutex);
11631190
/*

0 commit comments

Comments
 (0)