aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing/intel_th
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2016-03-10 11:21:14 -0500
committerAlexander Shishkin <alexander.shishkin@linux.intel.com>2016-04-08 09:11:59 -0400
commita45ff6ed742cdfdb3cdebee83d19ab1c00d91fcc (patch)
treef87e814284007aab0e97cc61d9c9209532b8bc50 /drivers/hwtracing/intel_th
parentf18a9531f6da9aba2920a3a5f166dba5a20592a0 (diff)
intel_th: msu: Serialize enabling/disabling
In order to guarantee that readers don't race with trace enabling, both should happen under the same mutex. Having two mutexes seems like an overkill, considering that because of the above, they'll have to be acquired together, around trace enabling and char device opening. This patch makes both buffer accesses and readers serialize on msc::buf_mutex and makes sure that 'enabled' flag accesses are also serialized on it. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Reviewed-by: Laurent Fert <laurent.fert@intel.com>
Diffstat (limited to 'drivers/hwtracing/intel_th')
-rw-r--r--drivers/hwtracing/intel_th/msu.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
index 25af2146866c..ee153067e136 100644
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -122,7 +122,6 @@ struct msc {
122 atomic_t mmap_count; 122 atomic_t mmap_count;
123 struct mutex buf_mutex; 123 struct mutex buf_mutex;
124 124
125 struct mutex iter_mutex;
126 struct list_head iter_list; 125 struct list_head iter_list;
127 126
128 /* config */ 127 /* config */
@@ -257,23 +256,37 @@ static struct msc_iter *msc_iter_install(struct msc *msc)
257 256
258 iter = kzalloc(sizeof(*iter), GFP_KERNEL); 257 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
259 if (!iter) 258 if (!iter)
260 return NULL; 259 return ERR_PTR(-ENOMEM);
260
261 mutex_lock(&msc->buf_mutex);
262
263 /*
264 * Reading and tracing are mutually exclusive; if msc is
265 * enabled, open() will fail; otherwise existing readers
266 * will prevent enabling the msc and the rest of fops don't
267 * need to worry about it.
268 */
269 if (msc->enabled) {
270 kfree(iter);
271 iter = ERR_PTR(-EBUSY);
272 goto unlock;
273 }
261 274
262 msc_iter_init(iter); 275 msc_iter_init(iter);
263 iter->msc = msc; 276 iter->msc = msc;
264 277
265 mutex_lock(&msc->iter_mutex);
266 list_add_tail(&iter->entry, &msc->iter_list); 278 list_add_tail(&iter->entry, &msc->iter_list);
267 mutex_unlock(&msc->iter_mutex); 279unlock:
280 mutex_unlock(&msc->buf_mutex);
268 281
269 return iter; 282 return iter;
270} 283}
271 284
272static void msc_iter_remove(struct msc_iter *iter, struct msc *msc) 285static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
273{ 286{
274 mutex_lock(&msc->iter_mutex); 287 mutex_lock(&msc->buf_mutex);
275 list_del(&iter->entry); 288 list_del(&iter->entry);
276 mutex_unlock(&msc->iter_mutex); 289 mutex_unlock(&msc->buf_mutex);
277 290
278 kfree(iter); 291 kfree(iter);
279} 292}
@@ -454,7 +467,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
454{ 467{
455 struct msc_window *win; 468 struct msc_window *win;
456 469
457 mutex_lock(&msc->buf_mutex);
458 list_for_each_entry(win, &msc->win_list, entry) { 470 list_for_each_entry(win, &msc->win_list, entry) {
459 unsigned int blk; 471 unsigned int blk;
460 size_t hw_sz = sizeof(struct msc_block_desc) - 472 size_t hw_sz = sizeof(struct msc_block_desc) -
@@ -466,7 +478,6 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
466 memset(&bdesc->hw_tag, 0, hw_sz); 478 memset(&bdesc->hw_tag, 0, hw_sz);
467 } 479 }
468 } 480 }
469 mutex_unlock(&msc->buf_mutex);
470} 481}
471 482
472/** 483/**
@@ -474,12 +485,15 @@ static void msc_buffer_clear_hw_header(struct msc *msc)
474 * @msc: the MSC device to configure 485 * @msc: the MSC device to configure
475 * 486 *
476 * Program storage mode, wrapping, burst length and trace buffer address 487 * Program storage mode, wrapping, burst length and trace buffer address
477 * into a given MSC. If msc::enabled is set, enable the trace, too. 488 * into a given MSC. Then, enable tracing and set msc::enabled.
489 * The latter is serialized on msc::buf_mutex, so make sure to hold it.
478 */ 490 */
479static int msc_configure(struct msc *msc) 491static int msc_configure(struct msc *msc)
480{ 492{
481 u32 reg; 493 u32 reg;
482 494
495 lockdep_assert_held(&msc->buf_mutex);
496
483 if (msc->mode > MSC_MODE_MULTI) 497 if (msc->mode > MSC_MODE_MULTI)
484 return -ENOTSUPP; 498 return -ENOTSUPP;
485 499
@@ -497,21 +511,19 @@ static int msc_configure(struct msc *msc)
497 reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL); 511 reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
498 reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD); 512 reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
499 513
514 reg |= MSC_EN;
500 reg |= msc->mode << __ffs(MSC_MODE); 515 reg |= msc->mode << __ffs(MSC_MODE);
501 reg |= msc->burst_len << __ffs(MSC_LEN); 516 reg |= msc->burst_len << __ffs(MSC_LEN);
502 /*if (msc->mode == MSC_MODE_MULTI) 517
503 reg |= MSC_RD_HDR_OVRD; */
504 if (msc->wrap) 518 if (msc->wrap)
505 reg |= MSC_WRAPEN; 519 reg |= MSC_WRAPEN;
506 if (msc->enabled)
507 reg |= MSC_EN;
508 520
509 iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL); 521 iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
510 522
511 if (msc->enabled) { 523 msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
512 msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI; 524 intel_th_trace_enable(msc->thdev);
513 intel_th_trace_enable(msc->thdev); 525 msc->enabled = 1;
514 } 526
515 527
516 return 0; 528 return 0;
517} 529}
@@ -521,15 +533,14 @@ static int msc_configure(struct msc *msc)
521 * @msc: MSC device to disable 533 * @msc: MSC device to disable
522 * 534 *
523 * If @msc is enabled, disable tracing on the switch and then disable MSC 535 * If @msc is enabled, disable tracing on the switch and then disable MSC
524 * storage. 536 * storage. Caller must hold msc::buf_mutex.
525 */ 537 */
526static void msc_disable(struct msc *msc) 538static void msc_disable(struct msc *msc)
527{ 539{
528 unsigned long count; 540 unsigned long count;
529 u32 reg; 541 u32 reg;
530 542
531 if (!msc->enabled) 543 lockdep_assert_held(&msc->buf_mutex);
532 return;
533 544
534 intel_th_trace_disable(msc->thdev); 545 intel_th_trace_disable(msc->thdev);
535 546
@@ -569,33 +580,35 @@ static void msc_disable(struct msc *msc)
569static int intel_th_msc_activate(struct intel_th_device *thdev) 580static int intel_th_msc_activate(struct intel_th_device *thdev)
570{ 581{
571 struct msc *msc = dev_get_drvdata(&thdev->dev); 582 struct msc *msc = dev_get_drvdata(&thdev->dev);
572 int ret = 0; 583 int ret = -EBUSY;
573 584
574 if (!atomic_inc_unless_negative(&msc->user_count)) 585 if (!atomic_inc_unless_negative(&msc->user_count))
575 return -ENODEV; 586 return -ENODEV;
576 587
577 mutex_lock(&msc->iter_mutex); 588 mutex_lock(&msc->buf_mutex);
578 if (!list_empty(&msc->iter_list))
579 ret = -EBUSY;
580 mutex_unlock(&msc->iter_mutex);
581 589
582 if (ret) { 590 /* if there are readers, refuse */
583 atomic_dec(&msc->user_count); 591 if (list_empty(&msc->iter_list))
584 return ret; 592 ret = msc_configure(msc);
585 }
586 593
587 msc->enabled = 1; 594 mutex_unlock(&msc->buf_mutex);
595
596 if (ret)
597 atomic_dec(&msc->user_count);
588 598
589 return msc_configure(msc); 599 return ret;
590} 600}
591 601
592static void intel_th_msc_deactivate(struct intel_th_device *thdev) 602static void intel_th_msc_deactivate(struct intel_th_device *thdev)
593{ 603{
594 struct msc *msc = dev_get_drvdata(&thdev->dev); 604 struct msc *msc = dev_get_drvdata(&thdev->dev);
595 605
596 msc_disable(msc); 606 mutex_lock(&msc->buf_mutex);
597 607 if (msc->enabled) {
598 atomic_dec(&msc->user_count); 608 msc_disable(msc);
609 atomic_dec(&msc->user_count);
610 }
611 mutex_unlock(&msc->buf_mutex);
599} 612}
600 613
601/** 614/**
@@ -1035,8 +1048,8 @@ static int intel_th_msc_open(struct inode *inode, struct file *file)
1035 return -EPERM; 1048 return -EPERM;
1036 1049
1037 iter = msc_iter_install(msc); 1050 iter = msc_iter_install(msc);
1038 if (!iter) 1051 if (IS_ERR(iter))
1039 return -ENOMEM; 1052 return PTR_ERR(iter);
1040 1053
1041 file->private_data = iter; 1054 file->private_data = iter;
1042 1055
@@ -1101,11 +1114,6 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
1101 if (!atomic_inc_unless_negative(&msc->user_count)) 1114 if (!atomic_inc_unless_negative(&msc->user_count))
1102 return 0; 1115 return 0;
1103 1116
1104 if (msc->enabled) {
1105 ret = -EBUSY;
1106 goto put_count;
1107 }
1108
1109 if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap) 1117 if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
1110 size = msc->single_sz; 1118 size = msc->single_sz;
1111 else 1119 else
@@ -1254,8 +1262,6 @@ static int intel_th_msc_init(struct msc *msc)
1254 msc->mode = MSC_MODE_MULTI; 1262 msc->mode = MSC_MODE_MULTI;
1255 mutex_init(&msc->buf_mutex); 1263 mutex_init(&msc->buf_mutex);
1256 INIT_LIST_HEAD(&msc->win_list); 1264 INIT_LIST_HEAD(&msc->win_list);
1257
1258 mutex_init(&msc->iter_mutex);
1259 INIT_LIST_HEAD(&msc->iter_list); 1265 INIT_LIST_HEAD(&msc->iter_list);
1260 1266
1261 msc->burst_len = 1267 msc->burst_len =