| .. | .. |
|---|
| 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 | |
|---|