diff options
author | Philip J Kelleher <pjk1939@linux.vnet.ibm.com> | 2013-02-25 13:31:31 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-03-11 14:53:55 -0400 |
commit | 03ac03a8971bd7e9f8c8b20a309b61beaf154d60 (patch) | |
tree | 310c2b5750e53387f45a4144e4454b181143bdc4 /drivers/block | |
parent | f37912039eb04979f269de0a7dc1a601702df51a (diff) |
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: Philip J Kelleher <pjk1939@linux.vnet.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rsxx/cregs.c | 44 |
1 files changed, 18 insertions, 26 deletions
diff --git a/drivers/block/rsxx/cregs.c b/drivers/block/rsxx/cregs.c index 224156435261..0539a25877eb 100644 --- a/drivers/block/rsxx/cregs.c +++ b/drivers/block/rsxx/cregs.c | |||
@@ -99,22 +99,6 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card, | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static struct creg_cmd *pop_active_cmd(struct rsxx_cardinfo *card) | ||
103 | { | ||
104 | struct creg_cmd *cmd; | ||
105 | |||
106 | /* | ||
107 | * Spin lock is needed because this can be called in atomic/interrupt | ||
108 | * context. | ||
109 | */ | ||
110 | spin_lock_bh(&card->creg_ctrl.lock); | ||
111 | cmd = card->creg_ctrl.active_cmd; | ||
112 | card->creg_ctrl.active_cmd = NULL; | ||
113 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
114 | |||
115 | return cmd; | ||
116 | } | ||
117 | |||
118 | static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) | 102 | static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) |
119 | { | 103 | { |
120 | iowrite32(cmd->addr, card->regmap + CREG_ADD); | 104 | iowrite32(cmd->addr, card->regmap + CREG_ADD); |
@@ -189,11 +173,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card, | |||
189 | cmd->cb_private = cb_private; | 173 | cmd->cb_private = cb_private; |
190 | cmd->status = 0; | 174 | cmd->status = 0; |
191 | 175 | ||
192 | spin_lock(&card->creg_ctrl.lock); | 176 | spin_lock_bh(&card->creg_ctrl.lock); |
193 | list_add_tail(&cmd->list, &card->creg_ctrl.queue); | 177 | list_add_tail(&cmd->list, &card->creg_ctrl.queue); |
194 | card->creg_ctrl.q_depth++; | 178 | card->creg_ctrl.q_depth++; |
195 | creg_kick_queue(card); | 179 | creg_kick_queue(card); |
196 | spin_unlock(&card->creg_ctrl.lock); | 180 | spin_unlock_bh(&card->creg_ctrl.lock); |
197 | 181 | ||
198 | return 0; | 182 | return 0; |
199 | } | 183 | } |
@@ -203,7 +187,11 @@ static void creg_cmd_timed_out(unsigned long data) | |||
203 | struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; | 187 | struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; |
204 | struct creg_cmd *cmd; | 188 | struct creg_cmd *cmd; |
205 | 189 | ||
206 | cmd = pop_active_cmd(card); | 190 | spin_lock(&card->creg_ctrl.lock); |
191 | cmd = card->creg_ctrl.active_cmd; | ||
192 | card->creg_ctrl.active_cmd = NULL; | ||
193 | spin_unlock(&card->creg_ctrl.lock); | ||
194 | |||
207 | if (cmd == NULL) { | 195 | if (cmd == NULL) { |
208 | card->creg_ctrl.creg_stats.creg_timeout++; | 196 | card->creg_ctrl.creg_stats.creg_timeout++; |
209 | dev_warn(CARD_TO_DEV(card), | 197 | dev_warn(CARD_TO_DEV(card), |
@@ -240,7 +228,11 @@ static void creg_cmd_done(struct work_struct *work) | |||
240 | if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) | 228 | if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) |
241 | card->creg_ctrl.creg_stats.failed_cancel_timer++; | 229 | card->creg_ctrl.creg_stats.failed_cancel_timer++; |
242 | 230 | ||
243 | cmd = pop_active_cmd(card); | 231 | spin_lock_bh(&card->creg_ctrl.lock); |
232 | cmd = card->creg_ctrl.active_cmd; | ||
233 | card->creg_ctrl.active_cmd = NULL; | ||
234 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
235 | |||
244 | if (cmd == NULL) { | 236 | if (cmd == NULL) { |
245 | dev_err(CARD_TO_DEV(card), | 237 | dev_err(CARD_TO_DEV(card), |
246 | "Spurious creg interrupt!\n"); | 238 | "Spurious creg interrupt!\n"); |
@@ -289,10 +281,10 @@ creg_done: | |||
289 | 281 | ||
290 | kmem_cache_free(creg_cmd_pool, cmd); | 282 | kmem_cache_free(creg_cmd_pool, cmd); |
291 | 283 | ||
292 | spin_lock(&card->creg_ctrl.lock); | 284 | spin_lock_bh(&card->creg_ctrl.lock); |
293 | card->creg_ctrl.active = 0; | 285 | card->creg_ctrl.active = 0; |
294 | creg_kick_queue(card); | 286 | creg_kick_queue(card); |
295 | spin_unlock(&card->creg_ctrl.lock); | 287 | spin_unlock_bh(&card->creg_ctrl.lock); |
296 | } | 288 | } |
297 | 289 | ||
298 | static void creg_reset(struct rsxx_cardinfo *card) | 290 | static void creg_reset(struct rsxx_cardinfo *card) |
@@ -317,7 +309,7 @@ static void creg_reset(struct rsxx_cardinfo *card) | |||
317 | "Resetting creg interface for recovery\n"); | 309 | "Resetting creg interface for recovery\n"); |
318 | 310 | ||
319 | /* Cancel outstanding commands */ | 311 | /* Cancel outstanding commands */ |
320 | spin_lock(&card->creg_ctrl.lock); | 312 | spin_lock_bh(&card->creg_ctrl.lock); |
321 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { | 313 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { |
322 | list_del(&cmd->list); | 314 | list_del(&cmd->list); |
323 | card->creg_ctrl.q_depth--; | 315 | card->creg_ctrl.q_depth--; |
@@ -338,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card) | |||
338 | 330 | ||
339 | card->creg_ctrl.active = 0; | 331 | card->creg_ctrl.active = 0; |
340 | } | 332 | } |
341 | spin_unlock(&card->creg_ctrl.lock); | 333 | spin_unlock_bh(&card->creg_ctrl.lock); |
342 | 334 | ||
343 | card->creg_ctrl.reset = 0; | 335 | card->creg_ctrl.reset = 0; |
344 | spin_lock_irqsave(&card->irq_lock, flags); | 336 | spin_lock_irqsave(&card->irq_lock, flags); |
@@ -705,7 +697,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) | |||
705 | int cnt = 0; | 697 | int cnt = 0; |
706 | 698 | ||
707 | /* Cancel outstanding commands */ | 699 | /* Cancel outstanding commands */ |
708 | spin_lock(&card->creg_ctrl.lock); | 700 | spin_lock_bh(&card->creg_ctrl.lock); |
709 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { | 701 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { |
710 | list_del(&cmd->list); | 702 | list_del(&cmd->list); |
711 | if (cmd->cb) | 703 | if (cmd->cb) |
@@ -730,7 +722,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) | |||
730 | "Canceled active creg command\n"); | 722 | "Canceled active creg command\n"); |
731 | kmem_cache_free(creg_cmd_pool, cmd); | 723 | kmem_cache_free(creg_cmd_pool, cmd); |
732 | } | 724 | } |
733 | spin_unlock(&card->creg_ctrl.lock); | 725 | spin_unlock_bh(&card->creg_ctrl.lock); |
734 | 726 | ||
735 | cancel_work_sync(&card->creg_ctrl.done_work); | 727 | cancel_work_sync(&card->creg_ctrl.done_work); |
736 | } | 728 | } |