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

📄 dasd_devmap.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	spin_lock(&dasd_devmap_lock);	devmap = ERR_PTR(-ENODEV);	hash = dasd_hash_busid(bus_id);	list_for_each_entry(tmp, &dasd_hashlists[hash], list) {		if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {			devmap = tmp;			break;		}	}	spin_unlock(&dasd_devmap_lock);	return devmap;}/* * Check if busid has been added to the list of dasd ranges. */intdasd_busid_known(char *bus_id){	return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;}/* * Forget all about the device numbers added so far. * This may only be called at module unload or system shutdown. */static voiddasd_forget_ranges(void){	struct dasd_devmap *devmap, *n;	int i;	spin_lock(&dasd_devmap_lock);	for (i = 0; i < 256; i++) {		list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {			if (devmap->device != NULL)				BUG();			list_del(&devmap->list);			kfree(devmap);		}	}	spin_unlock(&dasd_devmap_lock);}/* * Find the device struct by its device index. */struct dasd_device *dasd_device_from_devindex(int devindex){	struct dasd_devmap *devmap, *tmp;	struct dasd_device *device;	int i;	spin_lock(&dasd_devmap_lock);	devmap = 0;	for (i = 0; (i < 256) && !devmap; i++)		list_for_each_entry(tmp, &dasd_hashlists[i], list)			if (tmp->devindex == devindex) {				/* Found the devmap for the device. */				devmap = tmp;				break;			}	if (devmap && devmap->device) {		device = devmap->device;		dasd_get_device(device);	} else		device = ERR_PTR(-ENODEV);	spin_unlock(&dasd_devmap_lock);	return device;}/* * Return devmap for cdev. If no devmap exists yet, create one and * connect it to the cdev. */static struct dasd_devmap *dasd_devmap_from_cdev(struct ccw_device *cdev){	struct dasd_devmap *devmap;	devmap = dasd_find_busid(cdev->dev.bus_id);	if (IS_ERR(devmap))		devmap = dasd_add_busid(cdev->dev.bus_id,					DASD_FEATURE_DEFAULT);	return devmap;}/* * Create a dasd device structure for cdev. */struct dasd_device *dasd_create_device(struct ccw_device *cdev){	struct dasd_devmap *devmap;	struct dasd_device *device;	int rc;	devmap = dasd_devmap_from_cdev(cdev);	if (IS_ERR(devmap))		return (void *) devmap;	cdev->dev.driver_data = devmap;	device = dasd_alloc_device();	if (IS_ERR(device))		return device;	atomic_set(&device->ref_count, 2);	spin_lock(&dasd_devmap_lock);	if (!devmap->device) {		devmap->device = device;		device->devindex = devmap->devindex;		device->features = devmap->features;		get_device(&cdev->dev);		device->cdev = cdev;		rc = 0;	} else		/* Someone else was faster. */		rc = -EBUSY;	spin_unlock(&dasd_devmap_lock);	if (rc) {		dasd_free_device(device);		return ERR_PTR(rc);	}	return device;}/* * Wait queue for dasd_delete_device waits. */static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);/* * Remove a dasd device structure. The passed referenced * is destroyed. */voiddasd_delete_device(struct dasd_device *device){	struct ccw_device *cdev;	struct dasd_devmap *devmap;	/* First remove device pointer from devmap. */	devmap = dasd_find_busid(device->cdev->dev.bus_id);	if (IS_ERR(devmap))		BUG();	spin_lock(&dasd_devmap_lock);	if (devmap->device != device) {		spin_unlock(&dasd_devmap_lock);		dasd_put_device(device);		return;	}	devmap->device = NULL;	spin_unlock(&dasd_devmap_lock);	/* Drop ref_count by 2, one for the devmap reference and	 * one for the passed reference. */	atomic_sub(2, &device->ref_count);	/* Wait for reference counter to drop to zero. */	wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);	/* Disconnect dasd_device structure from ccw_device structure. */	cdev = device->cdev;	device->cdev = NULL;	/* Disconnect dasd_devmap structure from ccw_device structure. */	cdev->dev.driver_data = NULL;	/* Put ccw_device structure. */	put_device(&cdev->dev);	/* Now the device structure can be freed. */	dasd_free_device(device);}/* * Reference counter dropped to zero. Wake up waiter * in dasd_delete_device. */voiddasd_put_device_wake(struct dasd_device *device){	wake_up(&dasd_delete_wq);}/* * Return dasd_device structure associated with cdev. */struct dasd_device *dasd_device_from_cdev(struct ccw_device *cdev){	struct dasd_devmap *devmap;	struct dasd_device *device;	device = ERR_PTR(-ENODEV);	spin_lock(&dasd_devmap_lock);	devmap = cdev->dev.driver_data;	if (devmap && devmap->device) {		device = devmap->device;		dasd_get_device(device);	}	spin_unlock(&dasd_devmap_lock);	return device;}/* * SECTION: files in sysfs *//* * readonly controls the readonly status of a dasd */static ssize_tdasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf){	struct dasd_devmap *devmap;	int ro_flag;	devmap = dasd_find_busid(dev->bus_id);	if (!IS_ERR(devmap))		ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;	else		ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;	return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");}static ssize_tdasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){	struct dasd_devmap *devmap;	int ro_flag;	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));	if (IS_ERR(devmap))		return PTR_ERR(devmap);	ro_flag = buf[0] == '1';	spin_lock(&dasd_devmap_lock);	if (ro_flag)		devmap->features |= DASD_FEATURE_READONLY;	else		devmap->features &= ~DASD_FEATURE_READONLY;	if (devmap->device)		devmap->device->features = devmap->features;	if (devmap->device && devmap->device->gdp)		set_disk_ro(devmap->device->gdp, ro_flag);	spin_unlock(&dasd_devmap_lock);	return count;}static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);/* * use_diag controls whether the driver should use diag rather than ssch * to talk to the device */static ssize_t dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf){	struct dasd_devmap *devmap;	int use_diag;	devmap = dasd_find_busid(dev->bus_id);	if (!IS_ERR(devmap))		use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;	else		use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;	return sprintf(buf, use_diag ? "1\n" : "0\n");}static ssize_tdasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){	struct dasd_devmap *devmap;	ssize_t rc;	int use_diag;	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));	if (IS_ERR(devmap))		return PTR_ERR(devmap);	use_diag = buf[0] == '1';	spin_lock(&dasd_devmap_lock);	/* Changing diag discipline flag is only allowed in offline state. */	rc = count;	if (!devmap->device) {		if (use_diag)			devmap->features |= DASD_FEATURE_USEDIAG;		else			devmap->features &= ~DASD_FEATURE_USEDIAG;	} else		rc = -EPERM;	spin_unlock(&dasd_devmap_lock);	return rc;}staticDEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);static ssize_tdasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf){	struct dasd_devmap *devmap;	char *dname;	spin_lock(&dasd_devmap_lock);	dname = "none";	devmap = dev->driver_data;	if (devmap && devmap->device && devmap->device->discipline)		dname = devmap->device->discipline->name;	spin_unlock(&dasd_devmap_lock);	return snprintf(buf, PAGE_SIZE, "%s\n", dname);}static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);static struct attribute * dasd_attrs[] = {	&dev_attr_readonly.attr,	&dev_attr_discipline.attr,	&dev_attr_use_diag.attr,	NULL,};static struct attribute_group dasd_attr_group = {	.attrs = dasd_attrs,};/* * Return value of the specified feature. */intdasd_get_feature(struct ccw_device *cdev, int feature){	struct dasd_devmap *devmap;	devmap = dasd_find_busid(cdev->dev.bus_id);	if (IS_ERR(devmap))		return (int) PTR_ERR(devmap);	return ((devmap->features & feature) != 0);}/* * Set / reset given feature. * Flag indicates wether to set (!=0) or the reset (=0) the feature. */intdasd_set_feature(struct ccw_device *cdev, int feature, int flag){	struct dasd_devmap *devmap;	devmap = dasd_find_busid(cdev->dev.bus_id);	if (IS_ERR(devmap))		return (int) PTR_ERR(devmap);	spin_lock(&dasd_devmap_lock);	if (flag)		devmap->features |= feature;	else		devmap->features &= ~feature;	if (devmap->device)		devmap->device->features = devmap->features;	spin_unlock(&dasd_devmap_lock);	return 0;}intdasd_add_sysfs_files(struct ccw_device *cdev){	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);}voiddasd_remove_sysfs_files(struct ccw_device *cdev){	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);}intdasd_devmap_init(void){	int i;	/* Initialize devmap structures. */	dasd_max_devindex = 0;	for (i = 0; i < 256; i++)		INIT_LIST_HEAD(&dasd_hashlists[i]);	return 0;}voiddasd_devmap_exit(void){	dasd_forget_ranges();}

⌨️ 快捷键说明

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