diff options
author | Philip J Kelleher <pjk1939@linux.vnet.ibm.com> | 2013-03-16 03:22:25 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-03-16 03:22:25 -0400 |
commit | c95246c3a2ac796cfa43e76200ede59cb4a1644f (patch) | |
tree | 18a4a1a6b3ee78c5f8d646831edaecba1f0012ad | |
parent | 1ebfd109822ea35b71aee4efe9ddc2e1b9ac0ed7 (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.c | 203 | ||||
-rw-r--r-- | drivers/block/rsxx/cregs.c | 59 | ||||
-rw-r--r-- | drivers/block/rsxx/dma.c | 216 | ||||
-rw-r--r-- | drivers/block/rsxx/rsxx_priv.h | 25 |
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); | |||
52 | static DEFINE_SPINLOCK(rsxx_ida_lock); | 53 | static DEFINE_SPINLOCK(rsxx_ida_lock); |
53 | 54 | ||
54 | /*----------------- Interrupt Control & Handling -------------------*/ | 55 | /*----------------- Interrupt Control & Handling -------------------*/ |
56 | |||
57 | static void rsxx_mask_interrupts(struct rsxx_cardinfo *card) | ||
58 | { | ||
59 | card->isr_mask = 0; | ||
60 | card->ier_mask = 0; | ||
61 | } | ||
62 | |||
55 | static void __enable_intr(unsigned int *mask, unsigned int intr) | 63 | static 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 | */ |
72 | void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr) | 80 | void 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 | ||
81 | void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr) | 90 | void 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) | |||
87 | void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, | 99 | void 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, | |||
97 | void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card, | 110 | void 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 | ||
326 | static 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 | |||
361 | static 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 | |||
376 | static 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 | |||
399 | static 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 | |||
414 | static 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 | |||
479 | failed_hw_buffers_init: | ||
480 | failed_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 | } | ||
493 | failed_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 | ||
789 | static const struct pci_error_handlers rsxx_err_handler = { | ||
790 | .error_detected = rsxx_error_detected, | ||
791 | .slot_reset = rsxx_slot_reset, | ||
792 | }; | ||
793 | |||
596 | static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = { | 794 | static 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 | ||
613 | static int __init rsxx_core_init(void) | 812 | static 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 | ||
61 | static void copy_to_creg_data(struct rsxx_cardinfo *card, | 61 | static 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 | ||
82 | static void copy_from_creg_data(struct rsxx_cardinfo *card, | 87 | static 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 | ||
102 | static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) | 112 | static 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 | ||
278 | creg_done: | 299 | creg_done: |
@@ -675,6 +696,32 @@ int rsxx_reg_access(struct rsxx_cardinfo *card, | |||
675 | return 0; | 696 | return 0; |
676 | } | 697 | } |
677 | 698 | ||
699 | void 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 | |||
717 | void 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 --------------*/ |
679 | int rsxx_creg_setup(struct rsxx_cardinfo *card) | 726 | int 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 | |||
87 | static struct kmem_cache *rsxx_dma_pool; | 84 | static struct kmem_cache *rsxx_dma_pool; |
88 | 85 | ||
89 | struct dma_tracker { | 86 | struct 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 | ||
125 | static void rsxx_dma_queue_reset(struct rsxx_cardinfo *card) | 122 | void 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 -------------------*/ |
226 | static void rsxx_complete_dma(struct rsxx_cardinfo *card, | 224 | static 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 | ||
336 | static void dma_engine_stalled(unsigned long data) | 329 | static 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 -------------------*/ |
722 | int 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 | |||
720 | static int rsxx_dma_ctrl_init(struct pci_dev *dev, | 762 | static 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 | ||
825 | static int rsxx_dma_configure(struct rsxx_cardinfo *card) | 837 | int 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 | ||
983 | void 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 | |||
1030 | void 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 | |||
1047 | int 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 | ||
972 | int rsxx_dma_init(void) | 1072 | int 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 | ||
69 | struct dma_tracker_list; | 72 | struct 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 { | |||
113 | struct rsxx_cardinfo { | 119 | struct 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 | ||
226 | enum rsxx_intr { | 234 | enum 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 | ||
263 | enum rsxx_hw_fifo_flush { | ||
264 | RSXX_FLUSH_BUSY = 0x00000002, | ||
265 | RSXX_FLUSH_TIMEOUT = 0x00000004, | ||
266 | }; | ||
267 | |||
253 | enum rsxx_pci_revision { | 268 | enum rsxx_pci_revision { |
254 | RSXX_DISCARD_SUPPORT = 2, | 269 | RSXX_DISCARD_SUPPORT = 2, |
270 | RSXX_EEH_SUPPORT = 3, | ||
255 | }; | 271 | }; |
256 | 272 | ||
257 | enum rsxx_creg_cmd { | 273 | enum rsxx_creg_cmd { |
@@ -357,11 +373,17 @@ int rsxx_dma_setup(struct rsxx_cardinfo *card); | |||
357 | void rsxx_dma_destroy(struct rsxx_cardinfo *card); | 373 | void rsxx_dma_destroy(struct rsxx_cardinfo *card); |
358 | int rsxx_dma_init(void); | 374 | int rsxx_dma_init(void); |
359 | void rsxx_dma_cleanup(void); | 375 | void rsxx_dma_cleanup(void); |
376 | void rsxx_dma_queue_reset(struct rsxx_cardinfo *card); | ||
377 | int rsxx_dma_configure(struct rsxx_cardinfo *card); | ||
360 | int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, | 378 | int 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); |
383 | int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl); | ||
384 | void rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card); | ||
385 | void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card); | ||
386 | int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card); | ||
365 | 387 | ||
366 | /***** cregs.c *****/ | 388 | /***** cregs.c *****/ |
367 | int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, | 389 | int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, |
@@ -386,10 +408,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card); | |||
386 | void rsxx_creg_destroy(struct rsxx_cardinfo *card); | 408 | void rsxx_creg_destroy(struct rsxx_cardinfo *card); |
387 | int rsxx_creg_init(void); | 409 | int rsxx_creg_init(void); |
388 | void rsxx_creg_cleanup(void); | 410 | void rsxx_creg_cleanup(void); |
389 | |||
390 | int rsxx_reg_access(struct rsxx_cardinfo *card, | 411 | int 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); |
414 | void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card); | ||
415 | void rsxx_kick_creg_queue(struct rsxx_cardinfo *card); | ||
393 | 416 | ||
394 | 417 | ||
395 | 418 | ||