aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/talitos.c
diff options
context:
space:
mode:
authorKim Phillips <kim.phillips@freescale.com>2009-08-12 21:50:38 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2009-08-12 21:50:38 -0400
commit4b992628812137e30cda3510510cf3c052345b30 (patch)
tree97797e65fc0c3e1b7ed51a5b250d9c44213b3ecb /drivers/crypto/talitos.c
parente41256f139b9148cfa12d2d057fec39e3d181ff0 (diff)
crypto: talitos - align locks on cache lines
align channel access locks onto separate cache lines (for performance reasons). This is done by placing per-channel variables into their own private struct, and using the cacheline_aligned attribute within that struct. Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/talitos.c')
-rw-r--r--drivers/crypto/talitos.c141
1 files changed, 58 insertions, 83 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index b1a651c61829..5013a2dd47ed 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -86,6 +86,25 @@ struct talitos_request {
86 void *context; 86 void *context;
87}; 87};
88 88
89/* per-channel fifo management */
90struct talitos_channel {
91 /* request fifo */
92 struct talitos_request *fifo;
93
94 /* number of requests pending in channel h/w fifo */
95 atomic_t submit_count ____cacheline_aligned;
96
97 /* request submission (head) lock */
98 spinlock_t head_lock ____cacheline_aligned;
99 /* index to next free descriptor request */
100 int head;
101
102 /* request release (tail) lock */
103 spinlock_t tail_lock ____cacheline_aligned;
104 /* index to next in-progress/done descriptor request */
105 int tail;
106};
107
89struct talitos_private { 108struct talitos_private {
90 struct device *dev; 109 struct device *dev;
91 struct of_device *ofdev; 110 struct of_device *ofdev;
@@ -101,15 +120,6 @@ struct talitos_private {
101 /* SEC Compatibility info */ 120 /* SEC Compatibility info */
102 unsigned long features; 121 unsigned long features;
103 122
104 /* next channel to be assigned next incoming descriptor */
105 atomic_t last_chan;
106
107 /* per-channel number of requests pending in channel h/w fifo */
108 atomic_t *submit_count;
109
110 /* per-channel request fifo */
111 struct talitos_request **fifo;
112
113 /* 123 /*
114 * length of the request fifo 124 * length of the request fifo
115 * fifo_len is chfifo_len rounded up to next power of 2 125 * fifo_len is chfifo_len rounded up to next power of 2
@@ -117,15 +127,10 @@ struct talitos_private {
117 */ 127 */
118 unsigned int fifo_len; 128 unsigned int fifo_len;
119 129
120 /* per-channel index to next free descriptor request */ 130 struct talitos_channel *chan;
121 int *head;
122
123 /* per-channel index to next in-progress/done descriptor request */
124 int *tail;
125 131
126 /* per-channel request submission (head) and release (tail) locks */ 132 /* next channel to be assigned next incoming descriptor */
127 spinlock_t *head_lock; 133 atomic_t last_chan ____cacheline_aligned;
128 spinlock_t *tail_lock;
129 134
130 /* request callback tasklet */ 135 /* request callback tasklet */
131 struct tasklet_struct done_task; 136 struct tasklet_struct done_task;
@@ -282,16 +287,16 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
282 /* emulate SEC's round-robin channel fifo polling scheme */ 287 /* emulate SEC's round-robin channel fifo polling scheme */
283 ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1); 288 ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1);
284 289
285 spin_lock_irqsave(&priv->head_lock[ch], flags); 290 spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
286 291
287 if (!atomic_inc_not_zero(&priv->submit_count[ch])) { 292 if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
288 /* h/w fifo is full */ 293 /* h/w fifo is full */
289 spin_unlock_irqrestore(&priv->head_lock[ch], flags); 294 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
290 return -EAGAIN; 295 return -EAGAIN;
291 } 296 }
292 297
293 head = priv->head[ch]; 298 head = priv->chan[ch].head;
294 request = &priv->fifo[ch][head]; 299 request = &priv->chan[ch].fifo[head];
295 300
296 /* map descriptor and save caller data */ 301 /* map descriptor and save caller data */
297 request->dma_desc = dma_map_single(dev, desc, sizeof(*desc), 302 request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
@@ -300,7 +305,7 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
300 request->context = context; 305 request->context = context;
301 306
302 /* increment fifo head */ 307 /* increment fifo head */
303 priv->head[ch] = (priv->head[ch] + 1) & (priv->fifo_len - 1); 308 priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
304 309
305 smp_wmb(); 310 smp_wmb();
306 request->desc = desc; 311 request->desc = desc;
@@ -309,7 +314,7 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
309 wmb(); 314 wmb();
310 out_be32(priv->reg + TALITOS_FF_LO(ch), request->dma_desc); 315 out_be32(priv->reg + TALITOS_FF_LO(ch), request->dma_desc);
311 316
312 spin_unlock_irqrestore(&priv->head_lock[ch], flags); 317 spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
313 318
314 return -EINPROGRESS; 319 return -EINPROGRESS;
315} 320}
@@ -324,11 +329,11 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
324 unsigned long flags; 329 unsigned long flags;
325 int tail, status; 330 int tail, status;
326 331
327 spin_lock_irqsave(&priv->tail_lock[ch], flags); 332 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
328 333
329 tail = priv->tail[ch]; 334 tail = priv->chan[ch].tail;
330 while (priv->fifo[ch][tail].desc) { 335 while (priv->chan[ch].fifo[tail].desc) {
331 request = &priv->fifo[ch][tail]; 336 request = &priv->chan[ch].fifo[tail];
332 337
333 /* descriptors with their done bits set don't get the error */ 338 /* descriptors with their done bits set don't get the error */
334 rmb(); 339 rmb();
@@ -354,22 +359,22 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
354 request->desc = NULL; 359 request->desc = NULL;
355 360
356 /* increment fifo tail */ 361 /* increment fifo tail */
357 priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1); 362 priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
358 363
359 spin_unlock_irqrestore(&priv->tail_lock[ch], flags); 364 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
360 365
361 atomic_dec(&priv->submit_count[ch]); 366 atomic_dec(&priv->chan[ch].submit_count);
362 367
363 saved_req.callback(dev, saved_req.desc, saved_req.context, 368 saved_req.callback(dev, saved_req.desc, saved_req.context,
364 status); 369 status);
365 /* channel may resume processing in single desc error case */ 370 /* channel may resume processing in single desc error case */
366 if (error && !reset_ch && status == error) 371 if (error && !reset_ch && status == error)
367 return; 372 return;
368 spin_lock_irqsave(&priv->tail_lock[ch], flags); 373 spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
369 tail = priv->tail[ch]; 374 tail = priv->chan[ch].tail;
370 } 375 }
371 376
372 spin_unlock_irqrestore(&priv->tail_lock[ch], flags); 377 spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
373} 378}
374 379
375/* 380/*
@@ -397,20 +402,20 @@ static void talitos_done(unsigned long data)
397static struct talitos_desc *current_desc(struct device *dev, int ch) 402static struct talitos_desc *current_desc(struct device *dev, int ch)
398{ 403{
399 struct talitos_private *priv = dev_get_drvdata(dev); 404 struct talitos_private *priv = dev_get_drvdata(dev);
400 int tail = priv->tail[ch]; 405 int tail = priv->chan[ch].tail;
401 dma_addr_t cur_desc; 406 dma_addr_t cur_desc;
402 407
403 cur_desc = in_be32(priv->reg + TALITOS_CDPR_LO(ch)); 408 cur_desc = in_be32(priv->reg + TALITOS_CDPR_LO(ch));
404 409
405 while (priv->fifo[ch][tail].dma_desc != cur_desc) { 410 while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) {
406 tail = (tail + 1) & (priv->fifo_len - 1); 411 tail = (tail + 1) & (priv->fifo_len - 1);
407 if (tail == priv->tail[ch]) { 412 if (tail == priv->chan[ch].tail) {
408 dev_err(dev, "couldn't locate current descriptor\n"); 413 dev_err(dev, "couldn't locate current descriptor\n");
409 return NULL; 414 return NULL;
410 } 415 }
411 } 416 }
412 417
413 return priv->fifo[ch][tail].desc; 418 return priv->chan[ch].fifo[tail].desc;
414} 419}
415 420
416/* 421/*
@@ -1740,17 +1745,11 @@ static int talitos_remove(struct of_device *ofdev)
1740 if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 1745 if (hw_supports(dev, DESC_HDR_SEL0_RNG))
1741 talitos_unregister_rng(dev); 1746 talitos_unregister_rng(dev);
1742 1747
1743 kfree(priv->submit_count); 1748 for (i = 0; i < priv->num_channels; i++)
1744 kfree(priv->tail); 1749 if (priv->chan[i].fifo)
1745 kfree(priv->head); 1750 kfree(priv->chan[i].fifo);
1746
1747 if (priv->fifo)
1748 for (i = 0; i < priv->num_channels; i++)
1749 kfree(priv->fifo[i]);
1750 1751
1751 kfree(priv->fifo); 1752 kfree(priv->chan);
1752 kfree(priv->head_lock);
1753 kfree(priv->tail_lock);
1754 1753
1755 if (priv->irq != NO_IRQ) { 1754 if (priv->irq != NO_IRQ) {
1756 free_irq(priv->irq, dev); 1755 free_irq(priv->irq, dev);
@@ -1870,58 +1869,34 @@ static int talitos_probe(struct of_device *ofdev,
1870 if (of_device_is_compatible(np, "fsl,sec2.1")) 1869 if (of_device_is_compatible(np, "fsl,sec2.1"))
1871 priv->features |= TALITOS_FTR_HW_AUTH_CHECK; 1870 priv->features |= TALITOS_FTR_HW_AUTH_CHECK;
1872 1871
1873 priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, 1872 priv->chan = kzalloc(sizeof(struct talitos_channel) *
1874 GFP_KERNEL); 1873 priv->num_channels, GFP_KERNEL);
1875 priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, 1874 if (!priv->chan) {
1876 GFP_KERNEL); 1875 dev_err(dev, "failed to allocate channel management space\n");
1877 if (!priv->head_lock || !priv->tail_lock) {
1878 dev_err(dev, "failed to allocate fifo locks\n");
1879 err = -ENOMEM; 1876 err = -ENOMEM;
1880 goto err_out; 1877 goto err_out;
1881 } 1878 }
1882 1879
1883 for (i = 0; i < priv->num_channels; i++) { 1880 for (i = 0; i < priv->num_channels; i++) {
1884 spin_lock_init(&priv->head_lock[i]); 1881 spin_lock_init(&priv->chan[i].head_lock);
1885 spin_lock_init(&priv->tail_lock[i]); 1882 spin_lock_init(&priv->chan[i].tail_lock);
1886 }
1887
1888 priv->fifo = kmalloc(sizeof(struct talitos_request *) *
1889 priv->num_channels, GFP_KERNEL);
1890 if (!priv->fifo) {
1891 dev_err(dev, "failed to allocate request fifo\n");
1892 err = -ENOMEM;
1893 goto err_out;
1894 } 1883 }
1895 1884
1896 priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 1885 priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
1897 1886
1898 for (i = 0; i < priv->num_channels; i++) { 1887 for (i = 0; i < priv->num_channels; i++) {
1899 priv->fifo[i] = kzalloc(sizeof(struct talitos_request) * 1888 priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
1900 priv->fifo_len, GFP_KERNEL); 1889 priv->fifo_len, GFP_KERNEL);
1901 if (!priv->fifo[i]) { 1890 if (!priv->chan[i].fifo) {
1902 dev_err(dev, "failed to allocate request fifo %d\n", i); 1891 dev_err(dev, "failed to allocate request fifo %d\n", i);
1903 err = -ENOMEM; 1892 err = -ENOMEM;
1904 goto err_out; 1893 goto err_out;
1905 } 1894 }
1906 } 1895 }
1907 1896
1908 priv->submit_count = kmalloc(sizeof(atomic_t) * priv->num_channels,
1909 GFP_KERNEL);
1910 if (!priv->submit_count) {
1911 dev_err(dev, "failed to allocate fifo submit count space\n");
1912 err = -ENOMEM;
1913 goto err_out;
1914 }
1915 for (i = 0; i < priv->num_channels; i++) 1897 for (i = 0; i < priv->num_channels; i++)
1916 atomic_set(&priv->submit_count[i], -(priv->chfifo_len - 1)); 1898 atomic_set(&priv->chan[i].submit_count,
1917 1899 -(priv->chfifo_len - 1));
1918 priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
1919 priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
1920 if (!priv->head || !priv->tail) {
1921 dev_err(dev, "failed to allocate request index space\n");
1922 err = -ENOMEM;
1923 goto err_out;
1924 }
1925 1900
1926 /* reset and initialize the h/w */ 1901 /* reset and initialize the h/w */
1927 err = init_device(dev); 1902 err = init_device(dev);