aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwspinlock/omap_hwspinlock.c
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2011-09-05 10:30:34 -0400
committerOhad Ben-Cohen <ohad@wizery.com>2011-09-21 12:45:32 -0400
commitc97f6dd0fe21dfd658c59c144a1b7fd5d8db04ac (patch)
tree6cc0cb7fa7072aa62375a558a732b837703829a6 /drivers/hwspinlock/omap_hwspinlock.c
parente467b6421435f467e274d4f25d62900e1e0e4286 (diff)
hwspinlock/omap: simplify allocation scheme
Instead of allocating every hwspinlock separately, allocate them all in one shot. This both simplifies the driver and helps achieving better slab utilization. Reported-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Diffstat (limited to 'drivers/hwspinlock/omap_hwspinlock.c')
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c51
1 files changed, 17 insertions, 34 deletions
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 1d19fe9324a4..d0583480fe33 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -52,6 +52,7 @@ struct omap_hwspinlock {
52struct omap_hwspinlock_state { 52struct omap_hwspinlock_state {
53 int num_locks; /* Total number of locks in system */ 53 int num_locks; /* Total number of locks in system */
54 void __iomem *io_base; /* Mapped base address */ 54 void __iomem *io_base; /* Mapped base address */
55 struct omap_hwspinlock lock[0]; /* Array of 'num_locks' locks */
55}; 56};
56 57
57static int omap_hwspinlock_trylock(struct hwspinlock *lock) 58static int omap_hwspinlock_trylock(struct hwspinlock *lock)
@@ -95,7 +96,6 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
95{ 96{
96 struct omap_hwspinlock *omap_lock; 97 struct omap_hwspinlock *omap_lock;
97 struct omap_hwspinlock_state *state; 98 struct omap_hwspinlock_state *state;
98 struct hwspinlock *lock;
99 struct resource *res; 99 struct resource *res;
100 void __iomem *io_base; 100 void __iomem *io_base;
101 int i, ret; 101 int i, ret;
@@ -104,15 +104,9 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
104 if (!res) 104 if (!res)
105 return -ENODEV; 105 return -ENODEV;
106 106
107 state = kzalloc(sizeof(*state), GFP_KERNEL);
108 if (!state)
109 return -ENOMEM;
110
111 io_base = ioremap(res->start, resource_size(res)); 107 io_base = ioremap(res->start, resource_size(res));
112 if (!io_base) { 108 if (!io_base)
113 ret = -ENOMEM; 109 return -ENOMEM;
114 goto free_state;
115 }
116 110
117 /* Determine number of locks */ 111 /* Determine number of locks */
118 i = readl(io_base + SYSSTATUS_OFFSET); 112 i = readl(io_base + SYSSTATUS_OFFSET);
@@ -124,7 +118,15 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
124 goto iounmap_base; 118 goto iounmap_base;
125 } 119 }
126 120
127 state->num_locks = i * 32; 121 i *= 32; /* actual number of locks in this device */
122
123 state = kzalloc(sizeof(*state) + i * sizeof(*omap_lock), GFP_KERNEL);
124 if (!state) {
125 ret = -ENOMEM;
126 goto iounmap_base;
127 }
128
129 state->num_locks = i;
128 state->io_base = io_base; 130 state->io_base = io_base;
129 131
130 platform_set_drvdata(pdev, state); 132 platform_set_drvdata(pdev, state);
@@ -136,11 +138,7 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
136 pm_runtime_enable(&pdev->dev); 138 pm_runtime_enable(&pdev->dev);
137 139
138 for (i = 0; i < state->num_locks; i++) { 140 for (i = 0; i < state->num_locks; i++) {
139 omap_lock = kzalloc(sizeof(*omap_lock), GFP_KERNEL); 141 omap_lock = &state->lock[i];
140 if (!omap_lock) {
141 ret = -ENOMEM;
142 goto free_locks;
143 }
144 142
145 omap_lock->lock.dev = &pdev->dev; 143 omap_lock->lock.dev = &pdev->dev;
146 omap_lock->lock.id = i; 144 omap_lock->lock.id = i;
@@ -148,30 +146,19 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
148 omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i; 146 omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
149 147
150 ret = hwspin_lock_register(&omap_lock->lock); 148 ret = hwspin_lock_register(&omap_lock->lock);
151 if (ret) { 149 if (ret)
152 kfree(omap_lock);
153 goto free_locks; 150 goto free_locks;
154 }
155 } 151 }
156 152
157 return 0; 153 return 0;
158 154
159free_locks: 155free_locks:
160 while (--i >= 0) { 156 while (--i >= 0)
161 lock = hwspin_lock_unregister(i); 157 hwspin_lock_unregister(i);
162 /* this should't happen, but let's give our best effort */
163 if (!lock) {
164 dev_err(&pdev->dev, "%s: cleanups failed\n", __func__);
165 continue;
166 }
167 omap_lock = to_omap_hwspinlock(lock);
168 kfree(omap_lock);
169 }
170 pm_runtime_disable(&pdev->dev); 158 pm_runtime_disable(&pdev->dev);
159 kfree(state);
171iounmap_base: 160iounmap_base:
172 iounmap(io_base); 161 iounmap(io_base);
173free_state:
174 kfree(state);
175 return ret; 162 return ret;
176} 163}
177 164
@@ -179,7 +166,6 @@ static int omap_hwspinlock_remove(struct platform_device *pdev)
179{ 166{
180 struct omap_hwspinlock_state *state = platform_get_drvdata(pdev); 167 struct omap_hwspinlock_state *state = platform_get_drvdata(pdev);
181 struct hwspinlock *lock; 168 struct hwspinlock *lock;
182 struct omap_hwspinlock *omap_lock;
183 int i; 169 int i;
184 170
185 for (i = 0; i < state->num_locks; i++) { 171 for (i = 0; i < state->num_locks; i++) {
@@ -190,9 +176,6 @@ static int omap_hwspinlock_remove(struct platform_device *pdev)
190 dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i); 176 dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i);
191 return -EBUSY; 177 return -EBUSY;
192 } 178 }
193
194 omap_lock = to_omap_hwspinlock(lock);
195 kfree(omap_lock);
196 } 179 }
197 180
198 pm_runtime_disable(&pdev->dev); 181 pm_runtime_disable(&pdev->dev);