Commit a817d98d authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Alexander Gordeev
Browse files

s390/cio: rework channel-utilization-block handling



Convert channel-utilization-block (CUB) address variables from separate
named fields to arrays of addresses. Also simplify error handling and
introduce named constants. This is done in preparation of introducing
additional CUBs.

Note: With this change the __packed annotation of secm_area is required
to prevent an alignment hole that would otherwise occur due to the
switch from u32 to dma64_t.

Reviewed-by: default avatarVineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarPeter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent d35c34bb
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -161,12 +161,12 @@ static void chp_measurement_copy_block(struct cmg_entry *buf,
	struct cmg_entry *entry, reference_buf;
	int idx;

	if (chpid.id < 128) {
		area = css->cub_addr1;
	if (chpid.id < CSS_CUES_PER_PAGE) {
		area = css->cub[0];
		idx = chpid.id;
	} else {
		area = css->cub_addr2;
		idx = chpid.id - 128;
		area = css->cub[1];
		idx = chpid.id - CSS_CUES_PER_PAGE;
	}
	entry = area + (idx * sizeof(struct cmg_entry));
	do {
+37 −19
Original line number Diff line number Diff line
@@ -874,19 +874,16 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable)
		u32 : 30;
		u32 key : 4;
		u32 : 28;
		u32 zeroes1;
		dma32_t cub_addr1;
		u32 zeroes2;
		dma32_t cub_addr2;
		dma64_t cub[CSS_NUM_CUB_PAGES];
		u32 reserved[13];
		struct chsc_header response;
		u32 status : 8;
		u32 : 4;
		u32 fmt : 4;
		u32 : 16;
	} *secm_area;
	} __packed *secm_area;
	unsigned long flags;
	int ret, ccode;
	int ret, ccode, i;

	spin_lock_irqsave(&chsc_page_lock, flags);
	memset(chsc_page, 0, PAGE_SIZE);
@@ -895,8 +892,9 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable)
	secm_area->request.code = 0x0016;

	secm_area->key = PAGE_DEFAULT_KEY >> 4;
	secm_area->cub_addr1 = virt_to_dma32(css->cub_addr1);
	secm_area->cub_addr2 = virt_to_dma32(css->cub_addr2);

	for (i = 0; i < CSS_NUM_CUB_PAGES; i++)
		secm_area->cub[i] = (__force dma64_t)virt_to_dma32(css->cub[i]);

	secm_area->operation_code = enable ? 0 : 1;

@@ -922,19 +920,38 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable)
	return ret;
}

static int cub_alloc(struct channel_subsystem *css)
{
	int i;

	for (i = 0; i < CSS_NUM_CUB_PAGES; i++) {
		css->cub[i] = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
		if (!css->cub[i])
			return -ENOMEM;
	}

	return 0;
}

static void cub_free(struct channel_subsystem *css)
{
	int i;

	for (i = 0; i < CSS_NUM_CUB_PAGES; i++) {
		free_page((unsigned long)css->cub[i]);
		css->cub[i] = NULL;
	}
}

int
chsc_secm(struct channel_subsystem *css, int enable)
{
	int ret;

	if (enable && !css->cm_enabled) {
		css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
		css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
		if (!css->cub_addr1 || !css->cub_addr2) {
			free_page((unsigned long)css->cub_addr1);
			free_page((unsigned long)css->cub_addr2);
			return -ENOMEM;
		}
		ret = cub_alloc(css);
		if (ret)
			goto out;
	}
	ret = __chsc_do_secm(css, enable);
	if (!ret) {
@@ -948,10 +965,11 @@ chsc_secm(struct channel_subsystem *css, int enable)
		} else
			chsc_remove_cmg_attr(css);
	}
	if (!css->cm_enabled) {
		free_page((unsigned long)css->cub_addr1);
		free_page((unsigned long)css->cub_addr2);
	}

out:
	if (!css->cm_enabled)
		cub_free(css);

	return ret;
}

+8 −2
Original line number Diff line number Diff line
@@ -34,6 +34,13 @@
#define SNID_STATE3_MULTI_PATH	   1
#define SNID_STATE3_SINGLE_PATH	   0

/*
 * Miscellaneous constants
 */

#define CSS_NUM_CUB_PAGES		2
#define CSS_CUES_PER_PAGE		128

/*
 * Conditions used to specify which subchannels need evaluation
 */
@@ -122,8 +129,7 @@ struct channel_subsystem {
	struct mutex mutex;
	/* channel measurement related */
	int cm_enabled;
	void *cub_addr1;
	void *cub_addr2;
	void *cub[CSS_NUM_CUB_PAGES];
	/* for orphaned ccw devices */
	struct subchannel *pseudo_subchannel;
};