Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpci_hotplug_pci.c
Go to the documentation of this file.
1 /*
2  * CompactPCI Hot Plug Driver PCI functions
3  *
4  * Copyright (C) 2002,2005 by SOMA Networks, Inc.
5  *
6  * All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
16  * NON INFRINGEMENT. See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * Send feedback to <[email protected]>
24  */
25 
26 #include <linux/module.h>
27 #include <linux/kernel.h>
28 #include <linux/pci.h>
29 #include <linux/pci_hotplug.h>
30 #include <linux/proc_fs.h>
31 #include "../pci.h"
32 #include "cpci_hotplug.h"
33 
34 #define MY_NAME "cpci_hotplug"
35 
36 extern int cpci_debug;
37 
38 #define dbg(format, arg...) \
39  do { \
40  if (cpci_debug) \
41  printk (KERN_DEBUG "%s: " format "\n", \
42  MY_NAME , ## arg); \
43  } while (0)
44 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
45 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
46 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
47 
48 
50 {
51  int hs_cap;
52  u16 hs_csr;
53 
54  hs_cap = pci_bus_find_capability(slot->bus,
55  slot->devfn,
57  if (!hs_cap)
58  return 0;
59 
60  if (pci_bus_read_config_word(slot->bus,
61  slot->devfn,
62  hs_cap + 2,
63  &hs_csr))
64  return 0;
65 
66  return hs_csr & 0x0008 ? 1 : 0;
67 }
68 
70 {
71  int hs_cap;
72  u16 hs_csr;
73 
74  hs_cap = pci_bus_find_capability(slot->bus,
75  slot->devfn,
77  if (!hs_cap)
78  return 0;
79  if (pci_bus_read_config_word(slot->bus,
80  slot->devfn,
81  hs_cap + 2,
82  &hs_csr))
83  return 0;
84  if (status)
85  hs_csr |= HS_CSR_LOO;
86  else
87  hs_csr &= ~HS_CSR_LOO;
88  if (pci_bus_write_config_word(slot->bus,
89  slot->devfn,
90  hs_cap + 2,
91  hs_csr))
92  return 0;
93  return 1;
94 }
95 
97 {
98  int hs_cap;
99  u16 hs_csr;
100 
101  hs_cap = pci_bus_find_capability(slot->bus,
102  slot->devfn,
104  if (!hs_cap)
105  return 0xFFFF;
106  if (pci_bus_read_config_word(slot->bus,
107  slot->devfn,
108  hs_cap + 2,
109  &hs_csr))
110  return 0xFFFF;
111  return hs_csr;
112 }
113 
115 {
116  int hs_cap;
117  u16 hs_csr;
118  int ins = 0;
119 
120  hs_cap = pci_bus_find_capability(slot->bus,
121  slot->devfn,
123  if (!hs_cap)
124  return 0;
125  if (pci_bus_read_config_word(slot->bus,
126  slot->devfn,
127  hs_cap + 2,
128  &hs_csr))
129  return 0;
130  if (hs_csr & HS_CSR_INS) {
131  /* Clear INS (by setting it) */
132  if (pci_bus_write_config_word(slot->bus,
133  slot->devfn,
134  hs_cap + 2,
135  hs_csr))
136  ins = 0;
137  else
138  ins = 1;
139  }
140  return ins;
141 }
142 
144 {
145  int hs_cap;
146  u16 hs_csr;
147  int ext = 0;
148 
149  hs_cap = pci_bus_find_capability(slot->bus,
150  slot->devfn,
152  if (!hs_cap)
153  return 0;
154  if (pci_bus_read_config_word(slot->bus,
155  slot->devfn,
156  hs_cap + 2,
157  &hs_csr))
158  return 0;
159  if (hs_csr & HS_CSR_EXT)
160  ext = 1;
161  return ext;
162 }
163 
165 {
166  int hs_cap;
167  u16 hs_csr;
168 
169  hs_cap = pci_bus_find_capability(slot->bus,
170  slot->devfn,
172  if (!hs_cap)
173  return -ENODEV;
174  if (pci_bus_read_config_word(slot->bus,
175  slot->devfn,
176  hs_cap + 2,
177  &hs_csr))
178  return -ENODEV;
179  if (hs_csr & HS_CSR_EXT) {
180  /* Clear EXT (by setting it) */
181  if (pci_bus_write_config_word(slot->bus,
182  slot->devfn,
183  hs_cap + 2,
184  hs_csr))
185  return -ENODEV;
186  }
187  return 0;
188 }
189 
190 int cpci_led_on(struct slot* slot)
191 {
192  int hs_cap;
193  u16 hs_csr;
194 
195  hs_cap = pci_bus_find_capability(slot->bus,
196  slot->devfn,
198  if (!hs_cap)
199  return -ENODEV;
200  if (pci_bus_read_config_word(slot->bus,
201  slot->devfn,
202  hs_cap + 2,
203  &hs_csr))
204  return -ENODEV;
205  if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
206  hs_csr |= HS_CSR_LOO;
207  if (pci_bus_write_config_word(slot->bus,
208  slot->devfn,
209  hs_cap + 2,
210  hs_csr)) {
211  err("Could not set LOO for slot %s",
212  hotplug_slot_name(slot->hotplug_slot));
213  return -ENODEV;
214  }
215  }
216  return 0;
217 }
218 
219 int cpci_led_off(struct slot* slot)
220 {
221  int hs_cap;
222  u16 hs_csr;
223 
224  hs_cap = pci_bus_find_capability(slot->bus,
225  slot->devfn,
227  if (!hs_cap)
228  return -ENODEV;
229  if (pci_bus_read_config_word(slot->bus,
230  slot->devfn,
231  hs_cap + 2,
232  &hs_csr))
233  return -ENODEV;
234  if (hs_csr & HS_CSR_LOO) {
235  hs_csr &= ~HS_CSR_LOO;
236  if (pci_bus_write_config_word(slot->bus,
237  slot->devfn,
238  hs_cap + 2,
239  hs_csr)) {
240  err("Could not clear LOO for slot %s",
241  hotplug_slot_name(slot->hotplug_slot));
242  return -ENODEV;
243  }
244  }
245  return 0;
246 }
247 
248 
249 /*
250  * Device configuration functions
251  */
252 
254 {
255  struct pci_bus *parent;
256  int fn;
257 
258  dbg("%s - enter", __func__);
259 
260  if (slot->dev == NULL) {
261  dbg("pci_dev null, finding %02x:%02x:%x",
262  slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
263  slot->dev = pci_get_slot(slot->bus, slot->devfn);
264  }
265 
266  /* Still NULL? Well then scan for it! */
267  if (slot->dev == NULL) {
268  int n;
269  dbg("pci_dev still null");
270 
271  /*
272  * This will generate pci_dev structures for all functions, but
273  * we will only call this case when lookup fails.
274  */
275  n = pci_scan_slot(slot->bus, slot->devfn);
276  dbg("%s: pci_scan_slot returned %d", __func__, n);
277  slot->dev = pci_get_slot(slot->bus, slot->devfn);
278  if (slot->dev == NULL) {
279  err("Could not find PCI device for slot %02x", slot->number);
280  return -ENODEV;
281  }
282  }
283  parent = slot->dev->bus;
284 
285  for (fn = 0; fn < 8; fn++) {
286  struct pci_dev *dev;
287 
288  dev = pci_get_slot(parent,
289  PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
290  if (!dev)
291  continue;
292  if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
294  pci_hp_add_bridge(dev);
295  pci_dev_put(dev);
296  }
297 
299 
300  pci_bus_add_devices(parent);
301 
302  dbg("%s - exit", __func__);
303  return 0;
304 }
305 
307 {
308  int i;
309  struct pci_dev *dev;
310 
311  dbg("%s - enter", __func__);
312  if (!slot->dev) {
313  err("No device for slot %02x\n", slot->number);
314  return -ENODEV;
315  }
316 
317  for (i = 0; i < 8; i++) {
318  dev = pci_get_slot(slot->bus,
319  PCI_DEVFN(PCI_SLOT(slot->devfn), i));
320  if (dev) {
322  pci_dev_put(dev);
323  }
324  }
325  pci_dev_put(slot->dev);
326  slot->dev = NULL;
327 
328  dbg("%s - exit", __func__);
329  return 0;
330 }