aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilip J Kelleher <pjk1939@linux.vnet.ibm.com>2013-02-25 13:31:31 -0500
committerJens Axboe <axboe@kernel.dk>2013-03-11 14:53:55 -0400
commit03ac03a8971bd7e9f8c8b20a309b61beaf154d60 (patch)
tree310c2b5750e53387f45a4144e4454b181143bdc4 /drivers/block
parentf37912039eb04979f269de0a7dc1a601702df51a (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.c44
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
102static 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
118static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) 102static 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
298static void creg_reset(struct rsxx_cardinfo *card) 290static 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}