dasd_devmap.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 713 行 · 第 1/2 页

C
713
字号
			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;		if (devmap->features & DASD_FEATURE_READONLY)			set_bit(DASD_FLAG_RO, &device->flags);		else			clear_bit(DASD_FLAG_RO, &device->flags);		if (devmap->features & DASD_FEATURE_USEDIAG)			set_bit(DASD_FLAG_USE_DIAG, &device->flags);		else			clear_bit(DASD_FLAG_USE_DIAG, &device->flags);		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);	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, char *buf){	struct dasd_devmap *devmap;	int ro_flag;	devmap = dev->driver_data;	if (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, const char *buf, size_t count){	struct dasd_devmap *devmap;	int ro_flag;	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));	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) {		if (devmap->device->gdp)			set_disk_ro(devmap->device->gdp, ro_flag);		if (ro_flag)			set_bit(DASD_FLAG_RO, &devmap->device->flags);		else			clear_bit(DASD_FLAG_RO, &devmap->device->flags);	}	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 *//* TODO: Implement */static ssize_t dasd_use_diag_show(struct device *dev, char *buf){	struct dasd_devmap *devmap;	int use_diag;	devmap = dev->driver_data;	if (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, const char *buf, size_t count){	struct dasd_devmap *devmap;	int use_diag;	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));	use_diag = buf[0] == '1';	spin_lock(&dasd_devmap_lock);	/* Changing diag discipline flag is only allowed in offline state. */	if (!devmap->device) {		if (use_diag)			devmap->features |= DASD_FEATURE_USEDIAG;		else			devmap->features &= ~DASD_FEATURE_USEDIAG;	} else		count = -EPERM;	spin_unlock(&dasd_devmap_lock);	return count;}staticDEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);static ssize_tdasd_discipline_show(struct device *dev, 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,};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 + =
减小字号Ctrl + -
显示快捷键?