aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-08-29 13:37:28 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-08-30 02:57:17 -0400
commit1d57896638f080165165dd9fb4cf848220dfd853 (patch)
tree679a611e0a39e865855a611f5c8d5d90c0122470 /arch/s390
parent77e844b9644026c11c5883144540155de39af767 (diff)
s390/pci: split lpf
List pci functions is used to query and iterate over pci functions. This function currently has 2 users - initial device discovery and rescan after a machine check. Instead of having a multipurpose function pass a callback which gets called for each pci function. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/pci.h4
-rw-r--r--arch/s390/pci/pci.c7
-rw-r--r--arch/s390/pci/pci_clp.c113
-rw-r--r--arch/s390/pci/pci_event.c2
4 files changed, 72 insertions, 54 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 64081f85ffdb..4b2bbc1fdbe0 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -135,7 +135,8 @@ int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
135int zpci_unregister_ioat(struct zpci_dev *, u8); 135int zpci_unregister_ioat(struct zpci_dev *, u8);
136 136
137/* CLP */ 137/* CLP */
138int clp_find_pci_devices(void); 138int clp_scan_pci_devices(void);
139int clp_rescan_pci_devices(void);
139int clp_add_pci_device(u32, u32, int); 140int clp_add_pci_device(u32, u32, int);
140int clp_enable_fh(struct zpci_dev *, u8); 141int clp_enable_fh(struct zpci_dev *, u8);
141int clp_disable_fh(struct zpci_dev *); 142int clp_disable_fh(struct zpci_dev *);
@@ -163,7 +164,6 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {}
163/* Helpers */ 164/* Helpers */
164struct zpci_dev *get_zdev(struct pci_dev *); 165struct zpci_dev *get_zdev(struct pci_dev *);
165struct zpci_dev *get_zdev_by_fid(u32); 166struct zpci_dev *get_zdev_by_fid(u32);
166bool zpci_fid_present(u32);
167 167
168/* sysfs */ 168/* sysfs */
169int zpci_sysfs_add_device(struct device *); 169int zpci_sysfs_add_device(struct device *);
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index b0ccd424308a..a7ed6685e7fb 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -99,11 +99,6 @@ struct zpci_dev *get_zdev_by_fid(u32 fid)
99 return zdev; 99 return zdev;
100} 100}
101 101
102bool zpci_fid_present(u32 fid)
103{
104 return (get_zdev_by_fid(fid) != NULL) ? true : false;
105}
106
107static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus) 102static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
108{ 103{
109 return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL; 104 return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
@@ -926,7 +921,7 @@ static int __init pci_base_init(void)
926 if (rc) 921 if (rc)
927 goto out_dma; 922 goto out_dma;
928 923
929 rc = clp_find_pci_devices(); 924 rc = clp_scan_pci_devices();
930 if (rc) 925 if (rc)
931 goto out_find; 926 goto out_find;
932 927
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index 2e9539625d93..70db060b4d41 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -36,9 +36,9 @@ static inline u8 clp_instr(void *data)
36 return cc; 36 return cc;
37} 37}
38 38
39static void *clp_alloc_block(void) 39static void *clp_alloc_block(gfp_t gfp_mask)
40{ 40{
41 return (void *) __get_free_pages(GFP_KERNEL, get_order(CLP_BLK_SIZE)); 41 return (void *) __get_free_pages(gfp_mask, get_order(CLP_BLK_SIZE));
42} 42}
43 43
44static void clp_free_block(void *ptr) 44static void clp_free_block(void *ptr)
@@ -70,7 +70,7 @@ static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
70 struct clp_req_rsp_query_pci_grp *rrb; 70 struct clp_req_rsp_query_pci_grp *rrb;
71 int rc; 71 int rc;
72 72
73 rrb = clp_alloc_block(); 73 rrb = clp_alloc_block(GFP_KERNEL);
74 if (!rrb) 74 if (!rrb)
75 return -ENOMEM; 75 return -ENOMEM;
76 76
@@ -113,7 +113,7 @@ static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
113 struct clp_req_rsp_query_pci *rrb; 113 struct clp_req_rsp_query_pci *rrb;
114 int rc; 114 int rc;
115 115
116 rrb = clp_alloc_block(); 116 rrb = clp_alloc_block(GFP_KERNEL);
117 if (!rrb) 117 if (!rrb)
118 return -ENOMEM; 118 return -ENOMEM;
119 119
@@ -181,7 +181,7 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
181 struct clp_req_rsp_set_pci *rrb; 181 struct clp_req_rsp_set_pci *rrb;
182 int rc, retries = 1000; 182 int rc, retries = 1000;
183 183
184 rrb = clp_alloc_block(); 184 rrb = clp_alloc_block(GFP_KERNEL);
185 if (!rrb) 185 if (!rrb)
186 return -ENOMEM; 186 return -ENOMEM;
187 187
@@ -245,49 +245,12 @@ int clp_disable_fh(struct zpci_dev *zdev)
245 return rc; 245 return rc;
246} 246}
247 247
248static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry) 248static int clp_list_pci(struct clp_req_rsp_list_pci *rrb,
249 void (*cb)(struct clp_fh_list_entry *entry))
249{ 250{
250 int present, rc;
251
252 if (!entry->vendor_id)
253 return;
254
255 /* TODO: be a little bit more scalable */
256 present = zpci_fid_present(entry->fid);
257
258 if (present)
259 pr_debug("%s: device %x already present\n", __func__, entry->fid);
260
261 /* skip already used functions */
262 if (present && entry->config_state)
263 return;
264
265 /* aev 306: function moved to stand-by state */
266 if (present && !entry->config_state) {
267 /*
268 * The handle is already disabled, that means no iota/irq freeing via
269 * the firmware interfaces anymore. Need to free resources manually
270 * (DMA memory, debug, sysfs)...
271 */
272 zpci_stop_device(get_zdev_by_fid(entry->fid));
273 return;
274 }
275
276 rc = clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
277 if (rc)
278 pr_err("Failed to add fid: 0x%x\n", entry->fid);
279}
280
281int clp_find_pci_devices(void)
282{
283 struct clp_req_rsp_list_pci *rrb;
284 u64 resume_token = 0; 251 u64 resume_token = 0;
285 int entries, i, rc; 252 int entries, i, rc;
286 253
287 rrb = clp_alloc_block();
288 if (!rrb)
289 return -ENOMEM;
290
291 do { 254 do {
292 memset(rrb, 0, sizeof(*rrb)); 255 memset(rrb, 0, sizeof(*rrb));
293 rrb->request.hdr.len = sizeof(rrb->request); 256 rrb->request.hdr.len = sizeof(rrb->request);
@@ -316,12 +279,72 @@ int clp_find_pci_devices(void)
316 resume_token = rrb->response.resume_token; 279 resume_token = rrb->response.resume_token;
317 280
318 for (i = 0; i < entries; i++) 281 for (i = 0; i < entries; i++)
319 clp_check_pcifn_entry(&rrb->response.fh_list[i]); 282 cb(&rrb->response.fh_list[i]);
320 } while (resume_token); 283 } while (resume_token);
321 284
322 pr_debug("Maximum number of supported PCI functions: %u\n", 285 pr_debug("Maximum number of supported PCI functions: %u\n",
323 rrb->response.max_fn); 286 rrb->response.max_fn);
324out: 287out:
288 return rc;
289}
290
291static void __clp_add(struct clp_fh_list_entry *entry)
292{
293 if (!entry->vendor_id)
294 return;
295
296 clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
297}
298
299static void __clp_rescan(struct clp_fh_list_entry *entry)
300{
301 struct zpci_dev *zdev;
302
303 if (!entry->vendor_id)
304 return;
305
306 zdev = get_zdev_by_fid(entry->fid);
307 if (!zdev) {
308 clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
309 return;
310 }
311
312 if (!entry->config_state) {
313 /*
314 * The handle is already disabled, that means no iota/irq freeing via
315 * the firmware interfaces anymore. Need to free resources manually
316 * (DMA memory, debug, sysfs)...
317 */
318 zpci_stop_device(zdev);
319 }
320}
321
322int clp_scan_pci_devices(void)
323{
324 struct clp_req_rsp_list_pci *rrb;
325 int rc;
326
327 rrb = clp_alloc_block(GFP_KERNEL);
328 if (!rrb)
329 return -ENOMEM;
330
331 rc = clp_list_pci(rrb, __clp_add);
332
333 clp_free_block(rrb);
334 return rc;
335}
336
337int clp_rescan_pci_devices(void)
338{
339 struct clp_req_rsp_list_pci *rrb;
340 int rc;
341
342 rrb = clp_alloc_block(GFP_KERNEL);
343 if (!rrb)
344 return -ENOMEM;
345
346 rc = clp_list_pci(rrb, __clp_rescan);
347
325 clp_free_block(rrb); 348 clp_free_block(rrb);
326 return rc; 349 return rc;
327} 350}
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index ec62e3a0dc09..0aecaf954845 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -69,7 +69,7 @@ static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
69 clp_add_pci_device(ccdf->fid, ccdf->fh, 0); 69 clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
70 break; 70 break;
71 case 0x0306: 71 case 0x0306:
72 clp_find_pci_devices(); 72 clp_rescan_pci_devices();
73 break; 73 break;
74 default: 74 default:
75 break; 75 break;