Skip to content

Commit b7a5e5d

Browse files
NickJackolsonVasily Gorbik
authored andcommitted
s390/sthyi: Use cached data when diag is busy
When sthyi is being emulated, data from diag204 is used. If diag204 returns busy, previously cached sthyi info block is returned to the caller and cache expiry is set to expired. Acked-by: Heiko Carstens <[email protected]> Reviewed-by: Tobias Huschle <[email protected]> Signed-off-by: Tobias Huschle <[email protected]> Signed-off-by: Mete Durlu <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent 6fdf72c commit b7a5e5d

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

arch/s390/kernel/sthyi.c

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static struct diag204_x_part_block *lpar_cpu_inf(struct lpar_cpu_inf *part_inf,
300300
return (struct diag204_x_part_block *)&block->cpus[i];
301301
}
302302

303-
static void *diag204_get_data(void)
303+
static void *diag204_get_data(bool diag204_allow_busy)
304304
{
305305
unsigned long subcode;
306306
void *diag204_buf;
@@ -320,6 +320,8 @@ static void *diag204_get_data(void)
320320
return ERR_PTR(-ENOMEM);
321321
subcode = DIAG204_SUBC_STIB7;
322322
subcode |= DIAG204_INFO_EXT;
323+
if (diag204_has_bif() && diag204_allow_busy)
324+
subcode |= DIAG204_BIF_BIT;
323325
rc = diag204(subcode, pages, diag204_buf);
324326
if (rc < 0) {
325327
vfree(diag204_buf);
@@ -328,22 +330,27 @@ static void *diag204_get_data(void)
328330
return diag204_buf;
329331
}
330332

331-
static void fill_diag(struct sthyi_sctns *sctns)
333+
static bool is_diag204_cached(struct sthyi_sctns *sctns)
334+
{
335+
/*
336+
* Check if validity bits are set when diag204 data
337+
* is gathered.
338+
*/
339+
if (sctns->par.infpval1)
340+
return true;
341+
return false;
342+
}
343+
344+
static void fill_diag(struct sthyi_sctns *sctns, void *diag204_buf)
332345
{
333346
int i;
334347
bool this_lpar;
335-
void *diag204_buf;
336348
void *diag224_buf = NULL;
337349
struct diag204_x_info_blk_hdr *ti_hdr;
338350
struct diag204_x_part_block *part_block;
339351
struct diag204_x_phys_block *phys_block;
340352
struct lpar_cpu_inf lpar_inf = {};
341353

342-
/* Errors are handled through the validity bits in the response. */
343-
diag204_buf = diag204_get_data();
344-
if (IS_ERR(diag204_buf))
345-
return;
346-
347354
diag224_buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
348355
if (!diag224_buf || diag224(diag224_buf))
349356
goto out;
@@ -408,7 +415,6 @@ static void fill_diag(struct sthyi_sctns *sctns)
408415

409416
out:
410417
free_page((unsigned long)diag224_buf);
411-
vfree(diag204_buf);
412418
}
413419

414420
static int sthyi(u64 vaddr, u64 *rc)
@@ -430,19 +436,31 @@ static int sthyi(u64 vaddr, u64 *rc)
430436

431437
static int fill_dst(void *dst, u64 *rc)
432438
{
439+
void *diag204_buf;
440+
433441
struct sthyi_sctns *sctns = (struct sthyi_sctns *)dst;
434442

435443
/*
436444
* If the facility is on, we don't want to emulate the instruction.
437445
* We ask the hypervisor to provide the data.
438446
*/
439-
if (test_facility(74))
447+
if (test_facility(74)) {
448+
memset(dst, 0, PAGE_SIZE);
440449
return sthyi((u64)dst, rc);
441-
450+
}
451+
/*
452+
* When emulating, if diag204 returns BUSY don't reset dst buffer
453+
* and use cached data.
454+
*/
455+
*rc = 0;
456+
diag204_buf = diag204_get_data(is_diag204_cached(sctns));
457+
if (IS_ERR(diag204_buf))
458+
return PTR_ERR(diag204_buf);
459+
memset(dst, 0, PAGE_SIZE);
442460
fill_hdr(sctns);
443461
fill_stsi(sctns);
444-
fill_diag(sctns);
445-
*rc = 0;
462+
fill_diag(sctns, diag204_buf);
463+
vfree(diag204_buf);
446464
return 0;
447465
}
448466

@@ -461,11 +479,14 @@ static int sthyi_update_cache(u64 *rc)
461479
{
462480
int r;
463481

464-
memset(sthyi_cache.info, 0, PAGE_SIZE);
465482
r = fill_dst(sthyi_cache.info, rc);
466-
if (r)
467-
return r;
468-
sthyi_cache.end = jiffies + CACHE_VALID_JIFFIES;
483+
if (r == 0) {
484+
sthyi_cache.end = jiffies + CACHE_VALID_JIFFIES;
485+
} else if (r == -EBUSY) {
486+
/* mark as expired and return 0 to keep using cached data */
487+
sthyi_cache.end = jiffies - 1;
488+
r = 0;
489+
}
469490
return r;
470491
}
471492

0 commit comments

Comments
 (0)