Skip to content

Commit 17cdec9

Browse files
niklas88Vasily Gorbik
authored andcommitted
s390/pci: Recover handle in clp_set_pci_fn()
When we try to recover a PCI function using echo 1 > /sys/bus/pci/devices/<id>/recover or manually with echo 1 > /sys/bus/pci/devices/<id>/remove echo 0 > /sys/bus/pci/slots/<slot>/power echo 1 > /sys/bus/pci/slots/<slot>/power clp_disable_fn() / clp_enable_fn() call clp_set_pci_fn() to first disable and then reenable the function. When the function is already in the requested state we may be left with an invalid function handle. To get a new valid handle we do a clp_list_pci() call. For this we need both the function ID and function handle in clp_set_pci_fn() so pass the zdev and get both. To simplify things also pull setting the refreshed function handle into clp_set_pci_fn() Signed-off-by: Niklas Schnelle <[email protected]> Reviewed-by: Peter Oberparleiter <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent d1eef1c commit 17cdec9

File tree

3 files changed

+31
-21
lines changed

3 files changed

+31
-21
lines changed

arch/s390/include/asm/pci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void zpci_remove_reserved_devices(void);
180180
/* CLP */
181181
int clp_scan_pci_devices(void);
182182
int clp_rescan_pci_devices(void);
183-
int clp_rescan_pci_devices_simple(void);
183+
int clp_rescan_pci_devices_simple(u32 *fid);
184184
int clp_add_pci_device(u32, u32, int);
185185
int clp_enable_fh(struct zpci_dev *, u8);
186186
int clp_disable_fh(struct zpci_dev *);

arch/s390/pci/pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,5 +939,5 @@ subsys_initcall_sync(pci_base_init);
939939
void zpci_rescan(void)
940940
{
941941
if (zpci_is_enabled())
942-
clp_rescan_pci_devices_simple();
942+
clp_rescan_pci_devices_simple(NULL);
943943
}

arch/s390/pci/pci_clp.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,14 @@ int clp_add_pci_device(u32 fid, u32 fh, int configured)
240240
}
241241

242242
/*
243-
* Enable/Disable a given PCI function defined by its function handle.
243+
* Enable/Disable a given PCI function and update its function handle if
244+
* necessary
244245
*/
245-
static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
246+
static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
246247
{
247248
struct clp_req_rsp_set_pci *rrb;
248249
int rc, retries = 100;
250+
u32 fid = zdev->fid;
249251

250252
rrb = clp_alloc_block(GFP_KERNEL);
251253
if (!rrb)
@@ -256,7 +258,7 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
256258
rrb->request.hdr.len = sizeof(rrb->request);
257259
rrb->request.hdr.cmd = CLP_SET_PCI_FN;
258260
rrb->response.hdr.len = sizeof(rrb->response);
259-
rrb->request.fh = *fh;
261+
rrb->request.fh = zdev->fh;
260262
rrb->request.oc = command;
261263
rrb->request.ndas = nr_dma_as;
262264

@@ -269,31 +271,35 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
269271
}
270272
} while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
271273

272-
if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
273-
*fh = rrb->response.fh;
274-
else {
274+
if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
275275
zpci_err("Set PCI FN:\n");
276276
zpci_err_clp(rrb->response.hdr.rsp, rc);
277-
rc = -EIO;
277+
}
278+
279+
if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
280+
zdev->fh = rrb->response.fh;
281+
} else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY &&
282+
rrb->response.fh == 0) {
283+
/* Function is already in desired state - update handle */
284+
rc = clp_rescan_pci_devices_simple(&fid);
278285
}
279286
clp_free_block(rrb);
280287
return rc;
281288
}
282289

283290
int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
284291
{
285-
u32 fh = zdev->fh;
286292
int rc;
287293

288-
rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
289-
zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
294+
rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
295+
zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
290296
if (rc)
291297
goto out;
292298

293-
zdev->fh = fh;
294299
if (zpci_use_mio(zdev)) {
295-
rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_MIO);
296-
zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
300+
rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO);
301+
zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n",
302+
zdev->fid, zdev->fh, rc);
297303
if (rc)
298304
clp_disable_fh(zdev);
299305
}
@@ -309,11 +315,8 @@ int clp_disable_fh(struct zpci_dev *zdev)
309315
if (!zdev_enabled(zdev))
310316
return 0;
311317

312-
rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN);
318+
rc = clp_set_pci_fn(zdev, 0, CLP_SET_DISABLE_PCI_FN);
313319
zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
314-
if (!rc)
315-
zdev->fh = fh;
316-
317320
return rc;
318321
}
319322

@@ -370,10 +373,14 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data)
370373
static void __clp_update(struct clp_fh_list_entry *entry, void *data)
371374
{
372375
struct zpci_dev *zdev;
376+
u32 *fid = data;
373377

374378
if (!entry->vendor_id)
375379
return;
376380

381+
if (fid && *fid != entry->fid)
382+
return;
383+
377384
zdev = get_zdev_by_fid(entry->fid);
378385
if (!zdev)
379386
return;
@@ -413,7 +420,10 @@ int clp_rescan_pci_devices(void)
413420
return rc;
414421
}
415422

416-
int clp_rescan_pci_devices_simple(void)
423+
/* Rescan PCI functions and refresh function handles. If fid is non-NULL only
424+
* refresh the handle of the function matching @fid
425+
*/
426+
int clp_rescan_pci_devices_simple(u32 *fid)
417427
{
418428
struct clp_req_rsp_list_pci *rrb;
419429
int rc;
@@ -422,7 +432,7 @@ int clp_rescan_pci_devices_simple(void)
422432
if (!rrb)
423433
return -ENOMEM;
424434

425-
rc = clp_list_pci(rrb, NULL, __clp_update);
435+
rc = clp_list_pci(rrb, fid, __clp_update);
426436

427437
clp_free_block(rrb);
428438
return rc;

0 commit comments

Comments
 (0)