~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sh/drivers/pci/common.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <linux/pci.h>
  3 #include <linux/interrupt.h>
  4 #include <linux/timer.h>
  5 #include <linux/kernel.h>
  6 
  7 /*
  8  * These functions are used early on before PCI scanning is done
  9  * and all of the pci_dev and pci_bus structures have been created.
 10  */
 11 static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
 12         int top_bus, int busnr, int devfn)
 13 {
 14         static struct pci_dev dev;
 15         static struct pci_bus bus;
 16 
 17         dev.bus = &bus;
 18         dev.sysdata = hose;
 19         dev.devfn = devfn;
 20         bus.number = busnr;
 21         bus.sysdata = hose;
 22         bus.ops = hose->pci_ops;
 23 
 24         if(busnr != top_bus)
 25                 /* Fake a parent bus structure. */
 26                 bus.parent = &bus;
 27         else
 28                 bus.parent = NULL;
 29 
 30         return &dev;
 31 }
 32 
 33 #define EARLY_PCI_OP(rw, size, type)                                    \
 34 int __init early_##rw##_config_##size(struct pci_channel *hose,         \
 35         int top_bus, int bus, int devfn, int offset, type value)        \
 36 {                                                                       \
 37         return pci_##rw##_config_##size(                                \
 38                 fake_pci_dev(hose, top_bus, bus, devfn),                \
 39                 offset, value);                                         \
 40 }
 41 
 42 EARLY_PCI_OP(read, byte, u8 *)
 43 EARLY_PCI_OP(read, word, u16 *)
 44 EARLY_PCI_OP(read, dword, u32 *)
 45 EARLY_PCI_OP(write, byte, u8)
 46 EARLY_PCI_OP(write, word, u16)
 47 EARLY_PCI_OP(write, dword, u32)
 48 
 49 int __init pci_is_66mhz_capable(struct pci_channel *hose,
 50                                 int top_bus, int current_bus)
 51 {
 52         u32 pci_devfn;
 53         u16 vid;
 54         int cap66 = -1;
 55         u16 stat;
 56         int ret;
 57 
 58         pr_info("PCI: Checking 66MHz capabilities...\n");
 59 
 60         for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
 61                 if (PCI_FUNC(pci_devfn))
 62                         continue;
 63                 ret = early_read_config_word(hose, top_bus, current_bus,
 64                                              pci_devfn, PCI_VENDOR_ID, &vid);
 65                 if (ret != PCIBIOS_SUCCESSFUL)
 66                         continue;
 67                 if (PCI_POSSIBLE_ERROR(vid))
 68                         continue;
 69 
 70                 /* check 66MHz capability */
 71                 if (cap66 < 0)
 72                         cap66 = 1;
 73                 if (cap66) {
 74                         early_read_config_word(hose, top_bus, current_bus,
 75                                                pci_devfn, PCI_STATUS, &stat);
 76                         if (!(stat & PCI_STATUS_66MHZ)) {
 77                                 printk(KERN_DEBUG
 78                                        "PCI: %02x:%02x not 66MHz capable.\n",
 79                                        current_bus, pci_devfn);
 80                                 cap66 = 0;
 81                                 break;
 82                         }
 83                 }
 84         }
 85 
 86         return cap66 > 0;
 87 }
 88 
 89 static void pcibios_enable_err(struct timer_list *t)
 90 {
 91         struct pci_channel *hose = from_timer(hose, t, err_timer);
 92 
 93         del_timer(&hose->err_timer);
 94         printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
 95         enable_irq(hose->err_irq);
 96 }
 97 
 98 static void pcibios_enable_serr(struct timer_list *t)
 99 {
100         struct pci_channel *hose = from_timer(hose, t, serr_timer);
101 
102         del_timer(&hose->serr_timer);
103         printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
104         enable_irq(hose->serr_irq);
105 }
106 
107 void pcibios_enable_timers(struct pci_channel *hose)
108 {
109         if (hose->err_irq) {
110                 timer_setup(&hose->err_timer, pcibios_enable_err, 0);
111         }
112 
113         if (hose->serr_irq) {
114                 timer_setup(&hose->serr_timer, pcibios_enable_serr, 0);
115         }
116 }
117 
118 /*
119  * A simple handler for the regular PCI status errors, called from IRQ
120  * context.
121  */
122 unsigned int pcibios_handle_status_errors(unsigned long addr,
123                                           unsigned int status,
124                                           struct pci_channel *hose)
125 {
126         unsigned int cmd = 0;
127 
128         if (status & PCI_STATUS_REC_MASTER_ABORT) {
129                 printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
130                 cmd |= PCI_STATUS_REC_MASTER_ABORT;
131         }
132 
133         if (status & PCI_STATUS_REC_TARGET_ABORT) {
134                 printk(KERN_DEBUG "PCI: target abort: ");
135                 pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
136                                       PCI_STATUS_SIG_TARGET_ABORT |
137                                       PCI_STATUS_REC_MASTER_ABORT, 1);
138                 pr_cont("\n");
139 
140                 cmd |= PCI_STATUS_REC_TARGET_ABORT;
141         }
142 
143         if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
144                 printk(KERN_DEBUG "PCI: parity error detected: ");
145                 pcibios_report_status(PCI_STATUS_PARITY |
146                                       PCI_STATUS_DETECTED_PARITY, 1);
147                 pr_cont("\n");
148 
149                 cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
150 
151                 /* Now back off of the IRQ for awhile */
152                 if (hose->err_irq) {
153                         disable_irq_nosync(hose->err_irq);
154                         hose->err_timer.expires = jiffies + HZ;
155                         add_timer(&hose->err_timer);
156                 }
157         }
158 
159         return cmd;
160 }
161 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php