aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip J Kelleher <pjk1939@linux.vnet.ibm.com>2013-03-16 03:22:25 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-16 03:22:25 -0400
commitc95246c3a2ac796cfa43e76200ede59cb4a1644f (patch)
tree18a4a1a6b3ee78c5f8d646831edaecba1f0012ad
parent1ebfd109822ea35b71aee4efe9ddc2e1b9ac0ed7 (diff)
Adding in EEH support to the IBM FlashSystem 70/80 device driver
Changes in v2 include: o Fixed spelling of guarantee. o Fixed potential memory leak if slot reset fails out. o Changed list_for_each_entry_safe with list_for_each_entry. Signed-off-by: Philip J Kelleher <pjk1939@linux.vnet.ibm.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/rsxx/core.c203
-rw-r--r--drivers/block/rsxx/cregs.c59
-rw-r--r--drivers/block/rsxx/dma.c216
-rw-r--r--drivers/block/rsxx/rsxx_priv.h25
4 files changed, 436 insertions, 67 deletions
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c
index cbbdff113f46..93f28191a0ff 100644
--- a/drivers/block/rsxx/core.c
+++ b/drivers/block/rsxx/core.c
@@ -30,6 +30,7 @@
30#include <linux/reboot.h> 30#include <linux/reboot.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/bitops.h> 32#include <linux/bitops.h>
33#include <linux/delay.h>
33 34
34#include <linux/genhd.h> 35#include <linux/genhd.h>
35#include <linux/idr.h> 36#include <linux/idr.h>
@@ -52,6 +53,13 @@ static DEFINE_IDA(rsxx_disk_ida);
52static DEFINE_SPINLOCK(rsxx_ida_lock); 53static DEFINE_SPINLOCK(rsxx_ida_lock);
53 54
54/*----------------- Interrupt Control & Handling -------------------*/ 55/*----------------- Interrupt Control & Handling -------------------*/
56
57static void rsxx_mask_interrupts(struct rsxx_cardinfo *card)
58{
59 card->isr_mask = 0;
60 card->ier_mask = 0;
61}
62
55static void __enable_intr(unsigned int *mask, unsigned int intr) 63static void __enable_intr(unsigned int *mask, unsigned int intr)
56{ 64{
57 *mask |= intr; 65 *mask |= intr;
@@ -71,7 +79,8 @@ static void __disable_intr(unsigned int *mask, unsigned int intr)
71 */ 79 */
72void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr) 80void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr)
73{ 81{
74 if (unlikely(card->halt)) 82 if (unlikely(card->halt) ||
83 unlikely(card->eeh_state))
75 return; 84 return;
76 85
77 __enable_intr(&card->ier_mask, intr); 86 __enable_intr(&card->ier_mask, intr);
@@ -80,6 +89,9 @@ void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr)
80 89
81void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr) 90void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr)
82{ 91{
92 if (unlikely(card->eeh_state))
93 return;
94
83 __disable_intr(&card->ier_mask, intr); 95 __disable_intr(&card->ier_mask, intr);
84 iowrite32(card->ier_mask, card->regmap + IER); 96 iowrite32(card->ier_mask, card->regmap + IER);
85} 97}
@@ -87,7 +99,8 @@ void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr)
87void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, 99void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card,
88 unsigned int intr) 100 unsigned int intr)
89{ 101{
90 if (unlikely(card->halt)) 102 if (unlikely(card->halt) ||
103 unlikely(card->eeh_state))
91 return; 104 return;
92 105
93 __enable_intr(&card->isr_mask, intr); 106 __enable_intr(&card->isr_mask, intr);
@@ -97,6 +110,9 @@ void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card,
97void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card, 110void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card,
98 unsigned int intr) 111 unsigned int intr)
99{ 112{
113 if (unlikely(card->eeh_state))
114 return;
115
100 __disable_intr(&card->isr_mask, intr); 116 __disable_intr(&card->isr_mask, intr);
101 __disable_intr(&card->ier_mask, intr); 117 __disable_intr(&card->ier_mask, intr);
102 iowrite32(card->ier_mask, card->regmap + IER); 118 iowrite32(card->ier_mask, card->regmap + IER);
@@ -115,6 +131,9 @@ static irqreturn_t rsxx_isr(int irq, void *pdata)
115 do { 131 do {
116 reread_isr = 0; 132 reread_isr = 0;
117 133
134 if (unlikely(card->eeh_state))
135 break;
136
118 isr = ioread32(card->regmap + ISR); 137 isr = ioread32(card->regmap + ISR);
119 if (isr == 0xffffffff) { 138 if (isr == 0xffffffff) {
120 /* 139 /*
@@ -304,6 +323,179 @@ static int card_shutdown(struct rsxx_cardinfo *card)
304 return 0; 323 return 0;
305} 324}
306 325
326static void rsxx_eeh_frozen(struct pci_dev *dev)
327{
328 struct rsxx_cardinfo *card = pci_get_drvdata(dev);
329 int i;
330
331 dev_warn(&dev->dev, "IBM FlashSystem PCI: preparing for slot reset.\n");
332
333 card->eeh_state = 1;
334 rsxx_mask_interrupts(card);
335
336 /*
337 * We need to guarantee that the write for eeh_state and masking
338 * interrupts does not become reordered. This will prevent a possible
339 * race condition with the EEH code.
340 */
341 wmb();
342
343 pci_disable_device(dev);
344
345 rsxx_eeh_save_issued_dmas(card);
346
347 rsxx_eeh_save_issued_creg(card);
348
349 for (i = 0; i < card->n_targets; i++) {
350 if (card->ctrl[i].status.buf)
351 pci_free_consistent(card->dev, STATUS_BUFFER_SIZE8,
352 card->ctrl[i].status.buf,
353 card->ctrl[i].status.dma_addr);
354 if (card->ctrl[i].cmd.buf)
355 pci_free_consistent(card->dev, COMMAND_BUFFER_SIZE8,
356 card->ctrl[i].cmd.buf,
357 card->ctrl[i].cmd.dma_addr);
358 }
359}
360
361static void rsxx_eeh_failure(struct pci_dev *dev)
362{
363 struct rsxx_cardinfo *card = pci_get_drvdata(dev);
364 int i;
365
366 dev_err(&dev->dev, "IBM FlashSystem PCI: disabling failed card.\n");
367
368 card->eeh_state = 1;
369
370 for (i = 0; i < card->n_targets; i++)
371 del_timer_sync(&card->ctrl[i].activity_timer);
372
373 rsxx_eeh_cancel_dmas(card);
374}
375
376static int rsxx_eeh_fifo_flush_poll(struct rsxx_cardinfo *card)
377{
378 unsigned int status;
379 int iter = 0;
380
381 /* We need to wait for the hardware to reset */
382 while (iter++ < 10) {
383 status = ioread32(card->regmap + PCI_RECONFIG);
384
385 if (status & RSXX_FLUSH_BUSY) {
386 ssleep(1);
387 continue;
388 }
389
390 if (status & RSXX_FLUSH_TIMEOUT)
391 dev_warn(CARD_TO_DEV(card), "HW: flash controller timeout\n");
392 return 0;
393 }
394
395 /* Hardware failed resetting itself. */
396 return -1;
397}
398
399static pci_ers_result_t rsxx_error_detected(struct pci_dev *dev,
400 enum pci_channel_state error)
401{
402 if (dev->revision < RSXX_EEH_SUPPORT)
403 return PCI_ERS_RESULT_NONE;
404
405 if (error == pci_channel_io_perm_failure) {
406 rsxx_eeh_failure(dev);
407 return PCI_ERS_RESULT_DISCONNECT;
408 }
409
410 rsxx_eeh_frozen(dev);
411 return PCI_ERS_RESULT_NEED_RESET;
412}
413
414static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev)
415{
416 struct rsxx_cardinfo *card = pci_get_drvdata(dev);
417 unsigned long flags;
418 int i;
419 int st;
420
421 dev_warn(&dev->dev,
422 "IBM FlashSystem PCI: recovering from slot reset.\n");
423
424 st = pci_enable_device(dev);
425 if (st)
426 goto failed_hw_setup;
427
428 pci_set_master(dev);
429
430 st = rsxx_eeh_fifo_flush_poll(card);
431 if (st)
432 goto failed_hw_setup;
433
434 rsxx_dma_queue_reset(card);
435
436 for (i = 0; i < card->n_targets; i++) {
437 st = rsxx_hw_buffers_init(dev, &card->ctrl[i]);
438 if (st)
439 goto failed_hw_buffers_init;
440 }
441
442 if (card->config_valid)
443 rsxx_dma_configure(card);
444
445 /* Clears the ISR register from spurious interrupts */
446 st = ioread32(card->regmap + ISR);
447
448 card->eeh_state = 0;
449
450 st = rsxx_eeh_remap_dmas(card);
451 if (st)
452 goto failed_remap_dmas;
453
454 spin_lock_irqsave(&card->irq_lock, flags);
455 if (card->n_targets & RSXX_MAX_TARGETS)
456 rsxx_enable_ier_and_isr(card, CR_INTR_ALL_G);
457 else
458 rsxx_enable_ier_and_isr(card, CR_INTR_ALL_C);
459 spin_unlock_irqrestore(&card->irq_lock, flags);
460
461 rsxx_kick_creg_queue(card);
462
463 for (i = 0; i < card->n_targets; i++) {
464 spin_lock(&card->ctrl[i].queue_lock);
465 if (list_empty(&card->ctrl[i].queue)) {
466 spin_unlock(&card->ctrl[i].queue_lock);
467 continue;
468 }
469 spin_unlock(&card->ctrl[i].queue_lock);
470
471 queue_work(card->ctrl[i].issue_wq,
472 &card->ctrl[i].issue_dma_work);
473 }
474
475 dev_info(&dev->dev, "IBM FlashSystem PCI: recovery complete.\n");
476
477 return PCI_ERS_RESULT_RECOVERED;
478
479failed_hw_buffers_init:
480failed_remap_dmas:
481 for (i = 0; i < card->n_targets; i++) {
482 if (card->ctrl[i].status.buf)
483 pci_free_consistent(card->dev,
484 STATUS_BUFFER_SIZE8,
485 card->ctrl[i].status.buf,
486 card->ctrl[i].status.dma_addr);
487 if (card->ctrl[i].cmd.buf)
488 pci_free_consistent(card->dev,
489 COMMAND_BUFFER_SIZE8,
490 card->ctrl[i].cmd.buf,
491 card->ctrl[i].cmd.dma_addr);
492 }
493failed_hw_setup:
494 rsxx_eeh_failure(dev);
495 return PCI_ERS_RESULT_DISCONNECT;
496
497}
498
307/*----------------- Driver Initialization & Setup -------------------*/ 499/*----------------- Driver Initialization & Setup -------------------*/
308/* Returns: 0 if the driver is compatible with the device 500/* Returns: 0 if the driver is compatible with the device
309 -1 if the driver is NOT compatible with the device */ 501 -1 if the driver is NOT compatible with the device */
@@ -383,6 +575,7 @@ static int rsxx_pci_probe(struct pci_dev *dev,
383 575
384 spin_lock_init(&card->irq_lock); 576 spin_lock_init(&card->irq_lock);
385 card->halt = 0; 577 card->halt = 0;
578 card->eeh_state = 0;
386 579
387 spin_lock_irq(&card->irq_lock); 580 spin_lock_irq(&card->irq_lock);
388 rsxx_disable_ier_and_isr(card, CR_INTR_ALL); 581 rsxx_disable_ier_and_isr(card, CR_INTR_ALL);
@@ -593,6 +786,11 @@ static void rsxx_pci_shutdown(struct pci_dev *dev)
593 card_shutdown(card); 786 card_shutdown(card);
594} 787}
595 788
789static const struct pci_error_handlers rsxx_err_handler = {
790 .error_detected = rsxx_error_detected,
791 .slot_reset = rsxx_slot_reset,
792};
793
596static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = { 794static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = {
597 {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)}, 795 {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)},
598 {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)}, 796 {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)},
@@ -608,6 +806,7 @@ static struct pci_driver rsxx_pci_driver = {
608 .remove = rsxx_pci_remove, 806 .remove = rsxx_pci_remove,
609 .suspend = rsxx_pci_suspend, 807 .suspend = rsxx_pci_suspend,
610 .shutdown = rsxx_pci_shutdown, 808 .shutdown = rsxx_pci_shutdown,
809 .err_handler = &rsxx_err_handler,
611}; 810};
612 811
613static int __init rsxx_core_init(void) 812static int __init rsxx_core_init(void)
diff --git a/drivers/block/rsxx/cregs.c b/drivers/block/rsxx/cregs.c
index 0539a25877eb..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,19 +105,32 @@ 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 }
108
109 return 0;
100} 110}
101 111
102static 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)
103{ 113{
114 int st;
115
116 if (unlikely(card->eeh_state))
117 return;
118
104 iowrite32(cmd->addr, card->regmap + CREG_ADD); 119 iowrite32(cmd->addr, card->regmap + CREG_ADD);
105 iowrite32(cmd->cnt8, card->regmap + CREG_CNT); 120 iowrite32(cmd->cnt8, card->regmap + CREG_CNT);
106 121
107 if (cmd->op == CREG_OP_WRITE) { 122 if (cmd->op == CREG_OP_WRITE) {
108 if (cmd->buf) 123 if (cmd->buf) {
109 copy_to_creg_data(card, cmd->cnt8, 124 st = copy_to_creg_data(card, cmd->cnt8,
110 cmd->buf, cmd->stream); 125 cmd->buf, cmd->stream);
126 if (st)
127 return;
128 }
111 } 129 }
112 130
131 if (unlikely(card->eeh_state))
132 return;
133
113 /* Setting the valid bit will kick off the command. */ 134 /* Setting the valid bit will kick off the command. */
114 iowrite32(cmd->op, card->regmap + CREG_CMD); 135 iowrite32(cmd->op, card->regmap + CREG_CMD);
115} 136}
@@ -272,7 +293,7 @@ static void creg_cmd_done(struct work_struct *work)
272 goto creg_done; 293 goto creg_done;
273 } 294 }
274 295
275 copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); 296 st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream);
276 } 297 }
277 298
278creg_done: 299creg_done:
@@ -675,6 +696,32 @@ int rsxx_reg_access(struct rsxx_cardinfo *card,
675 return 0; 696 return 0;
676} 697}
677 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
678/*------------ Initialization & Setup --------------*/ 725/*------------ Initialization & Setup --------------*/
679int rsxx_creg_setup(struct rsxx_cardinfo *card) 726int rsxx_creg_setup(struct rsxx_cardinfo *card)
680{ 727{
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c
index efd75b55a670..60d344d002ec 100644
--- a/drivers/block/rsxx/dma.c
+++ b/drivers/block/rsxx/dma.c
@@ -81,9 +81,6 @@ enum rsxx_hw_status {
81 HW_STATUS_FAULT = 0x08, 81 HW_STATUS_FAULT = 0x08,
82}; 82};
83 83
84#define STATUS_BUFFER_SIZE8 4096
85#define COMMAND_BUFFER_SIZE8 4096
86
87static struct kmem_cache *rsxx_dma_pool; 84static struct kmem_cache *rsxx_dma_pool;
88 85
89struct dma_tracker { 86struct dma_tracker {
@@ -122,7 +119,7 @@ static unsigned int rsxx_get_dma_tgt(struct rsxx_cardinfo *card, u64 addr8)
122 return tgt; 119 return tgt;
123} 120}
124 121
125static void rsxx_dma_queue_reset(struct rsxx_cardinfo *card) 122void rsxx_dma_queue_reset(struct rsxx_cardinfo *card)
126{ 123{
127 /* Reset all DMA Command/Status Queues */ 124 /* Reset all DMA Command/Status Queues */
128 iowrite32(DMA_QUEUE_RESET, card->regmap + RESET); 125 iowrite32(DMA_QUEUE_RESET, card->regmap + RESET);
@@ -210,7 +207,8 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card)
210 u32 q_depth = 0; 207 u32 q_depth = 0;
211 u32 intr_coal; 208 u32 intr_coal;
212 209
213 if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE) 210 if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE ||
211 unlikely(card->eeh_state))
214 return; 212 return;
215 213
216 for (i = 0; i < card->n_targets; i++) 214 for (i = 0; i < card->n_targets; i++)
@@ -223,31 +221,26 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card)
223} 221}
224 222
225/*----------------- RSXX DMA Handling -------------------*/ 223/*----------------- RSXX DMA Handling -------------------*/
226static void rsxx_complete_dma(struct rsxx_cardinfo *card, 224static void rsxx_complete_dma(struct rsxx_dma_ctrl *ctrl,
227 struct rsxx_dma *dma, 225 struct rsxx_dma *dma,
228 unsigned int status) 226 unsigned int status)
229{ 227{
230 if (status & DMA_SW_ERR) 228 if (status & DMA_SW_ERR)
231 printk_ratelimited(KERN_ERR 229 ctrl->stats.dma_sw_err++;
232 "SW Error in DMA(cmd x%02x, laddr x%08x)\n",
233 dma->cmd, dma->laddr);
234 if (status & DMA_HW_FAULT) 230 if (status & DMA_HW_FAULT)
235 printk_ratelimited(KERN_ERR 231 ctrl->stats.dma_hw_fault++;
236 "HW Fault in DMA(cmd x%02x, laddr x%08x)\n",
237 dma->cmd, dma->laddr);
238 if (status & DMA_CANCELLED) 232 if (status & DMA_CANCELLED)
239 printk_ratelimited(KERN_ERR 233 ctrl->stats.dma_cancelled++;
240 "DMA Cancelled(cmd x%02x, laddr x%08x)\n",
241 dma->cmd, dma->laddr);
242 234
243 if (dma->dma_addr) 235 if (dma->dma_addr)
244 pci_unmap_page(card->dev, dma->dma_addr, get_dma_size(dma), 236 pci_unmap_page(ctrl->card->dev, dma->dma_addr,
237 get_dma_size(dma),
245 dma->cmd == HW_CMD_BLK_WRITE ? 238 dma->cmd == HW_CMD_BLK_WRITE ?
246 PCI_DMA_TODEVICE : 239 PCI_DMA_TODEVICE :
247 PCI_DMA_FROMDEVICE); 240 PCI_DMA_FROMDEVICE);
248 241
249 if (dma->cb) 242 if (dma->cb)
250 dma->cb(card, dma->cb_data, status ? 1 : 0); 243 dma->cb(ctrl->card, dma->cb_data, status ? 1 : 0);
251 244
252 kmem_cache_free(rsxx_dma_pool, dma); 245 kmem_cache_free(rsxx_dma_pool, dma);
253} 246}
@@ -330,14 +323,15 @@ static void rsxx_handle_dma_error(struct rsxx_dma_ctrl *ctrl,
330 if (requeue_cmd) 323 if (requeue_cmd)
331 rsxx_requeue_dma(ctrl, dma); 324 rsxx_requeue_dma(ctrl, dma);
332 else 325 else
333 rsxx_complete_dma(ctrl->card, dma, status); 326 rsxx_complete_dma(ctrl, dma, status);
334} 327}
335 328
336static void dma_engine_stalled(unsigned long data) 329static void dma_engine_stalled(unsigned long data)
337{ 330{
338 struct rsxx_dma_ctrl *ctrl = (struct rsxx_dma_ctrl *)data; 331 struct rsxx_dma_ctrl *ctrl = (struct rsxx_dma_ctrl *)data;
339 332
340 if (atomic_read(&ctrl->stats.hw_q_depth) == 0) 333 if (atomic_read(&ctrl->stats.hw_q_depth) == 0 ||
334 unlikely(ctrl->card->eeh_state))
341 return; 335 return;
342 336
343 if (ctrl->cmd.idx != ioread32(ctrl->regmap + SW_CMD_IDX)) { 337 if (ctrl->cmd.idx != ioread32(ctrl->regmap + SW_CMD_IDX)) {
@@ -369,7 +363,8 @@ static void rsxx_issue_dmas(struct work_struct *work)
369 ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work); 363 ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work);
370 hw_cmd_buf = ctrl->cmd.buf; 364 hw_cmd_buf = ctrl->cmd.buf;
371 365
372 if (unlikely(ctrl->card->halt)) 366 if (unlikely(ctrl->card->halt) ||
367 unlikely(ctrl->card->eeh_state))
373 return; 368 return;
374 369
375 while (1) { 370 while (1) {
@@ -397,7 +392,7 @@ static void rsxx_issue_dmas(struct work_struct *work)
397 */ 392 */
398 if (unlikely(ctrl->card->dma_fault)) { 393 if (unlikely(ctrl->card->dma_fault)) {
399 push_tracker(ctrl->trackers, tag); 394 push_tracker(ctrl->trackers, tag);
400 rsxx_complete_dma(ctrl->card, dma, DMA_CANCELLED); 395 rsxx_complete_dma(ctrl, dma, DMA_CANCELLED);
401 continue; 396 continue;
402 } 397 }
403 398
@@ -435,6 +430,12 @@ static void rsxx_issue_dmas(struct work_struct *work)
435 atomic_add(cmds_pending, &ctrl->stats.hw_q_depth); 430 atomic_add(cmds_pending, &ctrl->stats.hw_q_depth);
436 mod_timer(&ctrl->activity_timer, 431 mod_timer(&ctrl->activity_timer,
437 jiffies + DMA_ACTIVITY_TIMEOUT); 432 jiffies + DMA_ACTIVITY_TIMEOUT);
433
434 if (unlikely(ctrl->card->eeh_state)) {
435 del_timer_sync(&ctrl->activity_timer);
436 return;
437 }
438
438 iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX); 439 iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
439 } 440 }
440} 441}
@@ -453,7 +454,8 @@ static void rsxx_dma_done(struct work_struct *work)
453 hw_st_buf = ctrl->status.buf; 454 hw_st_buf = ctrl->status.buf;
454 455
455 if (unlikely(ctrl->card->halt) || 456 if (unlikely(ctrl->card->halt) ||
456 unlikely(ctrl->card->dma_fault)) 457 unlikely(ctrl->card->dma_fault) ||
458 unlikely(ctrl->card->eeh_state))
457 return; 459 return;
458 460
459 count = le16_to_cpu(hw_st_buf[ctrl->status.idx].count); 461 count = le16_to_cpu(hw_st_buf[ctrl->status.idx].count);
@@ -498,7 +500,7 @@ static void rsxx_dma_done(struct work_struct *work)
498 if (status) 500 if (status)
499 rsxx_handle_dma_error(ctrl, dma, status); 501 rsxx_handle_dma_error(ctrl, dma, status);
500 else 502 else
501 rsxx_complete_dma(ctrl->card, dma, 0); 503 rsxx_complete_dma(ctrl, dma, 0);
502 504
503 push_tracker(ctrl->trackers, tag); 505 push_tracker(ctrl->trackers, tag);
504 506
@@ -717,20 +719,54 @@ bvec_err:
717 719
718 720
719/*----------------- DMA Engine Initialization & Setup -------------------*/ 721/*----------------- DMA Engine Initialization & Setup -------------------*/
722int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl)
723{
724 ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8,
725 &ctrl->status.dma_addr);
726 ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8,
727 &ctrl->cmd.dma_addr);
728 if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL)
729 return -ENOMEM;
730
731 memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8);
732 iowrite32(lower_32_bits(ctrl->status.dma_addr),
733 ctrl->regmap + SB_ADD_LO);
734 iowrite32(upper_32_bits(ctrl->status.dma_addr),
735 ctrl->regmap + SB_ADD_HI);
736
737 memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8);
738 iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO);
739 iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI);
740
741 ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT);
742 if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) {
743 dev_crit(&dev->dev, "Failed reading status cnt x%x\n",
744 ctrl->status.idx);
745 return -EINVAL;
746 }
747 iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT);
748 iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT);
749
750 ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX);
751 if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) {
752 dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n",
753 ctrl->status.idx);
754 return -EINVAL;
755 }
756 iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX);
757 iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
758
759 return 0;
760}
761
720static int rsxx_dma_ctrl_init(struct pci_dev *dev, 762static int rsxx_dma_ctrl_init(struct pci_dev *dev,
721 struct rsxx_dma_ctrl *ctrl) 763 struct rsxx_dma_ctrl *ctrl)
722{ 764{
723 int i; 765 int i;
766 int st;
724 767
725 memset(&ctrl->stats, 0, sizeof(ctrl->stats)); 768 memset(&ctrl->stats, 0, sizeof(ctrl->stats));
726 769
727 ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8,
728 &ctrl->status.dma_addr);
729 ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8,
730 &ctrl->cmd.dma_addr);
731 if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL)
732 return -ENOMEM;
733
734 ctrl->trackers = vmalloc(DMA_TRACKER_LIST_SIZE8); 770 ctrl->trackers = vmalloc(DMA_TRACKER_LIST_SIZE8);
735 if (!ctrl->trackers) 771 if (!ctrl->trackers)
736 return -ENOMEM; 772 return -ENOMEM;
@@ -760,33 +796,9 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev,
760 INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas); 796 INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas);
761 INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done); 797 INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done);
762 798
763 memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8); 799 st = rsxx_hw_buffers_init(dev, ctrl);
764 iowrite32(lower_32_bits(ctrl->status.dma_addr), 800 if (st)
765 ctrl->regmap + SB_ADD_LO); 801 return st;
766 iowrite32(upper_32_bits(ctrl->status.dma_addr),
767 ctrl->regmap + SB_ADD_HI);
768
769 memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8);
770 iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO);
771 iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI);
772
773 ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT);
774 if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) {
775 dev_crit(&dev->dev, "Failed reading status cnt x%x\n",
776 ctrl->status.idx);
777 return -EINVAL;
778 }
779 iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT);
780 iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT);
781
782 ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX);
783 if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) {
784 dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n",
785 ctrl->status.idx);
786 return -EINVAL;
787 }
788 iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX);
789 iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
790 802
791 return 0; 803 return 0;
792} 804}
@@ -822,7 +834,7 @@ static int rsxx_dma_stripe_setup(struct rsxx_cardinfo *card,
822 return 0; 834 return 0;
823} 835}
824 836
825static int rsxx_dma_configure(struct rsxx_cardinfo *card) 837int rsxx_dma_configure(struct rsxx_cardinfo *card)
826{ 838{
827 u32 intr_coal; 839 u32 intr_coal;
828 840
@@ -968,6 +980,94 @@ void rsxx_dma_destroy(struct rsxx_cardinfo *card)
968 } 980 }
969} 981}
970 982
983void rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
984{
985 int i;
986 int j;
987 int cnt;
988 struct rsxx_dma *dma;
989 struct list_head issued_dmas[card->n_targets];
990
991 for (i = 0; i < card->n_targets; i++) {
992 INIT_LIST_HEAD(&issued_dmas[i]);
993 cnt = 0;
994 for (j = 0; j < RSXX_MAX_OUTSTANDING_CMDS; j++) {
995 dma = get_tracker_dma(card->ctrl[i].trackers, j);
996 if (dma == NULL)
997 continue;
998
999 if (dma->cmd == HW_CMD_BLK_WRITE)
1000 card->ctrl[i].stats.writes_issued--;
1001 else if (dma->cmd == HW_CMD_BLK_DISCARD)
1002 card->ctrl[i].stats.discards_issued--;
1003 else
1004 card->ctrl[i].stats.reads_issued--;
1005
1006 list_add_tail(&dma->list, &issued_dmas[i]);
1007 push_tracker(card->ctrl[i].trackers, j);
1008 cnt++;
1009 }
1010
1011 spin_lock(&card->ctrl[i].queue_lock);
1012 list_splice(&issued_dmas[i], &card->ctrl[i].queue);
1013
1014 atomic_sub(cnt, &card->ctrl[i].stats.hw_q_depth);
1015 card->ctrl[i].stats.sw_q_depth += cnt;
1016 card->ctrl[i].e_cnt = 0;
1017
1018 list_for_each_entry(dma, &card->ctrl[i].queue, list) {
1019 if (dma->dma_addr)
1020 pci_unmap_page(card->dev, dma->dma_addr,
1021 get_dma_size(dma),
1022 dma->cmd == HW_CMD_BLK_WRITE ?
1023 PCI_DMA_TODEVICE :
1024 PCI_DMA_FROMDEVICE);
1025 }
1026 spin_unlock(&card->ctrl[i].queue_lock);
1027 }
1028}
1029
1030void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card)
1031{
1032 struct rsxx_dma *dma;
1033 struct rsxx_dma *tmp;
1034 int i;
1035
1036 for (i = 0; i < card->n_targets; i++) {
1037 spin_lock(&card->ctrl[i].queue_lock);
1038 list_for_each_entry_safe(dma, tmp, &card->ctrl[i].queue, list) {
1039 list_del(&dma->list);
1040
1041 rsxx_complete_dma(&card->ctrl[i], dma, DMA_CANCELLED);
1042 }
1043 spin_unlock(&card->ctrl[i].queue_lock);
1044 }
1045}
1046
1047int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card)
1048{
1049 struct rsxx_dma *dma;
1050 struct rsxx_dma *tmp;
1051 int i;
1052
1053 for (i = 0; i < card->n_targets; i++) {
1054 spin_lock(&card->ctrl[i].queue_lock);
1055 list_for_each_entry(dma, &card->ctrl[i].queue, list) {
1056 dma->dma_addr = pci_map_page(card->dev, dma->page,
1057 dma->pg_off, get_dma_size(dma),
1058 dma->cmd == HW_CMD_BLK_WRITE ?
1059 PCI_DMA_TODEVICE :
1060 PCI_DMA_FROMDEVICE);
1061 if (!dma->dma_addr) {
1062 kmem_cache_free(rsxx_dma_pool, dma);
1063 return -ENOMEM;
1064 }
1065 }
1066 spin_unlock(&card->ctrl[i].queue_lock);
1067 }
1068
1069 return 0;
1070}
971 1071
972int rsxx_dma_init(void) 1072int rsxx_dma_init(void)
973{ 1073{
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h
index f5a95f75bd57..8a7ac87f1dc5 100644
--- a/drivers/block/rsxx/rsxx_priv.h
+++ b/drivers/block/rsxx/rsxx_priv.h
@@ -64,6 +64,9 @@ struct proc_cmd;
64#define RSXX_MAX_OUTSTANDING_CMDS 255 64#define RSXX_MAX_OUTSTANDING_CMDS 255
65#define RSXX_CS_IDX_MASK 0xff 65#define RSXX_CS_IDX_MASK 0xff
66 66
67#define STATUS_BUFFER_SIZE8 4096
68#define COMMAND_BUFFER_SIZE8 4096
69
67#define RSXX_MAX_TARGETS 8 70#define RSXX_MAX_TARGETS 8
68 71
69struct dma_tracker_list; 72struct dma_tracker_list;
@@ -88,6 +91,9 @@ struct rsxx_dma_stats {
88 u32 discards_failed; 91 u32 discards_failed;
89 u32 done_rescheduled; 92 u32 done_rescheduled;
90 u32 issue_rescheduled; 93 u32 issue_rescheduled;
94 u32 dma_sw_err;
95 u32 dma_hw_fault;
96 u32 dma_cancelled;
91 u32 sw_q_depth; /* Number of DMAs on the SW queue. */ 97 u32 sw_q_depth; /* Number of DMAs on the SW queue. */
92 atomic_t hw_q_depth; /* Number of DMAs queued to HW. */ 98 atomic_t hw_q_depth; /* Number of DMAs queued to HW. */
93}; 99};
@@ -113,6 +119,7 @@ struct rsxx_dma_ctrl {
113struct rsxx_cardinfo { 119struct rsxx_cardinfo {
114 struct pci_dev *dev; 120 struct pci_dev *dev;
115 unsigned int halt; 121 unsigned int halt;
122 unsigned int eeh_state;
116 123
117 void __iomem *regmap; 124 void __iomem *regmap;
118 spinlock_t irq_lock; 125 spinlock_t irq_lock;
@@ -221,6 +228,7 @@ enum rsxx_pci_regmap {
221 PERF_RD512_HI = 0xac, 228 PERF_RD512_HI = 0xac,
222 PERF_WR512_LO = 0xb0, 229 PERF_WR512_LO = 0xb0,
223 PERF_WR512_HI = 0xb4, 230 PERF_WR512_HI = 0xb4,
231 PCI_RECONFIG = 0xb8,
224}; 232};
225 233
226enum rsxx_intr { 234enum rsxx_intr {
@@ -234,6 +242,8 @@ enum rsxx_intr {
234 CR_INTR_DMA5 = 0x00000080, 242 CR_INTR_DMA5 = 0x00000080,
235 CR_INTR_DMA6 = 0x00000100, 243 CR_INTR_DMA6 = 0x00000100,
236 CR_INTR_DMA7 = 0x00000200, 244 CR_INTR_DMA7 = 0x00000200,
245 CR_INTR_ALL_C = 0x0000003f,
246 CR_INTR_ALL_G = 0x000003ff,
237 CR_INTR_DMA_ALL = 0x000003f5, 247 CR_INTR_DMA_ALL = 0x000003f5,
238 CR_INTR_ALL = 0xffffffff, 248 CR_INTR_ALL = 0xffffffff,
239}; 249};
@@ -250,8 +260,14 @@ enum rsxx_pci_reset {
250 DMA_QUEUE_RESET = 0x00000001, 260 DMA_QUEUE_RESET = 0x00000001,
251}; 261};
252 262
263enum rsxx_hw_fifo_flush {
264 RSXX_FLUSH_BUSY = 0x00000002,
265 RSXX_FLUSH_TIMEOUT = 0x00000004,
266};
267
253enum rsxx_pci_revision { 268enum rsxx_pci_revision {
254 RSXX_DISCARD_SUPPORT = 2, 269 RSXX_DISCARD_SUPPORT = 2,
270 RSXX_EEH_SUPPORT = 3,
255}; 271};
256 272
257enum rsxx_creg_cmd { 273enum rsxx_creg_cmd {
@@ -357,11 +373,17 @@ int rsxx_dma_setup(struct rsxx_cardinfo *card);
357void rsxx_dma_destroy(struct rsxx_cardinfo *card); 373void rsxx_dma_destroy(struct rsxx_cardinfo *card);
358int rsxx_dma_init(void); 374int rsxx_dma_init(void);
359void rsxx_dma_cleanup(void); 375void rsxx_dma_cleanup(void);
376void rsxx_dma_queue_reset(struct rsxx_cardinfo *card);
377int rsxx_dma_configure(struct rsxx_cardinfo *card);
360int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, 378int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
361 struct bio *bio, 379 struct bio *bio,
362 atomic_t *n_dmas, 380 atomic_t *n_dmas,
363 rsxx_dma_cb cb, 381 rsxx_dma_cb cb,
364 void *cb_data); 382 void *cb_data);
383int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl);
384void rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card);
385void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card);
386int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card);
365 387
366/***** cregs.c *****/ 388/***** cregs.c *****/
367int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, 389int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr,
@@ -386,10 +408,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card);
386void rsxx_creg_destroy(struct rsxx_cardinfo *card); 408void rsxx_creg_destroy(struct rsxx_cardinfo *card);
387int rsxx_creg_init(void); 409int rsxx_creg_init(void);
388void rsxx_creg_cleanup(void); 410void rsxx_creg_cleanup(void);
389
390int rsxx_reg_access(struct rsxx_cardinfo *card, 411int rsxx_reg_access(struct rsxx_cardinfo *card,
391 struct rsxx_reg_access __user *ucmd, 412 struct rsxx_reg_access __user *ucmd,
392 int read); 413 int read);
414void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card);
415void rsxx_kick_creg_queue(struct rsxx_cardinfo *card);
393 416
394 417
395 418