Skip to content

Commit

Permalink
rsxx: Fixes soft-lockup issues during DMAs.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Philip J Kelleher authored and Jens Axboe committed Jun 19, 2013
1 parent 0ab4743 commit 31a70bb
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 8 deletions.
35 changes: 27 additions & 8 deletions drivers/block/rsxx/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,15 +381,13 @@ static void dma_engine_stalled(unsigned long data)
}
}

static void rsxx_issue_dmas(struct work_struct *work)
static void rsxx_issue_dmas(struct rsxx_dma_ctrl *ctrl)
{
struct rsxx_dma_ctrl *ctrl;
struct rsxx_dma *dma;
int tag;
int cmds_pending = 0;
struct hw_cmd *hw_cmd_buf;

ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work);
hw_cmd_buf = ctrl->cmd.buf;

if (unlikely(ctrl->card->halt) ||
Expand Down Expand Up @@ -469,17 +467,15 @@ static void rsxx_issue_dmas(struct work_struct *work)
}
}

static void rsxx_dma_done(struct work_struct *work)
static void rsxx_dma_done(struct rsxx_dma_ctrl *ctrl)
{
struct rsxx_dma_ctrl *ctrl;
struct rsxx_dma *dma;
unsigned long flags;
u16 count;
u8 status;
u8 tag;
struct hw_status *hw_st_buf;

ctrl = container_of(work, struct rsxx_dma_ctrl, dma_done_work);
hw_st_buf = ctrl->status.buf;

if (unlikely(ctrl->card->halt) ||
Expand Down Expand Up @@ -555,6 +551,28 @@ static void rsxx_dma_done(struct work_struct *work)
spin_unlock_bh(&ctrl->queue_lock);
}

static void rsxx_schedule_issue(struct work_struct *work)
{
struct rsxx_dma_ctrl *ctrl;

ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work);

mutex_lock(&ctrl->work_lock);
rsxx_issue_dmas(ctrl);
mutex_unlock(&ctrl->work_lock);
}

static void rsxx_schedule_done(struct work_struct *work)
{
struct rsxx_dma_ctrl *ctrl;

ctrl = container_of(work, struct rsxx_dma_ctrl, dma_done_work);

mutex_lock(&ctrl->work_lock);
rsxx_dma_done(ctrl);
mutex_unlock(&ctrl->work_lock);
}

static int rsxx_queue_discard(struct rsxx_cardinfo *card,
struct list_head *q,
unsigned int laddr,
Expand Down Expand Up @@ -789,6 +807,7 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev,
spin_lock_init(&ctrl->trackers->lock);

spin_lock_init(&ctrl->queue_lock);
mutex_init(&ctrl->work_lock);
INIT_LIST_HEAD(&ctrl->queue);

setup_timer(&ctrl->activity_timer, dma_engine_stalled,
Expand All @@ -802,8 +821,8 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev,
if (!ctrl->done_wq)
return -ENOMEM;

INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas);
INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done);
INIT_WORK(&ctrl->issue_dma_work, rsxx_schedule_issue);
INIT_WORK(&ctrl->dma_done_work, rsxx_schedule_done);

st = rsxx_hw_buffers_init(dev, ctrl);
if (st)
Expand Down
1 change: 1 addition & 0 deletions drivers/block/rsxx/rsxx_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ struct rsxx_dma_ctrl {
struct timer_list activity_timer;
struct dma_tracker_list *trackers;
struct rsxx_dma_stats stats;
struct mutex work_lock;
};

struct rsxx_cardinfo {
Expand Down

0 comments on commit 31a70bb

Please sign in to comment.