Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *   S/390 common I/O routines -- channel subsystem call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *    Copyright IBM Corp. 1999,2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *		 Cornelia Huck (cornelia.huck@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *		 Arnd Bergmann (arndb@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #define KMSG_COMPONENT "cio"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <asm/cio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <asm/chpid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <asm/chsc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <asm/crw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <asm/isc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <asm/ap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include "css.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include "cio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include "cio_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include "ioasm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include "chp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include "chsc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) static void *sei_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) static void *chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) static DEFINE_SPINLOCK(chsc_page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  * chsc_error_from_response() - convert a chsc response to an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  * @response: chsc response code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44)  * Returns an appropriate Linux error code for @response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) int chsc_error_from_response(int response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	switch (response) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	case 0x0001:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	case 0x0002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	case 0x0003:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	case 0x0006:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	case 0x0007:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	case 0x0008:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	case 0x000a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	case 0x0104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	case 0x0004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	case 0x0106:		/* "Wrong Channel Parm" for the op 0x003d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	case 0x000b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	case 0x0107:		/* "Channel busy" for the op 0x003d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	case 0x0100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	case 0x0102:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	case 0x0108:		/* "HW limit exceeded" for the op 0x003d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 		return -EUSERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) EXPORT_SYMBOL_GPL(chsc_error_from_response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) struct chsc_ssd_area {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	u16 :10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	u16 ssid:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	u16 :4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	u16 f_sch;	  /* first subchannel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	u16 :16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	u16 l_sch;	  /* last subchannel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	u32 :32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	u32 :32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	u8 sch_valid : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	u8 dev_valid : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	u8 st	     : 3; /* subchannel type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	u8 zeroes    : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	u8  unit_addr;	  /* unit address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	u16 devno;	  /* device number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	u8 path_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	u8 fla_valid_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	u16 sch;	  /* subchannel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	u8 chpid[8];	  /* chpids 0-7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	u16 fla[8];	  /* full link addresses 0-7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) } __packed __aligned(PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	struct chsc_ssd_area *ssd_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	ssd_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	ssd_area->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	ssd_area->request.code = 0x0004;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	ssd_area->ssid = schid.ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	ssd_area->f_sch = schid.sch_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	ssd_area->l_sch = schid.sch_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	ccode = chsc(ssd_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	/* Check response. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	if (ccode > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 		ret = (ccode == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	ret = chsc_error_from_response(ssd_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		CIO_MSG_EVENT(2, "chsc: ssd failed for 0.%x.%04x (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 			      schid.ssid, schid.sch_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 			      ssd_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	if (!ssd_area->sch_valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	/* Copy data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	memset(ssd, 0, sizeof(struct chsc_ssd_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	if ((ssd_area->st != SUBCHANNEL_TYPE_IO) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	    (ssd_area->st != SUBCHANNEL_TYPE_MSG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	ssd->path_mask = ssd_area->path_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	ssd->fla_valid_mask = ssd_area->fla_valid_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		mask = 0x80 >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		if (ssd_area->path_mask & mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 			chp_id_init(&ssd->chpid[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 			ssd->chpid[i].id = ssd_area->chpid[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		if (ssd_area->fla_valid_mask & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 			ssd->fla[i] = ssd_area->fla[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158)  * chsc_ssqd() - store subchannel QDIO data (SSQD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159)  * @schid: id of the subchannel on which SSQD is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)  * @ssqd: request and response block for SSQD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) int chsc_ssqd(struct subchannel_id schid, struct chsc_ssqd_area *ssqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	memset(ssqd, 0, sizeof(*ssqd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	ssqd->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	ssqd->request.code = 0x0024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	ssqd->first_sch = schid.sch_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	ssqd->last_sch = schid.sch_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	ssqd->ssid = schid.ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	if (chsc(ssqd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	return chsc_error_from_response(ssqd->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) EXPORT_SYMBOL_GPL(chsc_ssqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  * chsc_sadc() - set adapter device controls (SADC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  * @schid: id of the subchannel on which SADC is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  * @scssc: request and response block for SADC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  * @summary_indicator_addr: summary indicator address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  * @subchannel_indicator_addr: subchannel indicator address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  * @isc: Interruption Subclass for this subchannel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188)  * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) int chsc_sadc(struct subchannel_id schid, struct chsc_scssc_area *scssc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	      u64 summary_indicator_addr, u64 subchannel_indicator_addr, u8 isc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	memset(scssc, 0, sizeof(*scssc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	scssc->request.length = 0x0fe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	scssc->request.code = 0x0021;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	scssc->operation_code = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	scssc->summary_indicator_addr = summary_indicator_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	scssc->subchannel_indicator_addr = subchannel_indicator_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	scssc->ks = PAGE_DEFAULT_KEY >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	scssc->kc = PAGE_DEFAULT_KEY >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	scssc->isc = isc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	scssc->schid = schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	/* enable the time delay disablement facility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	if (css_general_characteristics.aif_tdd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		scssc->word_with_d_bit = 0x10000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	if (chsc(scssc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	return chsc_error_from_response(scssc->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) EXPORT_SYMBOL_GPL(chsc_sadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	spin_lock_irq(sch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	if (sch->driver && sch->driver->chp_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 		if (sch->driver->chp_event(sch, data, CHP_OFFLINE) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 			goto out_unreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	spin_unlock_irq(sch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) out_unreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	sch->lpm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	spin_unlock_irq(sch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	css_schedule_eval(sch->schid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) void chsc_chp_offline(struct chp_id chpid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	struct channel_path *chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	struct chp_link link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	char dbf_txt[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	CIO_TRACE_EVENT(2, dbf_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	if (chp_get_status(chpid) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	memset(&link, 0, sizeof(struct chp_link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	link.chpid = chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	/* Wait until previous actions have settled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	css_wait_for_slow_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	chp_update_desc(chp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) static int __s390_process_res_acc(struct subchannel *sch, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	spin_lock_irq(sch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	if (sch->driver && sch->driver->chp_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 		sch->driver->chp_event(sch, data, CHP_ONLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	spin_unlock_irq(sch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) static void s390_process_res_acc(struct chp_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	char dbf_txt[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	sprintf(dbf_txt, "accpr%x.%02x", link->chpid.cssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		link->chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	CIO_TRACE_EVENT( 2, dbf_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	if (link->fla != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 		sprintf(dbf_txt, "fla%x", link->fla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 		CIO_TRACE_EVENT( 2, dbf_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	/* Wait until previous actions have settled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	css_wait_for_slow_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	 * I/O resources may have become accessible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	 * Scan through all subchannels that may be concerned and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	 * do a validation on those.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	 * The more information we have (info), the less scanning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	 * will we have to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	for_each_subchannel_staged(__s390_process_res_acc, NULL, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	css_schedule_reprobe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) struct chsc_sei_nt0_area {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	u8  flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	u8  vf;				/* validity flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	u8  rs;				/* reporting source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	u8  cc;				/* content code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	u16 fla;			/* full link address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	u16 rsid;			/* reporting source id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	u32 reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	u32 reserved2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	/* ccdf has to be big enough for a link-incident record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	u8  ccdf[PAGE_SIZE - 24 - 16];	/* content-code dependent field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) struct chsc_sei_nt2_area {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	u8  flags;			/* p and v bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	u8  reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	u8  reserved2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	u8  cc;				/* content code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	u32 reserved3[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	u8  ccdf[PAGE_SIZE - 24 - 56];	/* content-code dependent field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) #define CHSC_SEI_NT0	(1ULL << 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) #define CHSC_SEI_NT2	(1ULL << 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) struct chsc_sei {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	u32 reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	u64 ntsm;			/* notification type mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	u32 :24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	u8 nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		struct chsc_sei_nt0_area nt0_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		struct chsc_sei_nt2_area nt2_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		u8 nt_area[PAGE_SIZE - 24];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	} u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) } __packed __aligned(PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)  * Link Incident Record as defined in SA22-7202, "ESCON I/O Interface"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) #define LIR_IQ_CLASS_INFO		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) #define LIR_IQ_CLASS_DEGRADED		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) #define LIR_IQ_CLASS_NOT_OPERATIONAL	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) struct lir {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		u32 null:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		u32 reserved:3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		u32 class:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		u32 reserved2:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	} __packed iq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	u32 ic:8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	u32 reserved:16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	struct node_descriptor incident_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	struct node_descriptor attached_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	u8 reserved2[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) #define PARAMS_LEN	10	/* PARAMS=xx,xxxxxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) #define NODEID_LEN	35	/* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) /* Copy EBCIDC text, convert to ASCII and optionally add delimiter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) static char *store_ebcdic(char *dest, const char *src, unsigned long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 			  char delim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	memcpy(dest, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	EBCASC(dest, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	if (delim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		dest[len++] = delim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	return dest + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) /* Format node ID and parameters for output in LIR log message. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) static void format_node_data(char *params, char *id, struct node_descriptor *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	memset(params, 0, PARAMS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	memset(id, 0, NODEID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	if (nd->validity != ND_VALIDITY_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		strncpy(params, "n/a", PARAMS_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		strncpy(id, "n/a", NODEID_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	/* PARAMS=xx,xxxxxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	snprintf(params, PARAMS_LEN, "%02x,%06x", nd->byte0, nd->params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	/* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	id = store_ebcdic(id, nd->type, sizeof(nd->type), '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	id = store_ebcdic(id, nd->model, sizeof(nd->model), ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	id = store_ebcdic(id, nd->manufacturer, sizeof(nd->manufacturer), '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	id = store_ebcdic(id, nd->plant, sizeof(nd->plant), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	id = store_ebcdic(id, nd->seq, sizeof(nd->seq), ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	sprintf(id, "%04X", nd->tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	struct lir *lir = (struct lir *) &sei_area->ccdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	char iuparams[PARAMS_LEN], iunodeid[NODEID_LEN], auparams[PARAMS_LEN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	     aunodeid[NODEID_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x, iq=%02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		      sei_area->rs, sei_area->rsid, sei_area->ccdf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	/* Ignore NULL Link Incident Records. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	if (lir->iq.null)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	/* Inform user that a link requires maintenance actions because it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	 * become degraded or not operational. Note that this log message is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	 * the primary intention behind a Link Incident Record. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	format_node_data(iuparams, iunodeid, &lir->incident_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	format_node_data(auparams, aunodeid, &lir->attached_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	switch (lir->iq.class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	case LIR_IQ_CLASS_DEGRADED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		pr_warn("Link degraded: RS=%02x RSID=%04x IC=%02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 			"IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 			sei_area->rs, sei_area->rsid, lir->ic, iuparams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 			iunodeid, auparams, aunodeid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	case LIR_IQ_CLASS_NOT_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		pr_err("Link stopped: RS=%02x RSID=%04x IC=%02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		       "IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		       sei_area->rs, sei_area->rsid, lir->ic, iuparams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		       iunodeid, auparams, aunodeid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	struct channel_path *chp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	struct chp_link link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		      "rs_id=%04x)\n", sei_area->rs, sei_area->rsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	if (sei_area->rs != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	chpid.id = sei_area->rsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	/* allocate a new channel path structure, if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	status = chp_get_status(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		chp_new(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		chp_update_desc(chp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	memset(&link, 0, sizeof(struct chp_link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	link.chpid = chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	if ((sei_area->vf & 0xc0) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		link.fla = sei_area->fla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		if ((sei_area->vf & 0xc0) == 0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			/* full link address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 			link.fla_mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 			/* link address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 			link.fla_mask = 0xff00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	s390_process_res_acc(&link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) static void chsc_process_sei_chp_avail(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	struct channel_path *chp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	CIO_CRW_EVENT(4, "chsc: channel path availability information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	if (sei_area->rs != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	data = sei_area->ccdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	for (num = 0; num <= __MAX_CHPID; num++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		if (!chp_test_bit(data, num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		chpid.id = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		CIO_CRW_EVENT(4, "Update information for channel path "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 			      "%x.%02x\n", chpid.cssid, chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		if (!chp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 			chp_new(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		chp_update_desc(chp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 		mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) struct chp_config_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	u8 map[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	u8 op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	u8 pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) static void chsc_process_sei_chp_config(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	struct chp_config_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	struct chp_id chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	char *events[3] = {"configure", "deconfigure", "cancel deconfigure"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	CIO_CRW_EVENT(4, "chsc: channel-path-configuration notification\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	if (sei_area->rs != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	data = (struct chp_config_data *) &(sei_area->ccdf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	chp_id_init(&chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	for (num = 0; num <= __MAX_CHPID; num++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		if (!chp_test_bit(data->map, num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		chpid.id = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		pr_notice("Processing %s for channel path %x.%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 			  events[data->op], chpid.cssid, chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		switch (data->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 			chp_cfg_schedule(chpid, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 			chp_cfg_schedule(chpid, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 			chp_cfg_cancel_deconfigure(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	CIO_CRW_EVENT(4, "chsc: scm change notification\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	if (sei_area->rs != 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	ret = scm_update_information();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		CIO_CRW_EVENT(0, "chsc: updating change notification"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 			      " failed (rc=%d).\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) static void chsc_process_sei_scm_avail(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	CIO_CRW_EVENT(4, "chsc: scm available information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	if (sei_area->rs != 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	ret = scm_process_availability_information();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		CIO_CRW_EVENT(0, "chsc: process availability information"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 			      " failed (rc=%d).\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) static void chsc_process_sei_ap_cfg_chg(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	CIO_CRW_EVENT(3, "chsc: ap config changed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	if (sei_area->rs != 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	ap_bus_cfg_chg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	switch (sei_area->cc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		zpci_event_error(sei_area->ccdf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		zpci_event_availability(sei_area->ccdf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		CIO_CRW_EVENT(2, "chsc: sei nt2 unhandled cc=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 			      sei_area->cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	/* which kind of information was stored? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	switch (sei_area->cc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	case 1: /* link incident*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		chsc_process_sei_link_incident(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	case 2: /* i/o resource accessibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		chsc_process_sei_res_acc(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	case 3: /* ap config changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		chsc_process_sei_ap_cfg_chg(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	case 7: /* channel-path-availability information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		chsc_process_sei_chp_avail(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	case 8: /* channel-path-configuration notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		chsc_process_sei_chp_config(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	case 12: /* scm change notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		chsc_process_sei_scm_change(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	case 14: /* scm available notification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		chsc_process_sei_scm_avail(sei_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	default: /* other stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 			      sei_area->cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	/* Check if we might have lost some information. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	if (sei_area->flags & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		CIO_CRW_EVENT(2, "chsc: event overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		css_schedule_eval_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	static int ntsm_unsupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		memset(sei, 0, sizeof(*sei));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		sei->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		sei->request.code = 0x000e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		if (!ntsm_unsupported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 			sei->ntsm = ntsm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 		if (chsc(sei))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		if (sei->response.code != 0x0001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 			CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x, ntsm=%llx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 				      sei->response.code, sei->ntsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			if (sei->response.code == 3 && sei->ntsm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 				/* Fallback for old firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 				ntsm_unsupported = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		CIO_CRW_EVENT(2, "chsc: sei successful (nt=%d)\n", sei->nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		switch (sei->nt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			chsc_process_sei_nt0(&sei->u.nt0_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			chsc_process_sei_nt2(&sei->u.nt2_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		if (!(sei->u.nt0_area.flags & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672)  * Handle channel subsystem related CRWs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673)  * Use store event information to find out what's going on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)  * Note: Access to sei_page is serialized through machine check handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)  * thread, so no need for locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	struct chsc_sei *sei = sei_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	if (overflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		css_schedule_eval_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		      crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		      crw0->erc, crw0->rsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	CIO_TRACE_EVENT(2, "prcss");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	chsc_process_event_information(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) void chsc_chp_online(struct chp_id chpid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	struct channel_path *chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	struct chp_link link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	char dbf_txt[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	CIO_TRACE_EVENT(2, dbf_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	if (chp_get_status(chpid) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		memset(&link, 0, sizeof(struct chp_link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		link.chpid = chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		/* Wait until previous actions have settled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		css_wait_for_slow_path();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		mutex_lock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		chp_update_desc(chp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		mutex_unlock(&chp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		for_each_subchannel_staged(__s390_process_res_acc, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 					   &link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		css_schedule_reprobe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) static void __s390_subchannel_vary_chpid(struct subchannel *sch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 					 struct chp_id chpid, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	struct chp_link link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	memset(&link, 0, sizeof(struct chp_link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	link.chpid = chpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	spin_lock_irqsave(sch->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	if (sch->driver && sch->driver->chp_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		sch->driver->chp_event(sch, &link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 				       on ? CHP_VARY_ON : CHP_VARY_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	spin_unlock_irqrestore(sch->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) static int s390_subchannel_vary_chpid_off(struct subchannel *sch, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	struct chp_id *chpid = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	__s390_subchannel_vary_chpid(sch, *chpid, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	struct chp_id *chpid = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	__s390_subchannel_vary_chpid(sch, *chpid, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752)  * chsc_chp_vary - propagate channel-path vary operation to subchannels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753)  * @chpid: channl-path ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754)  * @on: non-zero for vary online, zero for vary offline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) int chsc_chp_vary(struct chp_id chpid, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	struct channel_path *chp = chpid_to_chp(chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	 * Redo PathVerification on the devices the chpid connects to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		/* Try to update the channel path description. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		chp_update_desc(chp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 					   NULL, &chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 		css_schedule_reprobe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 					   NULL, &chpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) chsc_remove_cmg_attr(struct channel_subsystem *css)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	for (i = 0; i <= __MAX_CHPID; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		if (!css->chps[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		chp_remove_cmg_attr(css->chps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) chsc_add_cmg_attr(struct channel_subsystem *css)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	for (i = 0; i <= __MAX_CHPID; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		if (!css->chps[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		ret = chp_add_cmg_attr(css->chps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	for (--i; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		if (!css->chps[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		chp_remove_cmg_attr(css->chps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) int __chsc_do_secm(struct channel_subsystem *css, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		u32 operation_code : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		u32 : 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		u32 key : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		u32 : 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		u32 zeroes1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		u32 cub_addr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		u32 zeroes2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		u32 cub_addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		u32 reserved[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		u32 status : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		u32 : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 		u32 fmt : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		u32 : 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	} *secm_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	int ret, ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	secm_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	secm_area->request.length = 0x0050;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	secm_area->request.code = 0x0016;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	secm_area->key = PAGE_DEFAULT_KEY >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	secm_area->operation_code = enable ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	ccode = chsc(secm_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	if (ccode > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		ret = (ccode == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	switch (secm_area->response.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	case 0x0102:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	case 0x0103:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		ret = chsc_error_from_response(secm_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		CIO_CRW_EVENT(2, "chsc: secm failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			      secm_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) chsc_secm(struct channel_subsystem *css, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	if (enable && !css->cm_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		if (!css->cub_addr1 || !css->cub_addr2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			free_page((unsigned long)css->cub_addr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 			free_page((unsigned long)css->cub_addr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	ret = __chsc_do_secm(css, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		css->cm_enabled = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		if (css->cm_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 			ret = chsc_add_cmg_attr(css);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 				__chsc_do_secm(css, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 				css->cm_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 			chsc_remove_cmg_attr(css);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	if (!css->cm_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 		free_page((unsigned long)css->cub_addr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		free_page((unsigned long)css->cub_addr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 				     int c, int m, void *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	struct chsc_scpd *scpd_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	int ccode, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	if ((rfmt == 1 || rfmt == 0) && c == 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	    !css_general_characteristics.fcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if ((rfmt == 2) && !css_general_characteristics.cib)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	if ((rfmt == 3) && !css_general_characteristics.util_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	memset(page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	scpd_area = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	scpd_area->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	scpd_area->request.code = 0x0002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	scpd_area->cssid = chpid.cssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	scpd_area->first_chpid = chpid.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	scpd_area->last_chpid = chpid.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	scpd_area->m = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	scpd_area->c = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	scpd_area->fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	scpd_area->rfmt = rfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	ccode = chsc(scpd_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	if (ccode > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		return (ccode == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	ret = chsc_error_from_response(scpd_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 			      scpd_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) #define chsc_det_chp_desc(FMT, c)					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) int chsc_determine_fmt##FMT##_channel_path_desc(			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	struct chp_id chpid, struct channel_path_desc_fmt##FMT *desc)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) {									\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	struct chsc_scpd *scpd_area;					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	unsigned long flags;						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	int ret;							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 									\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	spin_lock_irqsave(&chsc_page_lock, flags);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	scpd_area = chsc_page;						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	ret = chsc_determine_channel_path_desc(chpid, 0, FMT, c, 0,	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 					       scpd_area);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	if (ret)							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		goto out;						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 									\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	memcpy(desc, scpd_area->data, sizeof(*desc));			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) out:									\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	spin_unlock_irqrestore(&chsc_page_lock, flags);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	return ret;							\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) chsc_det_chp_desc(0, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) chsc_det_chp_desc(1, 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) chsc_det_chp_desc(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			  struct cmg_chars *chars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	int i, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		mask = 0x80 >> (i + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		if (cmcv & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 			chp->cmg_chars.values[i] = chars->values[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 			chp->cmg_chars.values[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) int chsc_get_channel_measurement_chars(struct channel_path *chp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	int ccode, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		u32 : 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		u32 first_chpid : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		u32 : 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		u32 last_chpid : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 		u32 zeroes1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		u32 zeroes2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		u32 not_valid : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		u32 shared : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		u32 : 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		u32 chpid : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		u32 cmcv : 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		u32 : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		u32 cmgq : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		u32 cmg : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		u32 zeroes3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		u32 data[NR_MEASUREMENT_CHARS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	} *scmc_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	chp->shared = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	chp->cmg = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	if (!css_chsc_characteristics.scmc || !css_chsc_characteristics.secm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	scmc_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	scmc_area->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	scmc_area->request.code = 0x0022;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	scmc_area->first_chpid = chp->chpid.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	scmc_area->last_chpid = chp->chpid.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	ccode = chsc(scmc_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	if (ccode > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		ret = (ccode == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	ret = chsc_error_from_response(scmc_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		CIO_CRW_EVENT(2, "chsc: scmc failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 			      scmc_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	if (scmc_area->not_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	chp->cmg = scmc_area->cmg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	chp->shared = scmc_area->shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	if (chp->cmg != 2 && chp->cmg != 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		/* No cmg-dependent data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 				  (struct cmg_chars *) &scmc_area->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) int __init chsc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	chsc_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	if (!sei_page || !chsc_page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	free_page((unsigned long)chsc_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	free_page((unsigned long)sei_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) void __init chsc_init_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	crw_unregister_handler(CRW_RSC_CSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	free_page((unsigned long)chsc_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	free_page((unsigned long)sei_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int __chsc_enable_facility(struct chsc_sda_area *sda_area, int operation_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	sda_area->request.length = 0x0400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	sda_area->request.code = 0x0031;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	sda_area->operation_code = operation_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	ret = chsc(sda_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		ret = (ret == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	switch (sda_area->response.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	case 0x0101:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		ret = chsc_error_from_response(sda_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) int chsc_enable_facility(int operation_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	struct chsc_sda_area *sda_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	sda_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	ret = __chsc_enable_facility(sda_area, operation_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			      operation_code, sda_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		u8 atype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		u32 : 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		u32 reserved1[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		u32 reserved2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 			u8 cssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 			u8 iid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 			u32 : 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		} list[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	} *sdcal_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	spin_lock_irq(&chsc_page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	sdcal_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	sdcal_area->request.length = 0x0020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	sdcal_area->request.code = 0x0034;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	sdcal_area->atype = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	ret = chsc(sdcal_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 		ret = (ret == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	ret = chsc_error_from_response(sdcal_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 		CIO_CRW_EVENT(2, "chsc: sdcal failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			      sdcal_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	if ((addr_t) &sdcal_area->list[idx] <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	    (addr_t) &sdcal_area->response + sdcal_area->response.length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 		*cssid = sdcal_area->list[idx].cssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		*iid = sdcal_area->list[idx].iid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	spin_unlock_irq(&chsc_page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct css_general_char css_general_characteristics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) struct css_chsc_char css_chsc_characteristics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) chsc_determine_css_characteristics(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 		u32 reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		u32 reserved2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		u32 reserved3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		u32 reserved4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		u32 general_char[510];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		u32 chsc_char[508];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	} *scsc_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	scsc_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	scsc_area->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	scsc_area->request.code = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	result = chsc(scsc_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		result = (result == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	result = chsc_error_from_response(scsc_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	if (result == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		memcpy(&css_general_characteristics, scsc_area->general_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		       sizeof(css_general_characteristics));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		memcpy(&css_chsc_characteristics, scsc_area->chsc_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		       sizeof(css_chsc_characteristics));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		CIO_CRW_EVENT(2, "chsc: scsc failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 			      scsc_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) EXPORT_SYMBOL_GPL(css_general_characteristics);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) EXPORT_SYMBOL_GPL(css_chsc_characteristics);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 		unsigned int rsvd0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		unsigned int op : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 		unsigned int rsvd1 : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		unsigned int ctrl : 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 		unsigned int rsvd2[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		unsigned int rsvd3[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		u64 clock_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		unsigned int rsvd4[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	} *rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	memset(page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	rr = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	rr->request.length = 0x0020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	rr->request.code = 0x0033;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	rr->op = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	rr->ctrl = ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	rc = chsc(rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	rc = (rr->response.code == 0x0001) ? 0 : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	if (clock_delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		*clock_delta = rr->clock_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int chsc_sstpi(void *page, void *result, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		unsigned int rsvd0[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		char data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	} *rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	memset(page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 	rr = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	rr->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	rr->request.code = 0x0038;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	rc = chsc(rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 	memcpy(result, &rr->data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	return (rr->response.code == 0x0001) ? 0 : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) int chsc_stzi(void *page, void *result, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		unsigned int rsvd0[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		char data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	} *rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	memset(page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	rr = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	rr->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	rr->request.code = 0x003e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	rc = chsc(rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	memcpy(result, &rr->data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	return (rr->response.code == 0x0001) ? 0 : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) int chsc_siosl(struct subchannel_id schid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 		u32 word1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		struct subchannel_id sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 		u32 word3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 		u32 word[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	} *siosl_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	int ccode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	spin_lock_irqsave(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	siosl_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	siosl_area->request.length = 0x0010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	siosl_area->request.code = 0x0046;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	siosl_area->word1 = 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	siosl_area->sid = schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	ccode = chsc(siosl_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 	if (ccode > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 		if (ccode == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 			rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 			rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		CIO_MSG_EVENT(2, "chsc: chsc failed for 0.%x.%04x (ccode=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 			      schid.ssid, schid.sch_no, ccode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 	rc = chsc_error_from_response(siosl_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		CIO_MSG_EVENT(2, "chsc: siosl failed for 0.%x.%04x (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 			      schid.ssid, schid.sch_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 			      siosl_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 		CIO_MSG_EVENT(4, "chsc: siosl succeeded for 0.%x.%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 			      schid.ssid, schid.sch_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	spin_unlock_irqrestore(&chsc_page_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) EXPORT_SYMBOL_GPL(chsc_siosl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)  * chsc_scm_info() - store SCM information (SSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)  * @scm_area: request and response block for SSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)  * @token: continuation token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)  * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	int ccode, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 	memset(scm_area, 0, sizeof(*scm_area));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	scm_area->request.length = 0x0020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 	scm_area->request.code = 0x004C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 	scm_area->reqtok = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	ccode = chsc(scm_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	if (ccode > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 		ret = (ccode == 3) ? -ENODEV : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	ret = chsc_error_from_response(scm_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		CIO_MSG_EVENT(2, "chsc: scm info failed (rc=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 			      scm_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) EXPORT_SYMBOL_GPL(chsc_scm_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)  * chsc_pnso() - Perform Network-Subchannel Operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)  * @schid:		id of the subchannel on which PNSO is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)  * @pnso_area:		request and response block for the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)  * @oc:			Operation Code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)  * @resume_token:	resume token for multiblock response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)  * @cnc:		Boolean change-notification control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)  * pnso_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)  * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	      u8 oc, struct chsc_pnso_resume_token resume_token, int cnc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	memset(pnso_area, 0, sizeof(*pnso_area));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	pnso_area->request.length = 0x0030;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 	pnso_area->request.code = 0x003d; /* network-subchannel operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	pnso_area->m	   = schid.m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 	pnso_area->ssid  = schid.ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	pnso_area->sch	 = schid.sch_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 	pnso_area->cssid = schid.cssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 	pnso_area->oc	 = oc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	pnso_area->resume_token = resume_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	pnso_area->n	   = (cnc != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	if (chsc(pnso_area))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	return chsc_error_from_response(pnso_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) int chsc_sgib(u32 origin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 		struct chsc_header request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		u16 op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 		u8  reserved01[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		u8  reserved02:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		u8  fmt:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		u8  reserved03[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		/* operation data area begin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		u8  reserved04[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		u32 gib_origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		u8  reserved05[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 		u8  aix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		u8  reserved06[4029];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		struct chsc_header response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		u8  reserved07[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	} *sgib_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	spin_lock_irq(&chsc_page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	memset(chsc_page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	sgib_area = chsc_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	sgib_area->request.length = 0x0fe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	sgib_area->request.code = 0x0021;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	sgib_area->op = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	sgib_area->gib_origin = origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	ret = chsc(sgib_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 	if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 		ret = chsc_error_from_response(sgib_area->response.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	spin_unlock_irq(&chsc_page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) EXPORT_SYMBOL_GPL(chsc_sgib);