diff options
author | Mikko Perttunen <mperttunen@nvidia.com> | 2017-06-14 19:18:42 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-06-15 08:25:38 -0400 |
commit | 8474b02531c4881a762c52ef869c52429e38633f (patch) | |
tree | 41cdb37fa4e424170bd7670e07ca0981c9f6c81f | |
parent | 03f0de770eda7a3f2e3950ca9f15d73e1dfd4596 (diff) |
gpu: host1x: Refactor channel allocation code
This is largely a rewrite of the Host1x channel allocation code, bringing
several changes:
- The previous code could deadlock due to an interaction
between the 'reflock' mutex and CDMA timeout handling.
This gets rid of the mutex.
- Support for more than 32 channels, required for Tegra186
- General refactoring, including better encapsulation
of channel ownership handling into channel.c
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/gr2d.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr3d.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/vic.c | 4 | ||||
-rw-r--r-- | drivers/gpu/host1x/channel.c | 147 | ||||
-rw-r--r-- | drivers/gpu/host1x/channel.h | 21 | ||||
-rw-r--r-- | drivers/gpu/host1x/debug.c | 47 | ||||
-rw-r--r-- | drivers/gpu/host1x/dev.c | 7 | ||||
-rw-r--r-- | drivers/gpu/host1x/dev.h | 6 | ||||
-rw-r--r-- | drivers/gpu/host1x/hw/channel_hw.c | 4 | ||||
-rw-r--r-- | include/linux/host1x.h | 1 |
10 files changed, 135 insertions, 110 deletions
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index fbe0b8b25b42..6ea070da7718 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c | |||
@@ -38,7 +38,7 @@ static int gr2d_init(struct host1x_client *client) | |||
38 | 38 | ||
39 | client->syncpts[0] = host1x_syncpt_request(client->dev, flags); | 39 | client->syncpts[0] = host1x_syncpt_request(client->dev, flags); |
40 | if (!client->syncpts[0]) { | 40 | if (!client->syncpts[0]) { |
41 | host1x_channel_free(gr2d->channel); | 41 | host1x_channel_put(gr2d->channel); |
42 | return -ENOMEM; | 42 | return -ENOMEM; |
43 | } | 43 | } |
44 | 44 | ||
@@ -57,7 +57,7 @@ static int gr2d_exit(struct host1x_client *client) | |||
57 | return err; | 57 | return err; |
58 | 58 | ||
59 | host1x_syncpt_free(client->syncpts[0]); | 59 | host1x_syncpt_free(client->syncpts[0]); |
60 | host1x_channel_free(gr2d->channel); | 60 | host1x_channel_put(gr2d->channel); |
61 | 61 | ||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 13f0d1b7cd98..cee2ab645cde 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c | |||
@@ -48,7 +48,7 @@ static int gr3d_init(struct host1x_client *client) | |||
48 | 48 | ||
49 | client->syncpts[0] = host1x_syncpt_request(client->dev, flags); | 49 | client->syncpts[0] = host1x_syncpt_request(client->dev, flags); |
50 | if (!client->syncpts[0]) { | 50 | if (!client->syncpts[0]) { |
51 | host1x_channel_free(gr3d->channel); | 51 | host1x_channel_put(gr3d->channel); |
52 | return -ENOMEM; | 52 | return -ENOMEM; |
53 | } | 53 | } |
54 | 54 | ||
@@ -67,7 +67,7 @@ static int gr3d_exit(struct host1x_client *client) | |||
67 | return err; | 67 | return err; |
68 | 68 | ||
69 | host1x_syncpt_free(client->syncpts[0]); | 69 | host1x_syncpt_free(client->syncpts[0]); |
70 | host1x_channel_free(gr3d->channel); | 70 | host1x_channel_put(gr3d->channel); |
71 | 71 | ||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index cd804e404a11..47cb1aaa58b1 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c | |||
@@ -182,7 +182,7 @@ static int vic_init(struct host1x_client *client) | |||
182 | free_syncpt: | 182 | free_syncpt: |
183 | host1x_syncpt_free(client->syncpts[0]); | 183 | host1x_syncpt_free(client->syncpts[0]); |
184 | free_channel: | 184 | free_channel: |
185 | host1x_channel_free(vic->channel); | 185 | host1x_channel_put(vic->channel); |
186 | detach_device: | 186 | detach_device: |
187 | if (tegra->domain) | 187 | if (tegra->domain) |
188 | iommu_detach_device(tegra->domain, vic->dev); | 188 | iommu_detach_device(tegra->domain, vic->dev); |
@@ -203,7 +203,7 @@ static int vic_exit(struct host1x_client *client) | |||
203 | return err; | 203 | return err; |
204 | 204 | ||
205 | host1x_syncpt_free(client->syncpts[0]); | 205 | host1x_syncpt_free(client->syncpts[0]); |
206 | host1x_channel_free(vic->channel); | 206 | host1x_channel_put(vic->channel); |
207 | 207 | ||
208 | if (vic->domain) { | 208 | if (vic->domain) { |
209 | iommu_detach_device(vic->domain, vic->dev); | 209 | iommu_detach_device(vic->domain, vic->dev); |
diff --git a/drivers/gpu/host1x/channel.c b/drivers/gpu/host1x/channel.c index 8f437d924c10..db9b91d1384c 100644 --- a/drivers/gpu/host1x/channel.c +++ b/drivers/gpu/host1x/channel.c | |||
@@ -24,19 +24,33 @@ | |||
24 | #include "job.h" | 24 | #include "job.h" |
25 | 25 | ||
26 | /* Constructor for the host1x device list */ | 26 | /* Constructor for the host1x device list */ |
27 | int host1x_channel_list_init(struct host1x *host) | 27 | int host1x_channel_list_init(struct host1x_channel_list *chlist, |
28 | unsigned int num_channels) | ||
28 | { | 29 | { |
29 | INIT_LIST_HEAD(&host->chlist.list); | 30 | chlist->channels = kcalloc(num_channels, sizeof(struct host1x_channel), |
30 | mutex_init(&host->chlist_mutex); | 31 | GFP_KERNEL); |
31 | 32 | if (!chlist->channels) | |
32 | if (host->info->nb_channels > BITS_PER_LONG) { | 33 | return -ENOMEM; |
33 | WARN(1, "host1x hardware has more channels than supported by the driver\n"); | 34 | |
34 | return -ENOSYS; | 35 | chlist->allocated_channels = |
36 | kcalloc(BITS_TO_LONGS(num_channels), sizeof(unsigned long), | ||
37 | GFP_KERNEL); | ||
38 | if (!chlist->allocated_channels) { | ||
39 | kfree(chlist->channels); | ||
40 | return -ENOMEM; | ||
35 | } | 41 | } |
36 | 42 | ||
43 | bitmap_zero(chlist->allocated_channels, num_channels); | ||
44 | |||
37 | return 0; | 45 | return 0; |
38 | } | 46 | } |
39 | 47 | ||
48 | void host1x_channel_list_free(struct host1x_channel_list *chlist) | ||
49 | { | ||
50 | kfree(chlist->allocated_channels); | ||
51 | kfree(chlist->channels); | ||
52 | } | ||
53 | |||
40 | int host1x_job_submit(struct host1x_job *job) | 54 | int host1x_job_submit(struct host1x_job *job) |
41 | { | 55 | { |
42 | struct host1x *host = dev_get_drvdata(job->channel->dev->parent); | 56 | struct host1x *host = dev_get_drvdata(job->channel->dev->parent); |
@@ -47,86 +61,107 @@ EXPORT_SYMBOL(host1x_job_submit); | |||
47 | 61 | ||
48 | struct host1x_channel *host1x_channel_get(struct host1x_channel *channel) | 62 | struct host1x_channel *host1x_channel_get(struct host1x_channel *channel) |
49 | { | 63 | { |
50 | int err = 0; | 64 | kref_get(&channel->refcount); |
51 | 65 | ||
52 | mutex_lock(&channel->reflock); | 66 | return channel; |
67 | } | ||
68 | EXPORT_SYMBOL(host1x_channel_get); | ||
53 | 69 | ||
54 | if (channel->refcount == 0) | 70 | /** |
55 | err = host1x_cdma_init(&channel->cdma); | 71 | * host1x_channel_get_index() - Attempt to get channel reference by index |
72 | * @host: Host1x device object | ||
73 | * @index: Index of channel | ||
74 | * | ||
75 | * If channel number @index is currently allocated, increase its refcount | ||
76 | * and return a pointer to it. Otherwise, return NULL. | ||
77 | */ | ||
78 | struct host1x_channel *host1x_channel_get_index(struct host1x *host, | ||
79 | unsigned int index) | ||
80 | { | ||
81 | struct host1x_channel *ch = &host->channel_list.channels[index]; | ||
56 | 82 | ||
57 | if (!err) | 83 | if (!kref_get_unless_zero(&ch->refcount)) |
58 | channel->refcount++; | 84 | return NULL; |
59 | 85 | ||
60 | mutex_unlock(&channel->reflock); | 86 | return ch; |
87 | } | ||
88 | |||
89 | static void release_channel(struct kref *kref) | ||
90 | { | ||
91 | struct host1x_channel *channel = | ||
92 | container_of(kref, struct host1x_channel, refcount); | ||
93 | struct host1x *host = dev_get_drvdata(channel->dev->parent); | ||
94 | struct host1x_channel_list *chlist = &host->channel_list; | ||
95 | |||
96 | host1x_hw_cdma_stop(host, &channel->cdma); | ||
97 | host1x_cdma_deinit(&channel->cdma); | ||
61 | 98 | ||
62 | return err ? NULL : channel; | 99 | clear_bit(channel->id, chlist->allocated_channels); |
63 | } | 100 | } |
64 | EXPORT_SYMBOL(host1x_channel_get); | ||
65 | 101 | ||
66 | void host1x_channel_put(struct host1x_channel *channel) | 102 | void host1x_channel_put(struct host1x_channel *channel) |
67 | { | 103 | { |
68 | mutex_lock(&channel->reflock); | 104 | kref_put(&channel->refcount, release_channel); |
105 | } | ||
106 | EXPORT_SYMBOL(host1x_channel_put); | ||
69 | 107 | ||
70 | if (channel->refcount == 1) { | 108 | static struct host1x_channel *acquire_unused_channel(struct host1x *host) |
71 | struct host1x *host = dev_get_drvdata(channel->dev->parent); | 109 | { |
110 | struct host1x_channel_list *chlist = &host->channel_list; | ||
111 | unsigned int max_channels = host->info->nb_channels; | ||
112 | unsigned int index; | ||
72 | 113 | ||
73 | host1x_hw_cdma_stop(host, &channel->cdma); | 114 | index = find_first_zero_bit(chlist->allocated_channels, max_channels); |
74 | host1x_cdma_deinit(&channel->cdma); | 115 | if (index >= max_channels) { |
116 | dev_err(host->dev, "failed to find free channel\n"); | ||
117 | return NULL; | ||
75 | } | 118 | } |
76 | 119 | ||
77 | channel->refcount--; | 120 | chlist->channels[index].id = index; |
78 | 121 | ||
79 | mutex_unlock(&channel->reflock); | 122 | set_bit(index, chlist->allocated_channels); |
123 | |||
124 | return &chlist->channels[index]; | ||
80 | } | 125 | } |
81 | EXPORT_SYMBOL(host1x_channel_put); | ||
82 | 126 | ||
127 | /** | ||
128 | * host1x_channel_request() - Allocate a channel | ||
129 | * @device: Host1x unit this channel will be used to send commands to | ||
130 | * | ||
131 | * Allocates a new host1x channel for @device. If there are no free channels, | ||
132 | * this will sleep until one becomes available. May return NULL if CDMA | ||
133 | * initialization fails. | ||
134 | */ | ||
83 | struct host1x_channel *host1x_channel_request(struct device *dev) | 135 | struct host1x_channel *host1x_channel_request(struct device *dev) |
84 | { | 136 | { |
85 | struct host1x *host = dev_get_drvdata(dev->parent); | 137 | struct host1x *host = dev_get_drvdata(dev->parent); |
86 | unsigned int max_channels = host->info->nb_channels; | 138 | struct host1x_channel_list *chlist = &host->channel_list; |
87 | struct host1x_channel *channel = NULL; | 139 | struct host1x_channel *channel; |
88 | unsigned long index; | ||
89 | int err; | 140 | int err; |
90 | 141 | ||
91 | mutex_lock(&host->chlist_mutex); | 142 | channel = acquire_unused_channel(host); |
143 | if (!channel) | ||
144 | return NULL; | ||
92 | 145 | ||
93 | index = find_first_zero_bit(&host->allocated_channels, max_channels); | 146 | kref_init(&channel->refcount); |
94 | if (index >= max_channels) | 147 | mutex_init(&channel->submitlock); |
95 | goto fail; | 148 | channel->dev = dev; |
96 | 149 | ||
97 | channel = kzalloc(sizeof(*channel), GFP_KERNEL); | 150 | err = host1x_hw_channel_init(host, channel, channel->id); |
98 | if (!channel) | 151 | if (err < 0) |
99 | goto fail; | 152 | goto fail; |
100 | 153 | ||
101 | err = host1x_hw_channel_init(host, channel, index); | 154 | err = host1x_cdma_init(&channel->cdma); |
102 | if (err < 0) | 155 | if (err < 0) |
103 | goto fail; | 156 | goto fail; |
104 | 157 | ||
105 | /* Link device to host1x_channel */ | ||
106 | channel->dev = dev; | ||
107 | |||
108 | /* Add to channel list */ | ||
109 | list_add_tail(&channel->list, &host->chlist.list); | ||
110 | |||
111 | host->allocated_channels |= BIT(index); | ||
112 | |||
113 | mutex_unlock(&host->chlist_mutex); | ||
114 | return channel; | 158 | return channel; |
115 | 159 | ||
116 | fail: | 160 | fail: |
117 | dev_err(dev, "failed to init channel\n"); | 161 | clear_bit(channel->id, chlist->allocated_channels); |
118 | kfree(channel); | ||
119 | mutex_unlock(&host->chlist_mutex); | ||
120 | return NULL; | ||
121 | } | ||
122 | EXPORT_SYMBOL(host1x_channel_request); | ||
123 | 162 | ||
124 | void host1x_channel_free(struct host1x_channel *channel) | 163 | dev_err(dev, "failed to initialize channel\n"); |
125 | { | ||
126 | struct host1x *host = dev_get_drvdata(channel->dev->parent); | ||
127 | 164 | ||
128 | host->allocated_channels &= ~BIT(channel->id); | 165 | return NULL; |
129 | list_del(&channel->list); | ||
130 | kfree(channel); | ||
131 | } | 166 | } |
132 | EXPORT_SYMBOL(host1x_channel_free); | 167 | EXPORT_SYMBOL(host1x_channel_request); |
diff --git a/drivers/gpu/host1x/channel.h b/drivers/gpu/host1x/channel.h index df767cf90d51..7068e42d42df 100644 --- a/drivers/gpu/host1x/channel.h +++ b/drivers/gpu/host1x/channel.h | |||
@@ -20,17 +20,21 @@ | |||
20 | #define __HOST1X_CHANNEL_H | 20 | #define __HOST1X_CHANNEL_H |
21 | 21 | ||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/kref.h> | ||
23 | 24 | ||
24 | #include "cdma.h" | 25 | #include "cdma.h" |
25 | 26 | ||
26 | struct host1x; | 27 | struct host1x; |
28 | struct host1x_channel; | ||
27 | 29 | ||
28 | struct host1x_channel { | 30 | struct host1x_channel_list { |
29 | struct list_head list; | 31 | struct host1x_channel *channels; |
32 | unsigned long *allocated_channels; | ||
33 | }; | ||
30 | 34 | ||
31 | unsigned int refcount; | 35 | struct host1x_channel { |
36 | struct kref refcount; | ||
32 | unsigned int id; | 37 | unsigned int id; |
33 | struct mutex reflock; | ||
34 | struct mutex submitlock; | 38 | struct mutex submitlock; |
35 | void __iomem *regs; | 39 | void __iomem *regs; |
36 | struct device *dev; | 40 | struct device *dev; |
@@ -38,9 +42,10 @@ struct host1x_channel { | |||
38 | }; | 42 | }; |
39 | 43 | ||
40 | /* channel list operations */ | 44 | /* channel list operations */ |
41 | int host1x_channel_list_init(struct host1x *host); | 45 | int host1x_channel_list_init(struct host1x_channel_list *chlist, |
42 | 46 | unsigned int num_channels); | |
43 | #define host1x_for_each_channel(host, channel) \ | 47 | void host1x_channel_list_free(struct host1x_channel_list *chlist); |
44 | list_for_each_entry(channel, &host->chlist.list, list) | 48 | struct host1x_channel *host1x_channel_get_index(struct host1x *host, |
49 | unsigned int index); | ||
45 | 50 | ||
46 | #endif | 51 | #endif |
diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c index d9330fcc62ad..2aae0e63214c 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c | |||
@@ -43,24 +43,19 @@ void host1x_debug_output(struct output *o, const char *fmt, ...) | |||
43 | o->fn(o->ctx, o->buf, len); | 43 | o->fn(o->ctx, o->buf, len); |
44 | } | 44 | } |
45 | 45 | ||
46 | static int show_channels(struct host1x_channel *ch, void *data, bool show_fifo) | 46 | static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo) |
47 | { | 47 | { |
48 | struct host1x *m = dev_get_drvdata(ch->dev->parent); | 48 | struct host1x *m = dev_get_drvdata(ch->dev->parent); |
49 | struct output *o = data; | 49 | struct output *o = data; |
50 | 50 | ||
51 | mutex_lock(&ch->reflock); | 51 | mutex_lock(&ch->cdma.lock); |
52 | 52 | ||
53 | if (ch->refcount) { | 53 | if (show_fifo) |
54 | mutex_lock(&ch->cdma.lock); | 54 | host1x_hw_show_channel_fifo(m, ch, o); |
55 | 55 | ||
56 | if (show_fifo) | 56 | host1x_hw_show_channel_cdma(m, ch, o); |
57 | host1x_hw_show_channel_fifo(m, ch, o); | ||
58 | 57 | ||
59 | host1x_hw_show_channel_cdma(m, ch, o); | 58 | mutex_unlock(&ch->cdma.lock); |
60 | mutex_unlock(&ch->cdma.lock); | ||
61 | } | ||
62 | |||
63 | mutex_unlock(&ch->reflock); | ||
64 | 59 | ||
65 | return 0; | 60 | return 0; |
66 | } | 61 | } |
@@ -94,28 +89,22 @@ static void show_syncpts(struct host1x *m, struct output *o) | |||
94 | host1x_debug_output(o, "\n"); | 89 | host1x_debug_output(o, "\n"); |
95 | } | 90 | } |
96 | 91 | ||
97 | static void show_all(struct host1x *m, struct output *o) | 92 | static void show_all(struct host1x *m, struct output *o, bool show_fifo) |
98 | { | 93 | { |
99 | struct host1x_channel *ch; | 94 | int i; |
100 | 95 | ||
101 | host1x_hw_show_mlocks(m, o); | 96 | host1x_hw_show_mlocks(m, o); |
102 | show_syncpts(m, o); | 97 | show_syncpts(m, o); |
103 | host1x_debug_output(o, "---- channels ----\n"); | 98 | host1x_debug_output(o, "---- channels ----\n"); |
104 | 99 | ||
105 | host1x_for_each_channel(m, ch) | 100 | for (i = 0; i < m->info->nb_channels; ++i) { |
106 | show_channels(ch, o, true); | 101 | struct host1x_channel *ch = host1x_channel_get_index(m, i); |
107 | } | ||
108 | |||
109 | static void show_all_no_fifo(struct host1x *host1x, struct output *o) | ||
110 | { | ||
111 | struct host1x_channel *ch; | ||
112 | |||
113 | host1x_hw_show_mlocks(host1x, o); | ||
114 | show_syncpts(host1x, o); | ||
115 | host1x_debug_output(o, "---- channels ----\n"); | ||
116 | 102 | ||
117 | host1x_for_each_channel(host1x, ch) | 103 | if (ch) { |
118 | show_channels(ch, o, false); | 104 | show_channel(ch, o, show_fifo); |
105 | host1x_channel_put(ch); | ||
106 | } | ||
107 | } | ||
119 | } | 108 | } |
120 | 109 | ||
121 | static int host1x_debug_show_all(struct seq_file *s, void *unused) | 110 | static int host1x_debug_show_all(struct seq_file *s, void *unused) |
@@ -125,7 +114,7 @@ static int host1x_debug_show_all(struct seq_file *s, void *unused) | |||
125 | .ctx = s | 114 | .ctx = s |
126 | }; | 115 | }; |
127 | 116 | ||
128 | show_all(s->private, &o); | 117 | show_all(s->private, &o, true); |
129 | 118 | ||
130 | return 0; | 119 | return 0; |
131 | } | 120 | } |
@@ -137,7 +126,7 @@ static int host1x_debug_show(struct seq_file *s, void *unused) | |||
137 | .ctx = s | 126 | .ctx = s |
138 | }; | 127 | }; |
139 | 128 | ||
140 | show_all_no_fifo(s->private, &o); | 129 | show_all(s->private, &o, false); |
141 | 130 | ||
142 | return 0; | 131 | return 0; |
143 | } | 132 | } |
@@ -216,7 +205,7 @@ void host1x_debug_dump(struct host1x *host1x) | |||
216 | .fn = write_to_printk | 205 | .fn = write_to_printk |
217 | }; | 206 | }; |
218 | 207 | ||
219 | show_all(host1x, &o); | 208 | show_all(host1x, &o, true); |
220 | } | 209 | } |
221 | 210 | ||
222 | void host1x_debug_dump_syncpts(struct host1x *host1x) | 211 | void host1x_debug_dump_syncpts(struct host1x *host1x) |
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index f05ebb14fa63..5c1c711a21af 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c | |||
@@ -198,7 +198,8 @@ static int host1x_probe(struct platform_device *pdev) | |||
198 | host->iova_end = geometry->aperture_end; | 198 | host->iova_end = geometry->aperture_end; |
199 | } | 199 | } |
200 | 200 | ||
201 | err = host1x_channel_list_init(host); | 201 | err = host1x_channel_list_init(&host->channel_list, |
202 | host->info->nb_channels); | ||
202 | if (err) { | 203 | if (err) { |
203 | dev_err(&pdev->dev, "failed to initialize channel list\n"); | 204 | dev_err(&pdev->dev, "failed to initialize channel list\n"); |
204 | goto fail_detach_device; | 205 | goto fail_detach_device; |
@@ -207,7 +208,7 @@ static int host1x_probe(struct platform_device *pdev) | |||
207 | err = clk_prepare_enable(host->clk); | 208 | err = clk_prepare_enable(host->clk); |
208 | if (err < 0) { | 209 | if (err < 0) { |
209 | dev_err(&pdev->dev, "failed to enable clock\n"); | 210 | dev_err(&pdev->dev, "failed to enable clock\n"); |
210 | goto fail_detach_device; | 211 | goto fail_free_channels; |
211 | } | 212 | } |
212 | 213 | ||
213 | err = reset_control_deassert(host->rst); | 214 | err = reset_control_deassert(host->rst); |
@@ -244,6 +245,8 @@ fail_reset_assert: | |||
244 | reset_control_assert(host->rst); | 245 | reset_control_assert(host->rst); |
245 | fail_unprepare_disable: | 246 | fail_unprepare_disable: |
246 | clk_disable_unprepare(host->clk); | 247 | clk_disable_unprepare(host->clk); |
248 | fail_free_channels: | ||
249 | host1x_channel_list_free(&host->channel_list); | ||
247 | fail_detach_device: | 250 | fail_detach_device: |
248 | if (host->domain) { | 251 | if (host->domain) { |
249 | put_iova_domain(&host->iova); | 252 | put_iova_domain(&host->iova); |
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 229d08b6a45e..ffdbc15b749b 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h | |||
@@ -129,10 +129,8 @@ struct host1x { | |||
129 | struct host1x_syncpt *nop_sp; | 129 | struct host1x_syncpt *nop_sp; |
130 | 130 | ||
131 | struct mutex syncpt_mutex; | 131 | struct mutex syncpt_mutex; |
132 | struct mutex chlist_mutex; | 132 | |
133 | struct host1x_channel chlist; | 133 | struct host1x_channel_list channel_list; |
134 | unsigned long allocated_channels; | ||
135 | unsigned int num_allocated_channels; | ||
136 | 134 | ||
137 | struct dentry *debugfs; | 135 | struct dentry *debugfs; |
138 | 136 | ||
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c index 5e8df78b7acd..8447a56c41ca 100644 --- a/drivers/gpu/host1x/hw/channel_hw.c +++ b/drivers/gpu/host1x/hw/channel_hw.c | |||
@@ -181,10 +181,6 @@ error: | |||
181 | static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev, | 181 | static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev, |
182 | unsigned int index) | 182 | unsigned int index) |
183 | { | 183 | { |
184 | ch->id = index; | ||
185 | mutex_init(&ch->reflock); | ||
186 | mutex_init(&ch->submitlock); | ||
187 | |||
188 | ch->regs = dev->regs + index * HOST1X_CHANNEL_SIZE; | 184 | ch->regs = dev->regs + index * HOST1X_CHANNEL_SIZE; |
189 | return 0; | 185 | return 0; |
190 | } | 186 | } |
diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 476da0e06bb2..630b1a98ab58 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h | |||
@@ -172,7 +172,6 @@ struct host1x_channel; | |||
172 | struct host1x_job; | 172 | struct host1x_job; |
173 | 173 | ||
174 | struct host1x_channel *host1x_channel_request(struct device *dev); | 174 | struct host1x_channel *host1x_channel_request(struct device *dev); |
175 | void host1x_channel_free(struct host1x_channel *channel); | ||
176 | struct host1x_channel *host1x_channel_get(struct host1x_channel *channel); | 175 | struct host1x_channel *host1x_channel_get(struct host1x_channel *channel); |
177 | void host1x_channel_put(struct host1x_channel *channel); | 176 | void host1x_channel_put(struct host1x_channel *channel); |
178 | int host1x_job_submit(struct host1x_job *job); | 177 | int host1x_job_submit(struct host1x_job *job); |