Commit b971cbd0 authored by Sumanth Korikkar's avatar Sumanth Korikkar Committed by Heiko Carstens
Browse files

s390/sclp: provide extended sccb support



As the number of cpus increases, the sccb response can exceed 4k for
read cpu and read scp info sclp commands. Hence, all cpu info entries
cant be embedded within a sccb response

Solution:
To overcome this limitation, extended sccb facility is provided by sclp.

1. Check if the extended sccb facility is installed.
2. If extended sccb is installed, perform the read scp and read cpu
   command considering a max sccb length of three page size. This max
   length is based on factors like max cpus, sccb header.
3. If extended sccb is not installed, perform the read scp and read cpu
   sclp command considering a max sccb length of one page size.

Signed-off-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent d25d23e1
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -12,7 +12,12 @@
#include <asm/cpu.h>

#define SCLP_CHP_INFO_MASK_SIZE		32
#define SCLP_MAX_CORES			256
#define EARLY_SCCB_SIZE		PAGE_SIZE
#define SCLP_MAX_CORES		512
/* 144 + 16 * SCLP_MAX_CORES + 2 * (SCLP_MAX_CORES - 1) */
#define EXT_SCCB_READ_SCP	(3 * PAGE_SIZE)
/* 24 + 16 * SCLP_MAX_CORES */
#define EXT_SCCB_READ_CPU	(3 * PAGE_SIZE)

struct sclp_chp_info {
	u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
+0 −2
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@
#define EARLY_SCCB_OFFSET	0x11000
#define HEAD_END		0x12000

#define EARLY_SCCB_SIZE		PAGE_SIZE

/*
 * Machine features detected in early.c
 */
+6 −2
Original line number Diff line number Diff line
@@ -156,7 +156,11 @@ struct read_cpu_info_sccb {
	u16	offset_configured;
	u16	nr_standby;
	u16	offset_standby;
	u8	reserved[4096 - 16];
	/*
	 * Without ext sccb, struct size is PAGE_SIZE.
	 * With ext sccb, struct size is EXT_SCCB_READ_CPU.
	 */
	u8	reserved[];
} __attribute__((packed, aligned(PAGE_SIZE)));

struct read_info_sccb {
@@ -199,7 +203,7 @@ struct read_info_sccb {
	u8	byte_134;			/* 134 */
	u8	cpudirq;		/* 135 */
	u16	cbl;			/* 136-137 */
	u8	_pad_138[4096 - 138];	/* 138-4095 */
	u8	_pad_138[EXT_SCCB_READ_SCP - 138];
} __packed __aligned(PAGE_SIZE);

struct read_storage_sccb {
+7 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <asm/page.h>
#include <asm/sclp.h>
#include <asm/numa.h>
#include <asm/facility.h>

#include "sclp.h"

@@ -87,14 +88,17 @@ int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout)
int _sclp_get_core_info(struct sclp_core_info *info)
{
	int rc;
	int length = test_facility(140) ? EXT_SCCB_READ_CPU : PAGE_SIZE;
	struct read_cpu_info_sccb *sccb;

	if (!SCLP_HAS_CPU_INFO)
		return -EOPNOTSUPP;
	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);

	sccb = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA | __GFP_ZERO, get_order(length));
	if (!sccb)
		return -ENOMEM;
	sccb->header.length = sizeof(*sccb);
	sccb->header.length = length;
	sccb->header.control_mask[2] = 0x80;
	rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb,
				       SCLP_QUEUE_INTERVAL);
	if (rc)
@@ -107,7 +111,7 @@ int _sclp_get_core_info(struct sclp_core_info *info)
	}
	sclp_fill_core_info(info, sccb);
out:
	free_page((unsigned long) sccb);
	free_pages((unsigned long) sccb, get_order(length));
	return rc;
}

+2 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <asm/sclp.h>
#include <asm/ipl.h>
#include <asm/setup.h>
#include <asm/facility.h>
#include "sclp_sdias.h"
#include "sclp.h"

@@ -114,7 +115,7 @@ void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info)
int __init sclp_early_get_core_info(struct sclp_core_info *info)
{
	struct read_cpu_info_sccb *sccb;
	int length = PAGE_SIZE;
	int length = test_facility(140) ? EXT_SCCB_READ_CPU : PAGE_SIZE;
	int rc = 0;

	if (!SCLP_HAS_CPU_INFO)
Loading