diff options
-rw-r--r-- | arch/powerpc/include/asm/eeh.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 32 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 40 |
3 files changed, 57 insertions, 17 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index daaad91ed576..d60f99814ffb 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -102,6 +102,8 @@ struct eeh_ops { | |||
102 | int (*wait_state)(struct device_node *dn, int max_wait); | 102 | int (*wait_state)(struct device_node *dn, int max_wait); |
103 | int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len); | 103 | int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len); |
104 | int (*configure_bridge)(struct device_node *dn); | 104 | int (*configure_bridge)(struct device_node *dn); |
105 | int (*read_config)(struct device_node *dn, int where, int size, u32 *val); | ||
106 | int (*write_config)(struct device_node *dn, int where, int size, u32 val); | ||
105 | }; | 107 | }; |
106 | 108 | ||
107 | extern struct eeh_ops *eeh_ops; | 109 | extern struct eeh_ops *eeh_ops; |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 1d08cd76e68d..8011088392d3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -141,11 +141,11 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
141 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); | 141 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); |
142 | printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name); | 142 | printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name); |
143 | 143 | ||
144 | rtas_read_config(PCI_DN(dn), PCI_VENDOR_ID, 4, &cfg); | 144 | eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg); |
145 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); | 145 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); |
146 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); | 146 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); |
147 | 147 | ||
148 | rtas_read_config(PCI_DN(dn), PCI_COMMAND, 4, &cfg); | 148 | eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg); |
149 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | 149 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); |
150 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); | 150 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); |
151 | 151 | ||
@@ -156,11 +156,11 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
156 | 156 | ||
157 | /* Gather bridge-specific registers */ | 157 | /* Gather bridge-specific registers */ |
158 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | 158 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { |
159 | rtas_read_config(PCI_DN(dn), PCI_SEC_STATUS, 2, &cfg); | 159 | eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg); |
160 | n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); | 160 | n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); |
161 | printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); | 161 | printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); |
162 | 162 | ||
163 | rtas_read_config(PCI_DN(dn), PCI_BRIDGE_CONTROL, 2, &cfg); | 163 | eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg); |
164 | n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); | 164 | n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); |
165 | printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); | 165 | printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); |
166 | } | 166 | } |
@@ -168,11 +168,11 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
168 | /* Dump out the PCI-X command and status regs */ | 168 | /* Dump out the PCI-X command and status regs */ |
169 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 169 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
170 | if (cap) { | 170 | if (cap) { |
171 | rtas_read_config(PCI_DN(dn), cap, 4, &cfg); | 171 | eeh_ops->read_config(dn, cap, 4, &cfg); |
172 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); | 172 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); |
173 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); | 173 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); |
174 | 174 | ||
175 | rtas_read_config(PCI_DN(dn), cap+4, 4, &cfg); | 175 | eeh_ops->read_config(dn, cap+4, 4, &cfg); |
176 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); | 176 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); |
177 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); | 177 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); |
178 | } | 178 | } |
@@ -185,7 +185,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
185 | "EEH: PCI-E capabilities and status follow:\n"); | 185 | "EEH: PCI-E capabilities and status follow:\n"); |
186 | 186 | ||
187 | for (i=0; i<=8; i++) { | 187 | for (i=0; i<=8; i++) { |
188 | rtas_read_config(PCI_DN(dn), cap+4*i, 4, &cfg); | 188 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
189 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 189 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
190 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | 190 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); |
191 | } | 191 | } |
@@ -197,7 +197,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
197 | "EEH: PCI-E AER capability register set follows:\n"); | 197 | "EEH: PCI-E AER capability register set follows:\n"); |
198 | 198 | ||
199 | for (i=0; i<14; i++) { | 199 | for (i=0; i<14; i++) { |
200 | rtas_read_config(PCI_DN(dn), cap+4*i, 4, &cfg); | 200 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
201 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 201 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
202 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); | 202 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); |
203 | } | 203 | } |
@@ -746,28 +746,28 @@ static inline void eeh_restore_one_device_bars(struct eeh_dev *edev) | |||
746 | return; | 746 | return; |
747 | 747 | ||
748 | for (i=4; i<10; i++) { | 748 | for (i=4; i<10; i++) { |
749 | rtas_write_config(PCI_DN(dn), i*4, 4, edev->config_space[i]); | 749 | eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); |
750 | } | 750 | } |
751 | 751 | ||
752 | /* 12 == Expansion ROM Address */ | 752 | /* 12 == Expansion ROM Address */ |
753 | rtas_write_config(PCI_DN(dn), 12*4, 4, edev->config_space[12]); | 753 | eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]); |
754 | 754 | ||
755 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | 755 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) |
756 | #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) | 756 | #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) |
757 | 757 | ||
758 | rtas_write_config(PCI_DN(dn), PCI_CACHE_LINE_SIZE, 1, | 758 | eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, |
759 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); | 759 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); |
760 | 760 | ||
761 | rtas_write_config(PCI_DN(dn), PCI_LATENCY_TIMER, 1, | 761 | eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, |
762 | SAVED_BYTE(PCI_LATENCY_TIMER)); | 762 | SAVED_BYTE(PCI_LATENCY_TIMER)); |
763 | 763 | ||
764 | /* max latency, min grant, interrupt pin and line */ | 764 | /* max latency, min grant, interrupt pin and line */ |
765 | rtas_write_config(PCI_DN(dn), 15*4, 4, edev->config_space[15]); | 765 | eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); |
766 | 766 | ||
767 | /* Restore PERR & SERR bits, some devices require it, | 767 | /* Restore PERR & SERR bits, some devices require it, |
768 | * don't touch the other command bits | 768 | * don't touch the other command bits |
769 | */ | 769 | */ |
770 | rtas_read_config(PCI_DN(dn), PCI_COMMAND, 4, &cmd); | 770 | eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd); |
771 | if (edev->config_space[1] & PCI_COMMAND_PARITY) | 771 | if (edev->config_space[1] & PCI_COMMAND_PARITY) |
772 | cmd |= PCI_COMMAND_PARITY; | 772 | cmd |= PCI_COMMAND_PARITY; |
773 | else | 773 | else |
@@ -776,7 +776,7 @@ static inline void eeh_restore_one_device_bars(struct eeh_dev *edev) | |||
776 | cmd |= PCI_COMMAND_SERR; | 776 | cmd |= PCI_COMMAND_SERR; |
777 | else | 777 | else |
778 | cmd &= ~PCI_COMMAND_SERR; | 778 | cmd &= ~PCI_COMMAND_SERR; |
779 | rtas_write_config(PCI_DN(dn), PCI_COMMAND, 4, cmd); | 779 | eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd); |
780 | } | 780 | } |
781 | 781 | ||
782 | /** | 782 | /** |
@@ -818,7 +818,7 @@ static void eeh_save_bars(struct eeh_dev *edev) | |||
818 | dn = eeh_dev_to_of_node(edev); | 818 | dn = eeh_dev_to_of_node(edev); |
819 | 819 | ||
820 | for (i = 0; i < 16; i++) | 820 | for (i = 0; i < 16; i++) |
821 | rtas_read_config(PCI_DN(dn), i * 4, 4, &edev->config_space[i]); | 821 | eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]); |
822 | } | 822 | } |
823 | 823 | ||
824 | /** | 824 | /** |
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 36a1af1d1140..8752f79a6af8 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -503,6 +503,42 @@ static int pseries_eeh_configure_bridge(struct device_node *dn) | |||
503 | return ret; | 503 | return ret; |
504 | } | 504 | } |
505 | 505 | ||
506 | /** | ||
507 | * pseries_eeh_read_config - Read PCI config space | ||
508 | * @dn: device node | ||
509 | * @where: PCI address | ||
510 | * @size: size to read | ||
511 | * @val: return value | ||
512 | * | ||
513 | * Read config space from the speicifed device | ||
514 | */ | ||
515 | static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val) | ||
516 | { | ||
517 | struct pci_dn *pdn; | ||
518 | |||
519 | pdn = PCI_DN(dn); | ||
520 | |||
521 | return rtas_read_config(pdn, where, size, val); | ||
522 | } | ||
523 | |||
524 | /** | ||
525 | * pseries_eeh_write_config - Write PCI config space | ||
526 | * @dn: device node | ||
527 | * @where: PCI address | ||
528 | * @size: size to write | ||
529 | * @val: value to be written | ||
530 | * | ||
531 | * Write config space to the specified device | ||
532 | */ | ||
533 | static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val) | ||
534 | { | ||
535 | struct pci_dn *pdn; | ||
536 | |||
537 | pdn = PCI_DN(dn); | ||
538 | |||
539 | return rtas_write_config(pdn, where, size, val); | ||
540 | } | ||
541 | |||
506 | static struct eeh_ops pseries_eeh_ops = { | 542 | static struct eeh_ops pseries_eeh_ops = { |
507 | .name = "pseries", | 543 | .name = "pseries", |
508 | .init = pseries_eeh_init, | 544 | .init = pseries_eeh_init, |
@@ -512,7 +548,9 @@ static struct eeh_ops pseries_eeh_ops = { | |||
512 | .reset = pseries_eeh_reset, | 548 | .reset = pseries_eeh_reset, |
513 | .wait_state = pseries_eeh_wait_state, | 549 | .wait_state = pseries_eeh_wait_state, |
514 | .get_log = pseries_eeh_get_log, | 550 | .get_log = pseries_eeh_get_log, |
515 | .configure_bridge = pseries_eeh_configure_bridge | 551 | .configure_bridge = pseries_eeh_configure_bridge, |
552 | .read_config = pseries_eeh_read_config, | ||
553 | .write_config = pseries_eeh_write_config | ||
516 | }; | 554 | }; |
517 | 555 | ||
518 | /** | 556 | /** |