aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rsxx/cregs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/rsxx/cregs.c')
-rw-r--r--drivers/block/rsxx/cregs.c112
1 files changed, 72 insertions, 40 deletions
diff --git a/drivers/block/rsxx/cregs.c b/drivers/block/rsxx/cregs.c
index 80bbe639fccd..4b5c020a0a65 100644
--- a/drivers/block/rsxx/cregs.c
+++ b/drivers/block/rsxx/cregs.c
@@ -58,7 +58,7 @@ static struct kmem_cache *creg_cmd_pool;
58#error Unknown endianess!!! Aborting... 58#error Unknown endianess!!! Aborting...
59#endif 59#endif
60 60
61static void copy_to_creg_data(struct rsxx_cardinfo *card, 61static int copy_to_creg_data(struct rsxx_cardinfo *card,
62 int cnt8, 62 int cnt8,
63 void *buf, 63 void *buf,
64 unsigned int stream) 64 unsigned int stream)
@@ -66,6 +66,9 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card,
66 int i = 0; 66 int i = 0;
67 u32 *data = buf; 67 u32 *data = buf;
68 68
69 if (unlikely(card->eeh_state))
70 return -EIO;
71
69 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 72 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) {
70 /* 73 /*
71 * Firmware implementation makes it necessary to byte swap on 74 * Firmware implementation makes it necessary to byte swap on
@@ -76,10 +79,12 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card,
76 else 79 else
77 iowrite32(data[i], card->regmap + CREG_DATA(i)); 80 iowrite32(data[i], card->regmap + CREG_DATA(i));
78 } 81 }
82
83 return 0;
79} 84}
80 85
81 86
82static void copy_from_creg_data(struct rsxx_cardinfo *card, 87static int copy_from_creg_data(struct rsxx_cardinfo *card,
83 int cnt8, 88 int cnt8,
84 void *buf, 89 void *buf,
85 unsigned int stream) 90 unsigned int stream)
@@ -87,6 +92,9 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card,
87 int i = 0; 92 int i = 0;
88 u32 *data = buf; 93 u32 *data = buf;
89 94
95 if (unlikely(card->eeh_state))
96 return -EIO;
97
90 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 98 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) {
91 /* 99 /*
92 * Firmware implementation makes it necessary to byte swap on 100 * Firmware implementation makes it necessary to byte swap on
@@ -97,41 +105,31 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card,
97 else 105 else
98 data[i] = ioread32(card->regmap + CREG_DATA(i)); 106 data[i] = ioread32(card->regmap + CREG_DATA(i));
99 } 107 }
100}
101
102static struct creg_cmd *pop_active_cmd(struct rsxx_cardinfo *card)
103{
104 struct creg_cmd *cmd;
105 108
106 /* 109 return 0;
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} 110}
117 111
118static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) 112static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd)
119{ 113{
114 int st;
115
116 if (unlikely(card->eeh_state))
117 return;
118
120 iowrite32(cmd->addr, card->regmap + CREG_ADD); 119 iowrite32(cmd->addr, card->regmap + CREG_ADD);
121 iowrite32(cmd->cnt8, card->regmap + CREG_CNT); 120 iowrite32(cmd->cnt8, card->regmap + CREG_CNT);
122 121
123 if (cmd->op == CREG_OP_WRITE) { 122 if (cmd->op == CREG_OP_WRITE) {
124 if (cmd->buf) 123 if (cmd->buf) {
125 copy_to_creg_data(card, cmd->cnt8, 124 st = copy_to_creg_data(card, cmd->cnt8,
126 cmd->buf, cmd->stream); 125 cmd->buf, cmd->stream);
126 if (st)
127 return;
128 }
127 } 129 }
128 130
129 /* 131 if (unlikely(card->eeh_state))
130 * Data copy must complete before initiating the command. This is 132 return;
131 * needed for weakly ordered processors (i.e. PowerPC), so that all
132 * neccessary registers are written before we kick the hardware.
133 */
134 wmb();
135 133
136 /* Setting the valid bit will kick off the command. */ 134 /* Setting the valid bit will kick off the command. */
137 iowrite32(cmd->op, card->regmap + CREG_CMD); 135 iowrite32(cmd->op, card->regmap + CREG_CMD);
@@ -196,11 +194,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card,
196 cmd->cb_private = cb_private; 194 cmd->cb_private = cb_private;
197 cmd->status = 0; 195 cmd->status = 0;
198 196
199 spin_lock(&card->creg_ctrl.lock); 197 spin_lock_bh(&card->creg_ctrl.lock);
200 list_add_tail(&cmd->list, &card->creg_ctrl.queue); 198 list_add_tail(&cmd->list, &card->creg_ctrl.queue);
201 card->creg_ctrl.q_depth++; 199 card->creg_ctrl.q_depth++;
202 creg_kick_queue(card); 200 creg_kick_queue(card);
203 spin_unlock(&card->creg_ctrl.lock); 201 spin_unlock_bh(&card->creg_ctrl.lock);
204 202
205 return 0; 203 return 0;
206} 204}
@@ -210,7 +208,11 @@ static void creg_cmd_timed_out(unsigned long data)
210 struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; 208 struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data;
211 struct creg_cmd *cmd; 209 struct creg_cmd *cmd;
212 210
213 cmd = pop_active_cmd(card); 211 spin_lock(&card->creg_ctrl.lock);
212 cmd = card->creg_ctrl.active_cmd;
213 card->creg_ctrl.active_cmd = NULL;
214 spin_unlock(&card->creg_ctrl.lock);
215
214 if (cmd == NULL) { 216 if (cmd == NULL) {
215 card->creg_ctrl.creg_stats.creg_timeout++; 217 card->creg_ctrl.creg_stats.creg_timeout++;
216 dev_warn(CARD_TO_DEV(card), 218 dev_warn(CARD_TO_DEV(card),
@@ -247,7 +249,11 @@ static void creg_cmd_done(struct work_struct *work)
247 if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) 249 if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0)
248 card->creg_ctrl.creg_stats.failed_cancel_timer++; 250 card->creg_ctrl.creg_stats.failed_cancel_timer++;
249 251
250 cmd = pop_active_cmd(card); 252 spin_lock_bh(&card->creg_ctrl.lock);
253 cmd = card->creg_ctrl.active_cmd;
254 card->creg_ctrl.active_cmd = NULL;
255 spin_unlock_bh(&card->creg_ctrl.lock);
256
251 if (cmd == NULL) { 257 if (cmd == NULL) {
252 dev_err(CARD_TO_DEV(card), 258 dev_err(CARD_TO_DEV(card),
253 "Spurious creg interrupt!\n"); 259 "Spurious creg interrupt!\n");
@@ -287,7 +293,7 @@ static void creg_cmd_done(struct work_struct *work)
287 goto creg_done; 293 goto creg_done;
288 } 294 }
289 295
290 copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); 296 st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream);
291 } 297 }
292 298
293creg_done: 299creg_done:
@@ -296,10 +302,10 @@ creg_done:
296 302
297 kmem_cache_free(creg_cmd_pool, cmd); 303 kmem_cache_free(creg_cmd_pool, cmd);
298 304
299 spin_lock(&card->creg_ctrl.lock); 305 spin_lock_bh(&card->creg_ctrl.lock);
300 card->creg_ctrl.active = 0; 306 card->creg_ctrl.active = 0;
301 creg_kick_queue(card); 307 creg_kick_queue(card);
302 spin_unlock(&card->creg_ctrl.lock); 308 spin_unlock_bh(&card->creg_ctrl.lock);
303} 309}
304 310
305static void creg_reset(struct rsxx_cardinfo *card) 311static void creg_reset(struct rsxx_cardinfo *card)
@@ -324,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
324 "Resetting creg interface for recovery\n"); 330 "Resetting creg interface for recovery\n");
325 331
326 /* Cancel outstanding commands */ 332 /* Cancel outstanding commands */
327 spin_lock(&card->creg_ctrl.lock); 333 spin_lock_bh(&card->creg_ctrl.lock);
328 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 334 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
329 list_del(&cmd->list); 335 list_del(&cmd->list);
330 card->creg_ctrl.q_depth--; 336 card->creg_ctrl.q_depth--;
@@ -345,7 +351,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
345 351
346 card->creg_ctrl.active = 0; 352 card->creg_ctrl.active = 0;
347 } 353 }
348 spin_unlock(&card->creg_ctrl.lock); 354 spin_unlock_bh(&card->creg_ctrl.lock);
349 355
350 card->creg_ctrl.reset = 0; 356 card->creg_ctrl.reset = 0;
351 spin_lock_irqsave(&card->irq_lock, flags); 357 spin_lock_irqsave(&card->irq_lock, flags);
@@ -399,12 +405,12 @@ static int __issue_creg_rw(struct rsxx_cardinfo *card,
399 return st; 405 return st;
400 406
401 /* 407 /*
402 * This timeout is neccessary for unresponsive hardware. The additional 408 * This timeout is necessary for unresponsive hardware. The additional
403 * 20 seconds to used to guarantee that each cregs requests has time to 409 * 20 seconds to used to guarantee that each cregs requests has time to
404 * complete. 410 * complete.
405 */ 411 */
406 timeout = msecs_to_jiffies((CREG_TIMEOUT_MSEC * 412 timeout = msecs_to_jiffies(CREG_TIMEOUT_MSEC *
407 card->creg_ctrl.q_depth) + 20000); 413 card->creg_ctrl.q_depth + 20000);
408 414
409 /* 415 /*
410 * The creg interface is guaranteed to complete. It has a timeout 416 * The creg interface is guaranteed to complete. It has a timeout
@@ -690,6 +696,32 @@ int rsxx_reg_access(struct rsxx_cardinfo *card,
690 return 0; 696 return 0;
691} 697}
692 698
699void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card)
700{
701 struct creg_cmd *cmd = NULL;
702
703 cmd = card->creg_ctrl.active_cmd;
704 card->creg_ctrl.active_cmd = NULL;
705
706 if (cmd) {
707 del_timer_sync(&card->creg_ctrl.cmd_timer);
708
709 spin_lock_bh(&card->creg_ctrl.lock);
710 list_add(&cmd->list, &card->creg_ctrl.queue);
711 card->creg_ctrl.q_depth++;
712 card->creg_ctrl.active = 0;
713 spin_unlock_bh(&card->creg_ctrl.lock);
714 }
715}
716
717void rsxx_kick_creg_queue(struct rsxx_cardinfo *card)
718{
719 spin_lock_bh(&card->creg_ctrl.lock);
720 if (!list_empty(&card->creg_ctrl.queue))
721 creg_kick_queue(card);
722 spin_unlock_bh(&card->creg_ctrl.lock);
723}
724
693/*------------ Initialization & Setup --------------*/ 725/*------------ Initialization & Setup --------------*/
694int rsxx_creg_setup(struct rsxx_cardinfo *card) 726int rsxx_creg_setup(struct rsxx_cardinfo *card)
695{ 727{
@@ -712,7 +744,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
712 int cnt = 0; 744 int cnt = 0;
713 745
714 /* Cancel outstanding commands */ 746 /* Cancel outstanding commands */
715 spin_lock(&card->creg_ctrl.lock); 747 spin_lock_bh(&card->creg_ctrl.lock);
716 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 748 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
717 list_del(&cmd->list); 749 list_del(&cmd->list);
718 if (cmd->cb) 750 if (cmd->cb)
@@ -737,7 +769,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
737 "Canceled active creg command\n"); 769 "Canceled active creg command\n");
738 kmem_cache_free(creg_cmd_pool, cmd); 770 kmem_cache_free(creg_cmd_pool, cmd);
739 } 771 }
740 spin_unlock(&card->creg_ctrl.lock); 772 spin_unlock_bh(&card->creg_ctrl.lock);
741 773
742 cancel_work_sync(&card->creg_ctrl.done_work); 774 cancel_work_sync(&card->creg_ctrl.done_work);
743} 775}