⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chsc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		ret = -EIO;		break;	default:		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",			      secm_area->response.code);		ret = -EIO;	}	return ret;}intchsc_secm(struct channel_subsystem *css, int enable){	void  *secm_area;	int ret;	secm_area = (void *)get_zeroed_page(GFP_KERNEL |  GFP_DMA);	if (!secm_area)		return -ENOMEM;	mutex_lock(&css->mutex);	if (enable && !css->cm_enabled) {		css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);		css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);		if (!css->cub_addr1 || !css->cub_addr2) {			free_page((unsigned long)css->cub_addr1);			free_page((unsigned long)css->cub_addr2);			free_page((unsigned long)secm_area);			mutex_unlock(&css->mutex);			return -ENOMEM;		}	}	ret = __chsc_do_secm(css, enable, secm_area);	if (!ret) {		css->cm_enabled = enable;		if (css->cm_enabled) {			ret = chsc_add_cmg_attr(css);			if (ret) {				memset(secm_area, 0, PAGE_SIZE);				__chsc_do_secm(css, 0, secm_area);				css->cm_enabled = 0;			}		} else			chsc_remove_cmg_attr(css);	}	if (enable && !css->cm_enabled) {		free_page((unsigned long)css->cub_addr1);		free_page((unsigned long)css->cub_addr2);	}	mutex_unlock(&css->mutex);	free_page((unsigned long)secm_area);	return ret;}/* * Files for the channel path entries. */static ssize_tchp_status_show(struct device *dev, struct device_attribute *attr, char *buf){	struct channel_path *chp = container_of(dev, struct channel_path, dev);	if (!chp)		return 0;	return (get_chp_status(chp->id) ? sprintf(buf, "online\n") :		sprintf(buf, "offline\n"));}static ssize_tchp_status_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){	struct channel_path *cp = container_of(dev, struct channel_path, dev);	char cmd[10];	int num_args;	int error;	num_args = sscanf(buf, "%5s", cmd);	if (!num_args)		return count;	if (!strnicmp(cmd, "on", 2))		error = s390_vary_chpid(cp->id, 1);	else if (!strnicmp(cmd, "off", 3))		error = s390_vary_chpid(cp->id, 0);	else		error = -EINVAL;	return error < 0 ? error : count;}static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);static ssize_tchp_type_show(struct device *dev, struct device_attribute *attr, char *buf){	struct channel_path *chp = container_of(dev, struct channel_path, dev);	if (!chp)		return 0;	return sprintf(buf, "%x\n", chp->desc.desc);}static DEVICE_ATTR(type, 0444, chp_type_show, NULL);static ssize_tchp_cmg_show(struct device *dev, struct device_attribute *attr, char *buf){	struct channel_path *chp = to_channelpath(dev);	if (!chp)		return 0;	if (chp->cmg == -1) /* channel measurements not available */		return sprintf(buf, "unknown\n");	return sprintf(buf, "%x\n", chp->cmg);}static DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL);static ssize_tchp_shared_show(struct device *dev, struct device_attribute *attr, char *buf){	struct channel_path *chp = to_channelpath(dev);	if (!chp)		return 0;	if (chp->shared == -1) /* channel measurements not available */		return sprintf(buf, "unknown\n");	return sprintf(buf, "%x\n", chp->shared);}static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL);static struct attribute * chp_attrs[] = {	&dev_attr_status.attr,	&dev_attr_type.attr,	&dev_attr_cmg.attr,	&dev_attr_shared.attr,	NULL,};static struct attribute_group chp_attr_group = {	.attrs = chp_attrs,};static voidchp_release(struct device *dev){	struct channel_path *cp;		cp = container_of(dev, struct channel_path, dev);	kfree(cp);}static intchsc_determine_channel_path_description(int chpid,					struct channel_path_desc *desc){	int ccode, ret;	struct {		struct chsc_header request;		u32 : 24;		u32 first_chpid : 8;		u32 : 24;		u32 last_chpid : 8;		u32 zeroes1;		struct chsc_header response;		u32 zeroes2;		struct channel_path_desc desc;	} *scpd_area;	scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!scpd_area)		return -ENOMEM;	scpd_area->request.length = 0x0010;	scpd_area->request.code = 0x0002;	scpd_area->first_chpid = chpid;	scpd_area->last_chpid = chpid;	ccode = chsc(scpd_area);	if (ccode > 0) {		ret = (ccode == 3) ? -ENODEV : -EBUSY;		goto out;	}	switch (scpd_area->response.code) {	case 0x0001: /* Success. */		memcpy(desc, &scpd_area->desc,		       sizeof(struct channel_path_desc));		ret = 0;		break;	case 0x0003: /* Invalid block. */	case 0x0007: /* Invalid format. */	case 0x0008: /* Other invalid block. */		CIO_CRW_EVENT(2, "Error in chsc request block!\n");		ret = -EINVAL;		break;	case 0x0004: /* Command not provided in model. */		CIO_CRW_EVENT(2, "Model does not provide scpd\n");		ret = -EOPNOTSUPP;		break;	default:		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",			      scpd_area->response.code);		ret = -EIO;	}out:	free_page((unsigned long)scpd_area);	return ret;}static voidchsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,			  struct cmg_chars *chars){	switch (chp->cmg) {	case 2:	case 3:		chp->cmg_chars = kmalloc(sizeof(struct cmg_chars),					 GFP_KERNEL);		if (chp->cmg_chars) {			int i, mask;			struct cmg_chars *cmg_chars;			cmg_chars = chp->cmg_chars;			for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {				mask = 0x80 >> (i + 3);				if (cmcv & mask)					cmg_chars->values[i] = chars->values[i];				else					cmg_chars->values[i] = 0;			}		}		break;	default:		/* No cmg-dependent data. */		break;	}}static intchsc_get_channel_measurement_chars(struct channel_path *chp){	int ccode, ret;	struct {		struct chsc_header request;		u32 : 24;		u32 first_chpid : 8;		u32 : 24;		u32 last_chpid : 8;		u32 zeroes1;		struct chsc_header response;		u32 zeroes2;		u32 not_valid : 1;		u32 shared : 1;		u32 : 22;		u32 chpid : 8;		u32 cmcv : 5;		u32 : 11;		u32 cmgq : 8;		u32 cmg : 8;		u32 zeroes3;		u32 data[NR_MEASUREMENT_CHARS];	} *scmc_area;	scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!scmc_area)		return -ENOMEM;	scmc_area->request.length = 0x0010;	scmc_area->request.code = 0x0022;	scmc_area->first_chpid = chp->id;	scmc_area->last_chpid = chp->id;	ccode = chsc(scmc_area);	if (ccode > 0) {		ret = (ccode == 3) ? -ENODEV : -EBUSY;		goto out;	}	switch (scmc_area->response.code) {	case 0x0001: /* Success. */		if (!scmc_area->not_valid) {			chp->cmg = scmc_area->cmg;			chp->shared = scmc_area->shared;			chsc_initialize_cmg_chars(chp, scmc_area->cmcv,						  (struct cmg_chars *)						  &scmc_area->data);		} else {			chp->cmg = -1;			chp->shared = -1;		}		ret = 0;		break;	case 0x0003: /* Invalid block. */	case 0x0007: /* Invalid format. */	case 0x0008: /* Invalid bit combination. */		CIO_CRW_EVENT(2, "Error in chsc request block!\n");		ret = -EINVAL;		break;	case 0x0004: /* Command not provided. */		CIO_CRW_EVENT(2, "Model does not provide scmc\n");		ret = -EOPNOTSUPP;		break;	default:		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",			      scmc_area->response.code);		ret = -EIO;	}out:	free_page((unsigned long)scmc_area);	return ret;}/* * Entries for chpids on the system bus. * This replaces /proc/chpids. */static intnew_channel_path(int chpid){	struct channel_path *chp;	int ret;	chp = kzalloc(sizeof(struct channel_path), GFP_KERNEL);	if (!chp)		return -ENOMEM;	/* fill in status, etc. */	chp->id = chpid;	chp->state = 1;	chp->dev = (struct device) {		.parent  = &css[0]->device,		.release = chp_release,	};	snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);	/* Obtain channel path description and fill it in. */	ret = chsc_determine_channel_path_description(chpid, &chp->desc);	if (ret)		goto out_free;	/* Get channel-measurement characteristics. */	if (css_characteristics_avail && css_chsc_characteristics.scmc	    && css_chsc_characteristics.secm) {		ret = chsc_get_channel_measurement_chars(chp);		if (ret)			goto out_free;	} else {		static int msg_done;		if (!msg_done) {			printk(KERN_WARNING "cio: Channel measurements not "			       "available, continuing.\n");			msg_done = 1;		}		chp->cmg = -1;	}	/* make it known to the system */	ret = device_register(&chp->dev);	if (ret) {		printk(KERN_WARNING "%s: could not register %02x\n",		       __func__, chpid);		goto out_free;	}	ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);	if (ret) {		device_unregister(&chp->dev);		goto out_free;	}	mutex_lock(&css[0]->mutex);	if (css[0]->cm_enabled) {		ret = chsc_add_chp_cmg_attr(chp);		if (ret) {			sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);			device_unregister(&chp->dev);			mutex_unlock(&css[0]->mutex);			goto out_free;		}	}	css[0]->chps[chpid] = chp;	mutex_unlock(&css[0]->mutex);	return ret;out_free:	kfree(chp);	return ret;}void *chsc_get_chp_desc(struct subchannel *sch, int chp_no){	struct channel_path *chp;	struct channel_path_desc *desc;	chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];	if (!chp)		return NULL;	desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);	if (!desc)		return NULL;	memcpy(desc, &chp->desc, sizeof(struct channel_path_desc));	return desc;}static int __initchsc_alloc_sei_area(void){	sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!sei_page)		printk(KERN_WARNING"Can't allocate page for processing of " \		       "chsc machine checks!\n");	return (sei_page ? 0 : -ENOMEM);}int __initchsc_enable_facility(int operation_code){	int ret;	struct {		struct chsc_header request;		u8 reserved1:4;		u8 format:4;		u8 reserved2;		u16 operation_code;		u32 reserved3;		u32 reserved4;		u32 operation_data_area[252];		struct chsc_header response;		u32 reserved5:4;		u32 format2:4;		u32 reserved6:24;	} *sda_area;	sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);	if (!sda_area)		return -ENOMEM;	sda_area->request.length = 0x0400;	sda_area->request.code = 0x0031;	sda_area->operation_code = operation_code;	ret = chsc(sda_area);	if (ret > 0) {		ret = (ret == 3) ? -ENODEV : -EBUSY;		goto out;	}	switch (sda_area->response.code) {	case 0x0001: /* everything ok */		ret = 0;		break;	case 0x0003: /* invalid request block */	case 0x0007:		ret = -EINVAL;		break;	case 0x0004: /* command not provided */	case 0x0101: /* facility not provided */		ret = -EOPNOTSUPP;		break;	default: /* something went wrong */		ret = -EIO;	} out:	free_page((unsigned long)sda_area);	return ret;}subsys_initcall(chsc_alloc_sei_area);struct css_general_char css_general_characteristics;struct css_chsc_char css_chsc_characteristics;int __initchsc_determine_css_characteristics(void){	int result;	struct {		struct chsc_header request;		u32 reserved1;		u32 reserved2;		u32 reserved3;		struct chsc_header response;		u32 reserved4;		u32 general_char[510];		u32 chsc_char[518];	} *scsc_area;	scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);	if (!scsc_area) {	        printk(KERN_WARNING"cio: Was not able to determine available" \		       "CHSCs due to no memory.\n");		return -ENOMEM;	}	scsc_area->request.length = 0x0010;	scsc_area->request.code = 0x0010;	result = chsc(scsc_area);	if (result) {		printk(KERN_WARNING"cio: Was not able to determine " \		       "available CHSCs, cc=%i.\n", result);		result = -EIO;		goto exit;	}	if (scsc_area->response.code != 1) {		printk(KERN_WARNING"cio: Was not able to determine " \		       "available CHSCs.\n");		result = -EIO;		goto exit;	}	memcpy(&css_general_characteristics, scsc_area->general_char,	       sizeof(css_general_characteristics));	memcpy(&css_chsc_characteristics, scsc_area->chsc_char,	       sizeof(css_chsc_characteristics));exit:	free_page ((unsigned long) scsc_area);	return result;}EXPORT_SYMBOL_GPL(css_general_characteristics);EXPORT_SYMBOL_GPL(css_chsc_characteristics);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -