diff options
author | Philip J Kelleher <pjk1939@linux.vnet.ibm.com> | 2013-06-18 15:38:26 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-06-19 07:52:09 -0400 |
commit | 31a70bb4440c963e69ce210389d8119c70b5c39d (patch) | |
tree | 70bb10af0da9ad240fef12bcd44968142d4bb202 | |
parent | 0ab4743ebc18c23bddf3e288cfc6221ec71533ac (diff) |
rsxx: Fixes soft-lockup issues during DMAs.
The workqueue mechanism has been reworked to prevent soft
lockup issues from occuring by adding in mutex sychronization.
Signed-off-by: Philip J Kelleher <pjk1939@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/rsxx/dma.c | 35 | ||||
-rw-r--r-- | drivers/block/rsxx/rsxx_priv.h | 1 |
2 files changed, 28 insertions, 8 deletions
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index 213e40e4bd92..b485a65b8de1 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c | |||
@@ -381,15 +381,13 @@ static void dma_engine_stalled(unsigned long data) | |||
381 | } | 381 | } |
382 | } | 382 | } |
383 | 383 | ||
384 | static void rsxx_issue_dmas(struct work_struct *work) | 384 | static void rsxx_issue_dmas(struct rsxx_dma_ctrl *ctrl) |
385 | { | 385 | { |
386 | struct rsxx_dma_ctrl *ctrl; | ||
387 | struct rsxx_dma *dma; | 386 | struct rsxx_dma *dma; |
388 | int tag; | 387 | int tag; |
389 | int cmds_pending = 0; | 388 | int cmds_pending = 0; |
390 | struct hw_cmd *hw_cmd_buf; | 389 | struct hw_cmd *hw_cmd_buf; |
391 | 390 | ||
392 | ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work); | ||
393 | hw_cmd_buf = ctrl->cmd.buf; | 391 | hw_cmd_buf = ctrl->cmd.buf; |
394 | 392 | ||
395 | if (unlikely(ctrl->card->halt) || | 393 | if (unlikely(ctrl->card->halt) || |
@@ -469,9 +467,8 @@ static void rsxx_issue_dmas(struct work_struct *work) | |||
469 | } | 467 | } |
470 | } | 468 | } |
471 | 469 | ||
472 | static void rsxx_dma_done(struct work_struct *work) | 470 | static void rsxx_dma_done(struct rsxx_dma_ctrl *ctrl) |
473 | { | 471 | { |
474 | struct rsxx_dma_ctrl *ctrl; | ||
475 | struct rsxx_dma *dma; | 472 | struct rsxx_dma *dma; |
476 | unsigned long flags; | 473 | unsigned long flags; |
477 | u16 count; | 474 | u16 count; |
@@ -479,7 +476,6 @@ static void rsxx_dma_done(struct work_struct *work) | |||
479 | u8 tag; | 476 | u8 tag; |
480 | struct hw_status *hw_st_buf; | 477 | struct hw_status *hw_st_buf; |
481 | 478 | ||
482 | ctrl = container_of(work, struct rsxx_dma_ctrl, dma_done_work); | ||
483 | hw_st_buf = ctrl->status.buf; | 479 | hw_st_buf = ctrl->status.buf; |
484 | 480 | ||
485 | if (unlikely(ctrl->card->halt) || | 481 | if (unlikely(ctrl->card->halt) || |
@@ -555,6 +551,28 @@ static void rsxx_dma_done(struct work_struct *work) | |||
555 | spin_unlock_bh(&ctrl->queue_lock); | 551 | spin_unlock_bh(&ctrl->queue_lock); |
556 | } | 552 | } |
557 | 553 | ||
554 | static void rsxx_schedule_issue(struct work_struct *work) | ||
555 | { | ||
556 | struct rsxx_dma_ctrl *ctrl; | ||
557 | |||
558 | ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work); | ||
559 | |||
560 | mutex_lock(&ctrl->work_lock); | ||
561 | rsxx_issue_dmas(ctrl); | ||
562 | mutex_unlock(&ctrl->work_lock); | ||
563 | } | ||
564 | |||
565 | static void rsxx_schedule_done(struct work_struct *work) | ||
566 | { | ||
567 | struct rsxx_dma_ctrl *ctrl; | ||
568 | |||
569 | ctrl = container_of(work, struct rsxx_dma_ctrl, dma_done_work); | ||
570 | |||
571 | mutex_lock(&ctrl->work_lock); | ||
572 | rsxx_dma_done(ctrl); | ||
573 | mutex_unlock(&ctrl->work_lock); | ||
574 | } | ||
575 | |||
558 | static int rsxx_queue_discard(struct rsxx_cardinfo *card, | 576 | static int rsxx_queue_discard(struct rsxx_cardinfo *card, |
559 | struct list_head *q, | 577 | struct list_head *q, |
560 | unsigned int laddr, | 578 | unsigned int laddr, |
@@ -789,6 +807,7 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev, | |||
789 | spin_lock_init(&ctrl->trackers->lock); | 807 | spin_lock_init(&ctrl->trackers->lock); |
790 | 808 | ||
791 | spin_lock_init(&ctrl->queue_lock); | 809 | spin_lock_init(&ctrl->queue_lock); |
810 | mutex_init(&ctrl->work_lock); | ||
792 | INIT_LIST_HEAD(&ctrl->queue); | 811 | INIT_LIST_HEAD(&ctrl->queue); |
793 | 812 | ||
794 | setup_timer(&ctrl->activity_timer, dma_engine_stalled, | 813 | setup_timer(&ctrl->activity_timer, dma_engine_stalled, |
@@ -802,8 +821,8 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev, | |||
802 | if (!ctrl->done_wq) | 821 | if (!ctrl->done_wq) |
803 | return -ENOMEM; | 822 | return -ENOMEM; |
804 | 823 | ||
805 | INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas); | 824 | INIT_WORK(&ctrl->issue_dma_work, rsxx_schedule_issue); |
806 | INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done); | 825 | INIT_WORK(&ctrl->dma_done_work, rsxx_schedule_done); |
807 | 826 | ||
808 | st = rsxx_hw_buffers_init(dev, ctrl); | 827 | st = rsxx_hw_buffers_init(dev, ctrl); |
809 | if (st) | 828 | if (st) |
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h index 60b6ed6779ac..c968a6918b6e 100644 --- a/drivers/block/rsxx/rsxx_priv.h +++ b/drivers/block/rsxx/rsxx_priv.h | |||
@@ -115,6 +115,7 @@ struct rsxx_dma_ctrl { | |||
115 | struct timer_list activity_timer; | 115 | struct timer_list activity_timer; |
116 | struct dma_tracker_list *trackers; | 116 | struct dma_tracker_list *trackers; |
117 | struct rsxx_dma_stats stats; | 117 | struct rsxx_dma_stats stats; |
118 | struct mutex work_lock; | ||
118 | }; | 119 | }; |
119 | 120 | ||
120 | struct rsxx_cardinfo { | 121 | struct rsxx_cardinfo { |