diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-08-29 13:37:28 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-08-30 02:57:17 -0400 |
commit | 1d57896638f080165165dd9fb4cf848220dfd853 (patch) | |
tree | 679a611e0a39e865855a611f5c8d5d90c0122470 /arch/s390 | |
parent | 77e844b9644026c11c5883144540155de39af767 (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.h | 4 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 7 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 113 | ||||
-rw-r--r-- | arch/s390/pci/pci_event.c | 2 |
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); | |||
135 | int zpci_unregister_ioat(struct zpci_dev *, u8); | 135 | int zpci_unregister_ioat(struct zpci_dev *, u8); |
136 | 136 | ||
137 | /* CLP */ | 137 | /* CLP */ |
138 | int clp_find_pci_devices(void); | 138 | int clp_scan_pci_devices(void); |
139 | int clp_rescan_pci_devices(void); | ||
139 | int clp_add_pci_device(u32, u32, int); | 140 | int clp_add_pci_device(u32, u32, int); |
140 | int clp_enable_fh(struct zpci_dev *, u8); | 141 | int clp_enable_fh(struct zpci_dev *, u8); |
141 | int clp_disable_fh(struct zpci_dev *); | 142 | int clp_disable_fh(struct zpci_dev *); |
@@ -163,7 +164,6 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {} | |||
163 | /* Helpers */ | 164 | /* Helpers */ |
164 | struct zpci_dev *get_zdev(struct pci_dev *); | 165 | struct zpci_dev *get_zdev(struct pci_dev *); |
165 | struct zpci_dev *get_zdev_by_fid(u32); | 166 | struct zpci_dev *get_zdev_by_fid(u32); |
166 | bool zpci_fid_present(u32); | ||
167 | 167 | ||
168 | /* sysfs */ | 168 | /* sysfs */ |
169 | int zpci_sysfs_add_device(struct device *); | 169 | int 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 | ||
102 | bool zpci_fid_present(u32 fid) | ||
103 | { | ||
104 | return (get_zdev_by_fid(fid) != NULL) ? true : false; | ||
105 | } | ||
106 | |||
107 | static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus) | 102 | static 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 | ||
39 | static void *clp_alloc_block(void) | 39 | static 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 | ||
44 | static void clp_free_block(void *ptr) | 44 | static 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 | ||
248 | static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry) | 248 | static 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 | |||
281 | int 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); |
324 | out: | 287 | out: |
288 | return rc; | ||
289 | } | ||
290 | |||
291 | static 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 | |||
299 | static 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 | |||
322 | int 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 | |||
337 | int 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; |