Commit 03ac03a8 authored by Philip J Kelleher's avatar Philip J Kelleher Committed by Jens Axboe

block: IBM RamSan 70/80 fixes inconsistent locking.

This patch includes changes to the cregs locking scheme. Before,
inconsistant locking would occur because of misuse of spin_lock,
spin_lock_bh, and counter parts.
Signed-off-by: default avatarPhilip J Kelleher <pjk1939@linux.vnet.ibm.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent f3791203
...@@ -99,22 +99,6 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card, ...@@ -99,22 +99,6 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card,
} }
} }
static struct creg_cmd *pop_active_cmd(struct rsxx_cardinfo *card)
{
struct creg_cmd *cmd;
/*
* Spin lock is needed because this can be called in atomic/interrupt
* context.
*/
spin_lock_bh(&card->creg_ctrl.lock);
cmd = card->creg_ctrl.active_cmd;
card->creg_ctrl.active_cmd = NULL;
spin_unlock_bh(&card->creg_ctrl.lock);
return cmd;
}
static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd)
{ {
iowrite32(cmd->addr, card->regmap + CREG_ADD); iowrite32(cmd->addr, card->regmap + CREG_ADD);
...@@ -189,11 +173,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card, ...@@ -189,11 +173,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card,
cmd->cb_private = cb_private; cmd->cb_private = cb_private;
cmd->status = 0; cmd->status = 0;
spin_lock(&card->creg_ctrl.lock); spin_lock_bh(&card->creg_ctrl.lock);
list_add_tail(&cmd->list, &card->creg_ctrl.queue); list_add_tail(&cmd->list, &card->creg_ctrl.queue);
card->creg_ctrl.q_depth++; card->creg_ctrl.q_depth++;
creg_kick_queue(card); creg_kick_queue(card);
spin_unlock(&card->creg_ctrl.lock); spin_unlock_bh(&card->creg_ctrl.lock);
return 0; return 0;
} }
...@@ -203,7 +187,11 @@ static void creg_cmd_timed_out(unsigned long data) ...@@ -203,7 +187,11 @@ static void creg_cmd_timed_out(unsigned long data)
struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data;
struct creg_cmd *cmd; struct creg_cmd *cmd;
cmd = pop_active_cmd(card); spin_lock(&card->creg_ctrl.lock);
cmd = card->creg_ctrl.active_cmd;
card->creg_ctrl.active_cmd = NULL;
spin_unlock(&card->creg_ctrl.lock);
if (cmd == NULL) { if (cmd == NULL) {
card->creg_ctrl.creg_stats.creg_timeout++; card->creg_ctrl.creg_stats.creg_timeout++;
dev_warn(CARD_TO_DEV(card), dev_warn(CARD_TO_DEV(card),
...@@ -240,7 +228,11 @@ static void creg_cmd_done(struct work_struct *work) ...@@ -240,7 +228,11 @@ static void creg_cmd_done(struct work_struct *work)
if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0)
card->creg_ctrl.creg_stats.failed_cancel_timer++; card->creg_ctrl.creg_stats.failed_cancel_timer++;
cmd = pop_active_cmd(card); spin_lock_bh(&card->creg_ctrl.lock);
cmd = card->creg_ctrl.active_cmd;
card->creg_ctrl.active_cmd = NULL;
spin_unlock_bh(&card->creg_ctrl.lock);
if (cmd == NULL) { if (cmd == NULL) {
dev_err(CARD_TO_DEV(card), dev_err(CARD_TO_DEV(card),
"Spurious creg interrupt!\n"); "Spurious creg interrupt!\n");
...@@ -289,10 +281,10 @@ static void creg_cmd_done(struct work_struct *work) ...@@ -289,10 +281,10 @@ static void creg_cmd_done(struct work_struct *work)
kmem_cache_free(creg_cmd_pool, cmd); kmem_cache_free(creg_cmd_pool, cmd);
spin_lock(&card->creg_ctrl.lock); spin_lock_bh(&card->creg_ctrl.lock);
card->creg_ctrl.active = 0; card->creg_ctrl.active = 0;
creg_kick_queue(card); creg_kick_queue(card);
spin_unlock(&card->creg_ctrl.lock); spin_unlock_bh(&card->creg_ctrl.lock);
} }
static void creg_reset(struct rsxx_cardinfo *card) static void creg_reset(struct rsxx_cardinfo *card)
...@@ -317,7 +309,7 @@ static void creg_reset(struct rsxx_cardinfo *card) ...@@ -317,7 +309,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
"Resetting creg interface for recovery\n"); "Resetting creg interface for recovery\n");
/* Cancel outstanding commands */ /* Cancel outstanding commands */
spin_lock(&card->creg_ctrl.lock); spin_lock_bh(&card->creg_ctrl.lock);
list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
list_del(&cmd->list); list_del(&cmd->list);
card->creg_ctrl.q_depth--; card->creg_ctrl.q_depth--;
...@@ -338,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card) ...@@ -338,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
card->creg_ctrl.active = 0; card->creg_ctrl.active = 0;
} }
spin_unlock(&card->creg_ctrl.lock); spin_unlock_bh(&card->creg_ctrl.lock);
card->creg_ctrl.reset = 0; card->creg_ctrl.reset = 0;
spin_lock_irqsave(&card->irq_lock, flags); spin_lock_irqsave(&card->irq_lock, flags);
...@@ -705,7 +697,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) ...@@ -705,7 +697,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
int cnt = 0; int cnt = 0;
/* Cancel outstanding commands */ /* Cancel outstanding commands */
spin_lock(&card->creg_ctrl.lock); spin_lock_bh(&card->creg_ctrl.lock);
list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
list_del(&cmd->list); list_del(&cmd->list);
if (cmd->cb) if (cmd->cb)
...@@ -730,7 +722,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) ...@@ -730,7 +722,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
"Canceled active creg command\n"); "Canceled active creg command\n");
kmem_cache_free(creg_cmd_pool, cmd); kmem_cache_free(creg_cmd_pool, cmd);
} }
spin_unlock(&card->creg_ctrl.lock); spin_unlock_bh(&card->creg_ctrl.lock);
cancel_work_sync(&card->creg_ctrl.done_work); cancel_work_sync(&card->creg_ctrl.done_work);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment