.. | .. |
---|
22 | 22 | #include <asm/clp.h> |
---|
23 | 23 | #include <uapi/asm/clp.h> |
---|
24 | 24 | |
---|
| 25 | +#include "pci_bus.h" |
---|
| 26 | + |
---|
25 | 27 | bool zpci_unique_uid; |
---|
26 | 28 | |
---|
27 | | -static void update_uid_checking(bool new) |
---|
| 29 | +void update_uid_checking(bool new) |
---|
28 | 30 | { |
---|
29 | 31 | if (zpci_unique_uid != new) |
---|
30 | 32 | zpci_dbg(1, "uid checking:%d\n", new); |
---|
.. | .. |
---|
66 | 68 | /* |
---|
67 | 69 | * Call Logical Processor with c=0, the give constant lps and an lpcb request. |
---|
68 | 70 | */ |
---|
69 | | -static inline int clp_req(void *data, unsigned int lps) |
---|
| 71 | +static __always_inline int clp_req(void *data, unsigned int lps) |
---|
70 | 72 | { |
---|
71 | 73 | struct { u8 _[CLP_BLK_SIZE]; } *req = data; |
---|
72 | 74 | u64 ignored; |
---|
.. | .. |
---|
102 | 104 | zdev->msi_addr = response->msia; |
---|
103 | 105 | zdev->max_msi = response->noi; |
---|
104 | 106 | zdev->fmb_update = response->mui; |
---|
| 107 | + zdev->version = response->version; |
---|
105 | 108 | |
---|
106 | 109 | switch (response->version) { |
---|
107 | 110 | case 1: |
---|
.. | .. |
---|
145 | 148 | { |
---|
146 | 149 | int i; |
---|
147 | 150 | |
---|
148 | | - for (i = 0; i < PCI_BAR_COUNT; i++) { |
---|
| 151 | + for (i = 0; i < PCI_STD_NUM_BARS; i++) { |
---|
149 | 152 | zdev->bars[i].val = le32_to_cpu(response->bar[i]); |
---|
150 | 153 | zdev->bars[i].size = response->bar_size[i]; |
---|
151 | 154 | } |
---|
.. | .. |
---|
155 | 158 | zdev->pfgid = response->pfgid; |
---|
156 | 159 | zdev->pft = response->pft; |
---|
157 | 160 | zdev->vfn = response->vfn; |
---|
| 161 | + zdev->port = response->port; |
---|
158 | 162 | zdev->uid = response->uid; |
---|
159 | 163 | zdev->fmb_length = sizeof(u32) * response->fmb_len; |
---|
| 164 | + zdev->rid_available = response->rid_avail; |
---|
| 165 | + zdev->is_physfn = response->is_physfn; |
---|
| 166 | + if (!s390_pci_no_rid && zdev->rid_available) |
---|
| 167 | + zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; |
---|
160 | 168 | |
---|
161 | 169 | memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); |
---|
162 | 170 | if (response->util_str_avail) { |
---|
163 | 171 | memcpy(zdev->util_str, response->util_str, |
---|
164 | 172 | sizeof(zdev->util_str)); |
---|
| 173 | + zdev->util_str_avail = 1; |
---|
165 | 174 | } |
---|
| 175 | + zdev->mio_capable = response->mio_addr_avail; |
---|
| 176 | + for (i = 0; i < PCI_STD_NUM_BARS; i++) { |
---|
| 177 | + if (!(response->mio.valid & (1 << (PCI_STD_NUM_BARS - i - 1)))) |
---|
| 178 | + continue; |
---|
166 | 179 | |
---|
| 180 | + zdev->bars[i].mio_wb = (void __iomem *) response->mio.addr[i].wb; |
---|
| 181 | + zdev->bars[i].mio_wt = (void __iomem *) response->mio.addr[i].wt; |
---|
| 182 | + } |
---|
167 | 183 | return 0; |
---|
168 | 184 | } |
---|
169 | 185 | |
---|
170 | | -static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh) |
---|
| 186 | +int clp_query_pci_fn(struct zpci_dev *zdev) |
---|
171 | 187 | { |
---|
172 | 188 | struct clp_req_rsp_query_pci *rrb; |
---|
173 | 189 | int rc; |
---|
.. | .. |
---|
180 | 196 | rrb->request.hdr.len = sizeof(rrb->request); |
---|
181 | 197 | rrb->request.hdr.cmd = CLP_QUERY_PCI_FN; |
---|
182 | 198 | rrb->response.hdr.len = sizeof(rrb->response); |
---|
183 | | - rrb->request.fh = fh; |
---|
| 199 | + rrb->request.fh = zdev->fh; |
---|
184 | 200 | |
---|
185 | 201 | rc = clp_req(rrb, CLP_LPS_PCI); |
---|
186 | 202 | if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) { |
---|
.. | .. |
---|
198 | 214 | return rc; |
---|
199 | 215 | } |
---|
200 | 216 | |
---|
201 | | -int clp_add_pci_device(u32 fid, u32 fh, int configured) |
---|
202 | | -{ |
---|
203 | | - struct zpci_dev *zdev; |
---|
204 | | - int rc = -ENOMEM; |
---|
205 | | - |
---|
206 | | - zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, configured); |
---|
207 | | - zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); |
---|
208 | | - if (!zdev) |
---|
209 | | - goto error; |
---|
210 | | - |
---|
211 | | - zdev->fh = fh; |
---|
212 | | - zdev->fid = fid; |
---|
213 | | - |
---|
214 | | - /* Query function properties and update zdev */ |
---|
215 | | - rc = clp_query_pci_fn(zdev, fh); |
---|
216 | | - if (rc) |
---|
217 | | - goto error; |
---|
218 | | - |
---|
219 | | - if (configured) |
---|
220 | | - zdev->state = ZPCI_FN_STATE_CONFIGURED; |
---|
221 | | - else |
---|
222 | | - zdev->state = ZPCI_FN_STATE_STANDBY; |
---|
223 | | - |
---|
224 | | - rc = zpci_create_device(zdev); |
---|
225 | | - if (rc) |
---|
226 | | - goto error; |
---|
227 | | - return 0; |
---|
228 | | - |
---|
229 | | -error: |
---|
230 | | - zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc); |
---|
231 | | - kfree(zdev); |
---|
232 | | - return rc; |
---|
233 | | -} |
---|
234 | | - |
---|
235 | | -/* |
---|
236 | | - * Enable/Disable a given PCI function defined by its function handle. |
---|
| 217 | +static int clp_refresh_fh(u32 fid); |
---|
| 218 | +/** |
---|
| 219 | + * clp_set_pci_fn() - Execute a command on a PCI function |
---|
| 220 | + * @zdev: Function that will be affected |
---|
| 221 | + * @nr_dma_as: DMA address space number |
---|
| 222 | + * @command: The command code to execute |
---|
| 223 | + * |
---|
| 224 | + * Returns: 0 on success, < 0 for Linux errors (e.g. -ENOMEM), and |
---|
| 225 | + * > 0 for non-success platform responses |
---|
237 | 226 | */ |
---|
238 | | -static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command) |
---|
| 227 | +static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command) |
---|
239 | 228 | { |
---|
240 | 229 | struct clp_req_rsp_set_pci *rrb; |
---|
241 | 230 | int rc, retries = 100; |
---|
.. | .. |
---|
249 | 238 | rrb->request.hdr.len = sizeof(rrb->request); |
---|
250 | 239 | rrb->request.hdr.cmd = CLP_SET_PCI_FN; |
---|
251 | 240 | rrb->response.hdr.len = sizeof(rrb->response); |
---|
252 | | - rrb->request.fh = *fh; |
---|
| 241 | + rrb->request.fh = zdev->fh; |
---|
253 | 242 | rrb->request.oc = command; |
---|
254 | 243 | rrb->request.ndas = nr_dma_as; |
---|
255 | 244 | |
---|
.. | .. |
---|
262 | 251 | } |
---|
263 | 252 | } while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY); |
---|
264 | 253 | |
---|
265 | | - if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) |
---|
266 | | - *fh = rrb->response.fh; |
---|
267 | | - else { |
---|
| 254 | + if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) { |
---|
| 255 | + zdev->fh = rrb->response.fh; |
---|
| 256 | + } else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY) { |
---|
| 257 | + /* Function is already in desired state - update handle */ |
---|
| 258 | + rc = clp_refresh_fh(zdev->fid); |
---|
| 259 | + } else { |
---|
268 | 260 | zpci_err("Set PCI FN:\n"); |
---|
| 261 | + zpci_err_clp(rrb->response.hdr.rsp, rc); |
---|
| 262 | + if (!rc) |
---|
| 263 | + rc = rrb->response.hdr.rsp; |
---|
| 264 | + } |
---|
| 265 | + clp_free_block(rrb); |
---|
| 266 | + return rc; |
---|
| 267 | +} |
---|
| 268 | + |
---|
| 269 | +int clp_setup_writeback_mio(void) |
---|
| 270 | +{ |
---|
| 271 | + struct clp_req_rsp_slpc_pci *rrb; |
---|
| 272 | + u8 wb_bit_pos; |
---|
| 273 | + int rc; |
---|
| 274 | + |
---|
| 275 | + rrb = clp_alloc_block(GFP_KERNEL); |
---|
| 276 | + if (!rrb) |
---|
| 277 | + return -ENOMEM; |
---|
| 278 | + |
---|
| 279 | + memset(rrb, 0, sizeof(*rrb)); |
---|
| 280 | + rrb->request.hdr.len = sizeof(rrb->request); |
---|
| 281 | + rrb->request.hdr.cmd = CLP_SLPC; |
---|
| 282 | + rrb->response.hdr.len = sizeof(rrb->response); |
---|
| 283 | + |
---|
| 284 | + rc = clp_req(rrb, CLP_LPS_PCI); |
---|
| 285 | + if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) { |
---|
| 286 | + if (rrb->response.vwb) { |
---|
| 287 | + wb_bit_pos = rrb->response.mio_wb; |
---|
| 288 | + set_bit_inv(wb_bit_pos, &mio_wb_bit_mask); |
---|
| 289 | + zpci_dbg(3, "wb bit: %d\n", wb_bit_pos); |
---|
| 290 | + } else { |
---|
| 291 | + zpci_dbg(3, "wb bit: n.a.\n"); |
---|
| 292 | + } |
---|
| 293 | + |
---|
| 294 | + } else { |
---|
| 295 | + zpci_err("SLPC PCI:\n"); |
---|
269 | 296 | zpci_err_clp(rrb->response.hdr.rsp, rc); |
---|
270 | 297 | rc = -EIO; |
---|
271 | 298 | } |
---|
.. | .. |
---|
275 | 302 | |
---|
276 | 303 | int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as) |
---|
277 | 304 | { |
---|
278 | | - u32 fh = zdev->fh; |
---|
279 | 305 | int rc; |
---|
280 | 306 | |
---|
281 | | - rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN); |
---|
282 | | - if (!rc) |
---|
283 | | - /* Success -> store enabled handle in zdev */ |
---|
284 | | - zdev->fh = fh; |
---|
285 | | - |
---|
| 307 | + rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN); |
---|
286 | 308 | zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc); |
---|
| 309 | + if (!rc && zpci_use_mio(zdev)) { |
---|
| 310 | + rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO); |
---|
| 311 | + zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n", |
---|
| 312 | + zdev->fid, zdev->fh, rc); |
---|
| 313 | + if (rc) |
---|
| 314 | + clp_disable_fh(zdev); |
---|
| 315 | + } |
---|
287 | 316 | return rc; |
---|
288 | 317 | } |
---|
289 | 318 | |
---|
290 | 319 | int clp_disable_fh(struct zpci_dev *zdev) |
---|
291 | 320 | { |
---|
292 | | - u32 fh = zdev->fh; |
---|
293 | 321 | int rc; |
---|
294 | 322 | |
---|
295 | 323 | if (!zdev_enabled(zdev)) |
---|
296 | 324 | return 0; |
---|
297 | 325 | |
---|
298 | | - rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN); |
---|
299 | | - if (!rc) |
---|
300 | | - /* Success -> store disabled handle in zdev */ |
---|
301 | | - zdev->fh = fh; |
---|
302 | | - |
---|
| 326 | + rc = clp_set_pci_fn(zdev, 0, CLP_SET_DISABLE_PCI_FN); |
---|
303 | 327 | zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc); |
---|
304 | 328 | return rc; |
---|
305 | 329 | } |
---|
.. | .. |
---|
350 | 374 | return; |
---|
351 | 375 | |
---|
352 | 376 | zdev = get_zdev_by_fid(entry->fid); |
---|
353 | | - if (!zdev) |
---|
354 | | - clp_add_pci_device(entry->fid, entry->fh, entry->config_state); |
---|
355 | | -} |
---|
356 | | - |
---|
357 | | -static void __clp_update(struct clp_fh_list_entry *entry, void *data) |
---|
358 | | -{ |
---|
359 | | - struct zpci_dev *zdev; |
---|
360 | | - |
---|
361 | | - if (!entry->vendor_id) |
---|
| 377 | + if (zdev) { |
---|
| 378 | + zpci_zdev_put(zdev); |
---|
362 | 379 | return; |
---|
363 | | - |
---|
364 | | - zdev = get_zdev_by_fid(entry->fid); |
---|
365 | | - if (!zdev) |
---|
366 | | - return; |
---|
367 | | - |
---|
368 | | - zdev->fh = entry->fh; |
---|
| 380 | + } |
---|
| 381 | + zpci_create_device(entry->fid, entry->fh, entry->config_state); |
---|
369 | 382 | } |
---|
370 | 383 | |
---|
371 | 384 | int clp_scan_pci_devices(void) |
---|
.. | .. |
---|
383 | 396 | return rc; |
---|
384 | 397 | } |
---|
385 | 398 | |
---|
386 | | -int clp_rescan_pci_devices(void) |
---|
| 399 | +static void __clp_refresh_fh(struct clp_fh_list_entry *entry, void *data) |
---|
387 | 400 | { |
---|
388 | | - struct clp_req_rsp_list_pci *rrb; |
---|
389 | | - int rc; |
---|
| 401 | + struct zpci_dev *zdev; |
---|
| 402 | + u32 fid = *((u32 *)data); |
---|
390 | 403 | |
---|
391 | | - zpci_remove_reserved_devices(); |
---|
| 404 | + if (!entry->vendor_id || fid != entry->fid) |
---|
| 405 | + return; |
---|
392 | 406 | |
---|
393 | | - rrb = clp_alloc_block(GFP_KERNEL); |
---|
394 | | - if (!rrb) |
---|
395 | | - return -ENOMEM; |
---|
| 407 | + zdev = get_zdev_by_fid(fid); |
---|
| 408 | + if (!zdev) |
---|
| 409 | + return; |
---|
396 | 410 | |
---|
397 | | - rc = clp_list_pci(rrb, NULL, __clp_add); |
---|
398 | | - |
---|
399 | | - clp_free_block(rrb); |
---|
400 | | - return rc; |
---|
| 411 | + zdev->fh = entry->fh; |
---|
401 | 412 | } |
---|
402 | 413 | |
---|
403 | | -int clp_rescan_pci_devices_simple(void) |
---|
| 414 | +/* |
---|
| 415 | + * Refresh the function handle of the function matching @fid |
---|
| 416 | + */ |
---|
| 417 | +static int clp_refresh_fh(u32 fid) |
---|
404 | 418 | { |
---|
405 | 419 | struct clp_req_rsp_list_pci *rrb; |
---|
406 | 420 | int rc; |
---|
.. | .. |
---|
409 | 423 | if (!rrb) |
---|
410 | 424 | return -ENOMEM; |
---|
411 | 425 | |
---|
412 | | - rc = clp_list_pci(rrb, NULL, __clp_update); |
---|
| 426 | + rc = clp_list_pci(rrb, &fid, __clp_refresh_fh); |
---|
413 | 427 | |
---|
414 | 428 | clp_free_block(rrb); |
---|
415 | 429 | return rc; |
---|
.. | .. |
---|
468 | 482 | } |
---|
469 | 483 | } |
---|
470 | 484 | |
---|
471 | | -static int clp_pci_slpc(struct clp_req *req, struct clp_req_rsp_slpc *lpcb) |
---|
| 485 | +static int clp_pci_slpc(struct clp_req *req, struct clp_req_rsp_slpc_pci *lpcb) |
---|
472 | 486 | { |
---|
473 | 487 | unsigned long limit = PAGE_SIZE - sizeof(lpcb->request); |
---|
474 | 488 | |
---|