Commit cc236b9a authored by Mike Sullivan's avatar Mike Sullivan Committed by Linus Torvalds

linux-2.5.22-driverfs.patch

parent d9083ea2
...@@ -431,6 +431,11 @@ int unregister_cdrom(struct cdrom_device_info *unreg) ...@@ -431,6 +431,11 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
topCdromPtr = cdi->next; topCdromPtr = cdi->next;
cdi->ops->n_minors--; cdi->ops->n_minors--;
devfs_unregister (cdi->de); devfs_unregister (cdi->de);
if (atomic_read (&cdi->cdrom_driverfs_dev.refcount)) {
device_remove_file (&cdi->cdrom_driverfs_dev, "name");
device_remove_file (&cdi->cdrom_driverfs_dev, "kdev");
put_device (&cdi->cdrom_driverfs_dev);
}
devfs_dealloc_unique_number (&cdrom_numspace, cdi->number); devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
return 0; return 0;
......
...@@ -418,6 +418,11 @@ struct Scsi_Host ...@@ -418,6 +418,11 @@ struct Scsi_Host
*/ */
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
/*
* Support for driverfs filesystem
*/
struct device host_driverfs_dev;
/* /*
* We should ensure that this is aligned, both for better performance * We should ensure that this is aligned, both for better performance
* and also because some compilers (m68k) don't automatically force * and also because some compilers (m68k) don't automatically force
...@@ -478,6 +483,7 @@ static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt, ...@@ -478,6 +483,7 @@ static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
SHpnt->pci_dev = pdev; SHpnt->pci_dev = pdev;
SHpnt->host_driverfs_dev.parent=&pdev->dev;
} }
...@@ -516,6 +522,7 @@ struct Scsi_Device_Template ...@@ -516,6 +522,7 @@ struct Scsi_Device_Template
void (*detach)(Scsi_Device *); void (*detach)(Scsi_Device *);
int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code. int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code.
Selects command for blkdevs */ Selects command for blkdevs */
struct device_driver scsi_driverfs_driver;
}; };
void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt); void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
......
...@@ -1939,6 +1939,11 @@ int scsi_register_host(Scsi_Host_Template * tpnt) ...@@ -1939,6 +1939,11 @@ int scsi_register_host(Scsi_Host_Template * tpnt)
} }
printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */ printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */
shpnt->host_no, name); shpnt->host_no, name);
strncpy(shpnt->host_driverfs_dev.name,name,
DEVICE_NAME_SIZE-1);
sprintf(shpnt->host_driverfs_dev.bus_id,
"scsi%d",
shpnt->host_no);
} }
} }
...@@ -1947,6 +1952,8 @@ int scsi_register_host(Scsi_Host_Template * tpnt) ...@@ -1947,6 +1952,8 @@ int scsi_register_host(Scsi_Host_Template * tpnt)
*/ */
for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
if (shpnt->hostt == tpnt) { if (shpnt->hostt == tpnt) {
/* first register parent with driverfs */
device_register(&shpnt->host_driverfs_dev);
scan_scsis(shpnt, 0, 0, 0, 0); scan_scsis(shpnt, 0, 0, 0, 0);
if (shpnt->select_queue_depths != NULL) { if (shpnt->select_queue_depths != NULL) {
(shpnt->select_queue_depths) (shpnt, shpnt->host_queue); (shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
...@@ -2101,6 +2108,7 @@ int scsi_unregister_host(Scsi_Host_Template * tpnt) ...@@ -2101,6 +2108,7 @@ int scsi_unregister_host(Scsi_Host_Template * tpnt)
goto err_out; goto err_out;
} }
devfs_unregister (SDpnt->de); devfs_unregister (SDpnt->de);
put_device(&SDpnt->sdev_driverfs_dev);
} }
} }
...@@ -2151,6 +2159,7 @@ int scsi_unregister_host(Scsi_Host_Template * tpnt) ...@@ -2151,6 +2159,7 @@ int scsi_unregister_host(Scsi_Host_Template * tpnt)
/* Remove the /proc/scsi directory entry */ /* Remove the /proc/scsi directory entry */
sprintf(name,"%d",shpnt->host_no); sprintf(name,"%d",shpnt->host_no);
remove_proc_entry(name, tpnt->proc_dir); remove_proc_entry(name, tpnt->proc_dir);
put_device(&shpnt->host_driverfs_dev);
if (tpnt->release) if (tpnt->release)
(*tpnt->release) (shpnt); (*tpnt->release) (shpnt);
else { else {
...@@ -2499,6 +2508,34 @@ void scsi_free_sgtable(struct scatterlist *sgl, int index) ...@@ -2499,6 +2508,34 @@ void scsi_free_sgtable(struct scatterlist *sgl, int index)
mempool_free(sgl, sgp->pool); mempool_free(sgl, sgp->pool);
} }
static int scsi_bus_match(struct device *scsi_driverfs_dev,
struct device_driver *scsi_driverfs_drv)
{
char *p=0;
if (!strcmp("sd", scsi_driverfs_drv->name)) {
if ((p = strstr(scsi_driverfs_dev->bus_id, ":disc")) ||
(p = strstr(scsi_driverfs_dev->bus_id, ":p"))) {
return 1;
}
} else if (!strcmp("sg", scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id, ":gen"))
return 1;
} else if (!strcmp("sr",scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id,":cd"))
return 1;
} else if (!strcmp("st",scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id,":mt"))
return 1;
}
return 0;
}
struct bus_type scsi_driverfs_bus_type = {
name: "scsi",
match: scsi_bus_match,
};
static int __init init_scsi(void) static int __init init_scsi(void)
{ {
struct proc_dir_entry *generic; struct proc_dir_entry *generic;
...@@ -2544,6 +2581,8 @@ static int __init init_scsi(void) ...@@ -2544,6 +2581,8 @@ static int __init init_scsi(void)
if (scsihosts) if (scsihosts)
printk(KERN_INFO "scsi: host order: %s\n", scsihosts); printk(KERN_INFO "scsi: host order: %s\n", scsihosts);
scsi_host_no_init (scsihosts); scsi_host_no_init (scsihosts);
bus_register(&scsi_driverfs_bus_type);
/* /*
* This is where the processing takes place for most everything * This is where the processing takes place for most everything
* when commands are completed. * when commands are completed.
......
...@@ -417,6 +417,8 @@ extern unsigned int scsi_need_isa_buffer; /* True if some devices need indirecti ...@@ -417,6 +417,8 @@ extern unsigned int scsi_need_isa_buffer; /* True if some devices need indirecti
extern volatile int in_scan_scsis; extern volatile int in_scan_scsis;
extern const unsigned char scsi_command_size[8]; extern const unsigned char scsi_command_size[8];
extern struct bus_type scsi_driverfs_bus_type;
/* /*
* These are the error handling functions defined in scsi_error.c * These are the error handling functions defined in scsi_error.c
...@@ -622,6 +624,7 @@ struct scsi_device { ...@@ -622,6 +624,7 @@ struct scsi_device {
// Flag to allow revalidate to succeed in sd_open // Flag to allow revalidate to succeed in sd_open
int allow_revalidate; int allow_revalidate;
struct device sdev_driverfs_dev;
}; };
......
This diff is collapsed.
...@@ -101,3 +101,8 @@ extern void scsi_add_timer(Scsi_Cmnd *, int, void ((*) (Scsi_Cmnd *))); ...@@ -101,3 +101,8 @@ extern void scsi_add_timer(Scsi_Cmnd *, int, void ((*) (Scsi_Cmnd *)));
extern int scsi_delete_timer(Scsi_Cmnd *); extern int scsi_delete_timer(Scsi_Cmnd *);
EXPORT_SYMBOL(scsi_add_timer); EXPORT_SYMBOL(scsi_add_timer);
EXPORT_SYMBOL(scsi_delete_timer); EXPORT_SYMBOL(scsi_delete_timer);
/*
* driverfs support for determining driver types
*/
EXPORT_SYMBOL(scsi_driverfs_bus_type);
...@@ -128,6 +128,7 @@ static void sd_rw_intr(Scsi_Cmnd * SCpnt); ...@@ -128,6 +128,7 @@ static void sd_rw_intr(Scsi_Cmnd * SCpnt);
static Scsi_Disk * sd_get_sdisk(int index); static Scsi_Disk * sd_get_sdisk(int index);
extern void driverfs_remove_partitions(struct gendisk *hd, int minor);
#if defined(CONFIG_PPC32) #if defined(CONFIG_PPC32)
/** /**
...@@ -1276,12 +1277,15 @@ static int sd_init() ...@@ -1276,12 +1277,15 @@ static int sd_init()
init_mem_lth(sd_gendisks[k].de_arr, N); init_mem_lth(sd_gendisks[k].de_arr, N);
init_mem_lth(sd_gendisks[k].flags, N); init_mem_lth(sd_gendisks[k].flags, N);
init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags) if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
!sd_gendisks[k].driverfs_dev_arr)
goto cleanup_gendisks; goto cleanup_gendisks;
zero_mem_lth(sd_gendisks[k].de_arr, N); zero_mem_lth(sd_gendisks[k].de_arr, N);
zero_mem_lth(sd_gendisks[k].flags, N); zero_mem_lth(sd_gendisks[k].flags, N);
zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
sd_gendisks[k].major = SD_MAJOR(k); sd_gendisks[k].major = SD_MAJOR(k);
sd_gendisks[k].major_name = "sd"; sd_gendisks[k].major_name = "sd";
...@@ -1290,7 +1294,6 @@ static int sd_init() ...@@ -1290,7 +1294,6 @@ static int sd_init()
sd_gendisks[k].sizes = sd_sizes + k * (N << 4); sd_gendisks[k].sizes = sd_sizes + k * (N << 4);
sd_gendisks[k].nr_real = 0; sd_gendisks[k].nr_real = 0;
} }
return 0; return 0;
#undef init_mem_lth #undef init_mem_lth
...@@ -1301,6 +1304,7 @@ static int sd_init() ...@@ -1301,6 +1304,7 @@ static int sd_init()
for (k = 0; k < N_USED_SD_MAJORS; k++) { for (k = 0; k < N_USED_SD_MAJORS; k++) {
vfree(sd_gendisks[k].de_arr); vfree(sd_gendisks[k].de_arr);
vfree(sd_gendisks[k].flags); vfree(sd_gendisks[k].flags);
vfree(sd_gendisks[k].driverfs_dev_arr);
} }
cleanup_mem: cleanup_mem:
vfree(sd_gendisks); vfree(sd_gendisks);
...@@ -1435,6 +1439,8 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1435,6 +1439,8 @@ static int sd_attach(Scsi_Device * sdp)
SD_GENDISK(dsk_nr).nr_real++; SD_GENDISK(dsk_nr).nr_real++;
devnum = dsk_nr % SCSI_DISKS_PER_MAJOR; devnum = dsk_nr % SCSI_DISKS_PER_MAJOR;
SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de; SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] =
&sdp->sdev_driverfs_dev;
if (sdp->removable) if (sdp->removable)
SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE; SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
sd_dskname(dsk_nr, diskname); sd_dskname(dsk_nr, diskname);
...@@ -1534,6 +1540,8 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1534,6 +1540,8 @@ static void sd_detach(Scsi_Device * sdp)
max_p = 1 << sd_gendisk.minor_shift; max_p = 1 << sd_gendisk.minor_shift;
start = dsk_nr << sd_gendisk.minor_shift; start = dsk_nr << sd_gendisk.minor_shift;
dev = MKDEV_SD_PARTITION(start); dev = MKDEV_SD_PARTITION(start);
driverfs_remove_partitions(&SD_GENDISK (dsk_nr),
SD_MINOR_NUMBER (start));
wipe_partitions(dev); wipe_partitions(dev);
for (j = max_p - 1; j >= 0; j--) for (j = max_p - 1; j >= 0; j--)
sd_sizes[start + j] = 0; sd_sizes[start + j] = 0;
...@@ -1555,9 +1563,16 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1555,9 +1563,16 @@ static void sd_detach(Scsi_Device * sdp)
**/ **/
static int __init init_sd(void) static int __init init_sd(void)
{ {
int rc;
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
sd_template.module = THIS_MODULE; sd_template.module = THIS_MODULE;
return scsi_register_device(&sd_template); rc = scsi_register_device(&sd_template);
if (!rc) {
sd_template.scsi_driverfs_driver.name = (char *)sd_template.tag;
sd_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
driver_register(&sd_template.scsi_driverfs_driver);
}
return rc;
} }
/** /**
...@@ -1590,6 +1605,7 @@ static void __exit exit_sd(void) ...@@ -1590,6 +1605,7 @@ static void __exit exit_sd(void)
sd_template.dev_max = 0; sd_template.dev_max = 0;
if (sd_gendisks != &sd_gendisk) if (sd_gendisks != &sd_gendisk)
vfree(sd_gendisks); vfree(sd_gendisks);
remove_driver(&sd_template.scsi_driverfs_driver);
} }
static Scsi_Disk * sd_get_sdisk(int index) static Scsi_Disk * sd_get_sdisk(int index)
......
...@@ -194,6 +194,7 @@ typedef struct sg_device /* holds the state of each scsi generic device */ ...@@ -194,6 +194,7 @@ typedef struct sg_device /* holds the state of each scsi generic device */
volatile char detached; /* 0->attached, 1->detached pending removal */ volatile char detached; /* 0->attached, 1->detached pending removal */
volatile char exclude; /* opened for exclusive access */ volatile char exclude; /* opened for exclusive access */
char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
struct device sg_driverfs_dev;
} Sg_device; /* 36 bytes long on i386 */ } Sg_device; /* 36 bytes long on i386 */
...@@ -1370,6 +1371,29 @@ static int __init sg_def_reserved_size_setup(char *str) ...@@ -1370,6 +1371,29 @@ static int __init sg_def_reserved_size_setup(char *str)
__setup("sg_def_reserved_size=", sg_def_reserved_size_setup); __setup("sg_def_reserved_size=", sg_def_reserved_size_setup);
#endif #endif
/* Driverfs file support */
static ssize_t sg_device_kdev_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value);
}
static struct driver_file_entry sg_device_kdev_file = {
name: "kdev",
mode: S_IRUGO,
show: sg_device_kdev_read,
};
static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static struct driver_file_entry sg_device_type_file = {
name: "type",
mode: S_IRUGO,
show: sg_device_type_read,
};
static int sg_attach(Scsi_Device * scsidp) static int sg_attach(Scsi_Device * scsidp)
{ {
...@@ -1428,6 +1452,18 @@ static int sg_attach(Scsi_Device * scsidp) ...@@ -1428,6 +1452,18 @@ static int sg_attach(Scsi_Device * scsidp)
sdp->detached = 0; sdp->detached = 0;
sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0; sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k); sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
memset(&sdp->sg_driverfs_dev, 0, sizeof(struct device));
sprintf(sdp->sg_driverfs_dev.bus_id, "%s:gen",
scsidp->sdev_driverfs_dev.bus_id);
sprintf(sdp->sg_driverfs_dev.name, "%sgeneric",
scsidp->sdev_driverfs_dev.name);
sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type;
device_register(&sdp->sg_driverfs_dev);
device_create_file(&sdp->sg_driverfs_dev, &sg_device_type_file);
device_create_file(&sdp->sg_driverfs_dev, &sg_device_kdev_file);
sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT, sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
SCSI_GENERIC_MAJOR, k, SCSI_GENERIC_MAJOR, k,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
...@@ -1496,6 +1532,9 @@ static void sg_detach(Scsi_Device * scsidp) ...@@ -1496,6 +1532,9 @@ static void sg_detach(Scsi_Device * scsidp)
} }
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k)); SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k));
devfs_unregister (sdp->de); devfs_unregister (sdp->de);
device_remove_file(&sdp->sg_driverfs_dev,sg_device_type_file.name);
device_remove_file(&sdp->sg_driverfs_dev,sg_device_kdev_file.name);
put_device(&sdp->sg_driverfs_dev);
sdp->de = NULL; sdp->de = NULL;
if (NULL == sdp->headfp) { if (NULL == sdp->headfp) {
kfree((char *)sdp); kfree((char *)sdp);
...@@ -1505,6 +1544,7 @@ static void sg_detach(Scsi_Device * scsidp) ...@@ -1505,6 +1544,7 @@ static void sg_detach(Scsi_Device * scsidp)
else { /* nothing active, simple case */ else { /* nothing active, simple case */
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
devfs_unregister (sdp->de); devfs_unregister (sdp->de);
put_device(&sdp->sg_driverfs_dev);
kfree((char *)sdp); kfree((char *)sdp);
sg_dev_arr[k] = NULL; sg_dev_arr[k] = NULL;
} }
...@@ -1529,9 +1569,16 @@ MODULE_PARM(def_reserved_size, "i"); ...@@ -1529,9 +1569,16 @@ MODULE_PARM(def_reserved_size, "i");
MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
static int __init init_sg(void) { static int __init init_sg(void) {
int rc;
if (def_reserved_size >= 0) if (def_reserved_size >= 0)
sg_big_buff = def_reserved_size; sg_big_buff = def_reserved_size;
return scsi_register_device(&sg_template); rc = scsi_register_device(&sg_template);
if (!rc) {
sg_template.scsi_driverfs_driver.name = (char *)sg_template.tag;
sg_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
driver_register(&sg_template.scsi_driverfs_driver);
}
return rc;
} }
static void __exit exit_sg( void) static void __exit exit_sg( void)
...@@ -1546,6 +1593,7 @@ static void __exit exit_sg( void) ...@@ -1546,6 +1593,7 @@ static void __exit exit_sg( void)
sg_dev_arr = NULL; sg_dev_arr = NULL;
} }
sg_template.dev_max = 0; sg_template.dev_max = 0;
remove_driver(&sg_template.scsi_driverfs_driver);
} }
......
...@@ -730,6 +730,32 @@ static int sr_init() ...@@ -730,6 +730,32 @@ static int sr_init()
return 1; return 1;
} }
/* Driverfs file support */
static ssize_t sr_device_kdev_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
kdev_t kdev;
kdev.value=(int)driverfs_dev->driver_data;
return off ? 0 : sprintf(page, "%x\n",kdev.value);
}
static struct driver_file_entry sr_device_kdev_file = {
name: "kdev",
mode: S_IRUGO,
show: sr_device_kdev_read,
};
static ssize_t sr_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static struct driver_file_entry sr_device_type_file = {
name: "type",
mode: S_IRUGO,
show: sr_device_type_read,
};
void sr_finish() void sr_finish()
{ {
int i; int i;
...@@ -775,6 +801,20 @@ void sr_finish() ...@@ -775,6 +801,20 @@ void sr_finish()
sprintf(name, "sr%d", i); sprintf(name, "sr%d", i);
strcpy(SCp->cdi.name, name); strcpy(SCp->cdi.name, name);
sprintf(SCp->cdi.cdrom_driverfs_dev.bus_id, "%s:cd",
SCp->device->sdev_driverfs_dev.bus_id);
sprintf(SCp->cdi.cdrom_driverfs_dev.name, "%scdrom",
SCp->device->sdev_driverfs_dev.name);
SCp->cdi.cdrom_driverfs_dev.parent =
&SCp->device->sdev_driverfs_dev;
SCp->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type;
SCp->cdi.cdrom_driverfs_dev.driver_data =
(void *)__mkdev(MAJOR_NR, i);
device_register(&SCp->cdi.cdrom_driverfs_dev);
device_create_file(&SCp->cdi.cdrom_driverfs_dev,
&sr_device_type_file);
device_create_file(&SCp->cdi.cdrom_driverfs_dev,
&sr_device_kdev_file);
SCp->cdi.de = devfs_register(SCp->device->de, "cd", SCp->cdi.de = devfs_register(SCp->device->de, "cd",
DEVFS_FL_DEFAULT, MAJOR_NR, i, DEVFS_FL_DEFAULT, MAJOR_NR, i,
S_IFBLK | S_IRUGO | S_IWUGO, S_IFBLK | S_IRUGO | S_IWUGO,
...@@ -815,7 +855,14 @@ static void sr_detach(Scsi_Device * SDp) ...@@ -815,7 +855,14 @@ static void sr_detach(Scsi_Device * SDp)
static int __init init_sr(void) static int __init init_sr(void)
{ {
return scsi_register_device(&sr_template); int rc;
rc = scsi_register_device(&sr_template);
if (!rc) {
sr_template.scsi_driverfs_driver.name = (char *)sr_template.tag;
sr_template.scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
driver_register(&sr_template.scsi_driverfs_driver);
}
return rc;
} }
static void __exit exit_sr(void) static void __exit exit_sr(void)
...@@ -832,6 +879,7 @@ static void __exit exit_sr(void) ...@@ -832,6 +879,7 @@ static void __exit exit_sr(void)
blk_clear(MAJOR_NR); blk_clear(MAJOR_NR);
sr_template.dev_max = 0; sr_template.dev_max = 0;
remove_driver(&sr_template.scsi_driverfs_driver);
} }
module_init(init_sr); module_init(init_sr);
......
...@@ -3677,6 +3677,31 @@ __setup("st=", st_setup); ...@@ -3677,6 +3677,31 @@ __setup("st=", st_setup);
#endif #endif
/* Driverfs file support */
static ssize_t st_device_kdev_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
kdev_t kdev;
kdev.value=(int)driverfs_dev->driver_data;
return off ? 0 : sprintf(page, "%x\n",kdev.value);
}
static struct driver_file_entry st_device_kdev_file = {
name: "kdev",
mode: S_IRUGO,
show: st_device_kdev_read,
};
static ssize_t st_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static struct driver_file_entry st_device_type_file = {
name: "type",
mode: S_IRUGO,
show: st_device_type_read,
};
static struct file_operations st_fops = static struct file_operations st_fops =
{ {
...@@ -3779,6 +3804,18 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3779,6 +3804,18 @@ static int st_attach(Scsi_Device * SDp)
/* Rewind entry */ /* Rewind entry */
sprintf (name, "mt%s", formats[mode]); sprintf (name, "mt%s", formats[mode]);
sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.name, name);
sprintf(tpnt->driverfs_dev_r[mode].name, "%s%s",
SDp->sdev_driverfs_dev.name, name);
tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type;
tpnt->driverfs_dev_r[mode].driver_data =
(void *)__mkdev(MAJOR_NR, i + (mode << 5));
device_register(&tpnt->driverfs_dev_r[mode]);
device_create_file(&tpnt->driverfs_dev_r[mode],
&st_device_type_file);
device_create_file(&tpnt->driverfs_dev_r[mode], &st_device_kdev_file);
tpnt->de_r[mode] = tpnt->de_r[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, i + (mode << 5), MAJOR_NR, i + (mode << 5),
...@@ -3786,6 +3823,19 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3786,6 +3823,19 @@ static int st_attach(Scsi_Device * SDp)
&st_fops, NULL); &st_fops, NULL);
/* No-rewind entry */ /* No-rewind entry */
sprintf (name, "mt%sn", formats[mode]); sprintf (name, "mt%sn", formats[mode]);
sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.name, name);
sprintf(tpnt->driverfs_dev_n[mode].name, "%s%s",
SDp->sdev_driverfs_dev.name, name);
tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type;
tpnt->driverfs_dev_n[mode].driver_data =
(void *)__mkdev(MAJOR_NR, i + (mode << 5) + 128);
device_register(&tpnt->driverfs_dev_n[mode]);
device_create_file(&tpnt->driverfs_dev_n[mode],
&st_device_type_file);
device_create_file(&tpnt->driverfs_dev_n[mode],
&st_device_kdev_file);
tpnt->de_n[mode] = tpnt->de_n[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, i + (mode << 5) + 128, MAJOR_NR, i + (mode << 5) + 128,
...@@ -3894,8 +3944,18 @@ static void st_detach(Scsi_Device * SDp) ...@@ -3894,8 +3944,18 @@ static void st_detach(Scsi_Device * SDp)
for (mode = 0; mode < ST_NBR_MODES; ++mode) { for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_unregister (tpnt->de_r[mode]); devfs_unregister (tpnt->de_r[mode]);
tpnt->de_r[mode] = NULL; tpnt->de_r[mode] = NULL;
device_remove_file(&tpnt->driverfs_dev_r[mode],
st_device_type_file.name);
device_remove_file(&tpnt->driverfs_dev_r[mode],
st_device_kdev_file.name);
put_device(&tpnt->driverfs_dev_r[mode]);
devfs_unregister (tpnt->de_n[mode]); devfs_unregister (tpnt->de_n[mode]);
tpnt->de_n[mode] = NULL; tpnt->de_n[mode] = NULL;
device_remove_file(&tpnt->driverfs_dev_n[mode],
st_device_type_file.name);
device_remove_file(&tpnt->driverfs_dev_n[mode],
st_device_kdev_file.name);
put_device(&tpnt->driverfs_dev_n[mode]);
} }
kfree(tpnt); kfree(tpnt);
scsi_tapes[i] = 0; scsi_tapes[i] = 0;
...@@ -3921,8 +3981,16 @@ static int __init init_st(void) ...@@ -3921,8 +3981,16 @@ static int __init init_st(void)
verstr, st_buffer_size, st_write_threshold, verstr, st_buffer_size, st_write_threshold,
st_max_buffers, st_max_sg_segs); st_max_buffers, st_max_sg_segs);
if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
return scsi_register_device(&st_template); if (scsi_register_device(&st_template) == 0) {
st_template.scsi_driverfs_driver.name =
(char *)st_template.tag;
st_template.scsi_driverfs_driver.bus =
&scsi_driverfs_bus_type;
driver_register(&st_template.scsi_driverfs_driver);
return 0;
}
}
printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR); printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR);
return 1; return 1;
...@@ -3951,6 +4019,7 @@ static void __exit exit_st(void) ...@@ -3951,6 +4019,7 @@ static void __exit exit_st(void)
} }
} }
st_template.dev_max = 0; st_template.dev_max = 0;
remove_driver(&st_template.scsi_driverfs_driver);
printk(KERN_INFO "st: Unloaded.\n"); printk(KERN_INFO "st: Unloaded.\n");
} }
......
...@@ -94,6 +94,8 @@ typedef struct { ...@@ -94,6 +94,8 @@ typedef struct {
int current_mode; int current_mode;
devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */ devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */
devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */ devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */
struct device driverfs_dev_r[ST_NBR_MODES];
struct device driverfs_dev_n[ST_NBR_MODES];
/* Status variables */ /* Status variables */
int partition; int partition;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/raid/md.h> #include <linux/raid/md.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */ #include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/kmod.h>
#include "check.h" #include "check.h"
...@@ -221,6 +222,136 @@ void add_gd_partition(struct gendisk *hd, int minor, int start, int size) ...@@ -221,6 +222,136 @@ void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
#endif #endif
} }
/* Driverfs file support */
static ssize_t partition_device_kdev_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
kdev_t kdev;
kdev.value=(int)driverfs_dev->driver_data;
return off ? 0 : sprintf (page, "%x\n",kdev.value);
}
static struct driver_file_entry partition_device_kdev_file = {
name: "kdev",
mode: S_IRUGO,
show: partition_device_kdev_read,
};
static ssize_t partition_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "BLK\n");
}
static struct driver_file_entry partition_device_type_file = {
name: "type",
mode: S_IRUGO,
show: partition_device_type_read,
};
void driverfs_create_partitions(struct gendisk *hd, int minor)
{
int pos = -1;
int devnum = minor >> hd->minor_shift;
char dirname[256];
struct device *parent = 0;
int max_p;
int part;
devfs_handle_t dir = 0;
/* get parent driverfs device structure */
if (hd->driverfs_dev_arr)
parent = hd->driverfs_dev_arr[devnum];
else /* if driverfs not supported by subsystem, skip partitions */
return;
/* get parent device node directory name */
if (hd->de_arr) {
dir = hd->de_arr[devnum];
if (dir)
pos = devfs_generate_path (dir, dirname,
sizeof dirname);
}
if (pos < 0) {
disk_name(hd, minor, dirname);
pos = 0;
}
max_p = (1 << hd->minor_shift);
/* for all partitions setup parents and device node names */
for(part=0; part < max_p; part++) {
if ((part == 0) || (hd->part[minor + part].nr_sects >= 1)) {
struct device * current_driverfs_dev =
&hd->part[minor+part].hd_driverfs_dev;
current_driverfs_dev->parent = parent;
/* handle disc case */
current_driverfs_dev->driver_data =
(void *)__mkdev(hd->major, minor+part);
if (part == 0) {
if (parent) {
sprintf(current_driverfs_dev->name,
"%sdisc", parent->name);
sprintf(current_driverfs_dev->bus_id,
"%s:disc", parent->bus_id);
} else {
sprintf(current_driverfs_dev->name,
"disc");
sprintf(current_driverfs_dev->bus_id,
"disc");
}
} else { /* this is a partition */
if (parent) {
sprintf(current_driverfs_dev->name,
"%spart%d", parent->name, part);
sprintf(current_driverfs_dev->bus_id,
"%s:p%d", parent->bus_id, part);
} else {
sprintf(current_driverfs_dev->name,
"part%d", part);
sprintf(current_driverfs_dev->bus_id,
"p%d" ,part);
}
}
if (parent) current_driverfs_dev->bus = parent->bus;
device_register(current_driverfs_dev);
device_create_file(current_driverfs_dev,
&partition_device_type_file);
device_create_file(current_driverfs_dev,
&partition_device_kdev_file);
}
}
return;
}
void driverfs_remove_partitions(struct gendisk *hd, int minor)
{
int max_p;
int part;
struct device * current_driverfs_dev;
max_p=(1 << hd->minor_shift);
/* for all parts setup parent relationships and device node names */
for(part=1; part < max_p; part++) {
if ((hd->part[minor + part].nr_sects >= 1)) {
current_driverfs_dev =
&hd->part[minor + part].hd_driverfs_dev;
device_remove_file(current_driverfs_dev,
partition_device_type_file.name);
device_remove_file(current_driverfs_dev,
partition_device_kdev_file.name);
put_device(current_driverfs_dev);
}
}
current_driverfs_dev = &hd->part[minor].hd_driverfs_dev;
device_remove_file(current_driverfs_dev,
partition_device_type_file.name);
device_remove_file(current_driverfs_dev,
partition_device_kdev_file.name);
put_device(current_driverfs_dev);
return;
}
static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor) static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
{ {
devfs_handle_t de = NULL; devfs_handle_t de = NULL;
...@@ -281,6 +412,13 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor ...@@ -281,6 +412,13 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
truncate_inode_pages(bdev->bd_inode->i_mapping, 0); truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
bdput(bdev); bdput(bdev);
i = first_part_minor - 1; i = first_part_minor - 1;
/* Setup driverfs tree */
if (hd->sizes)
driverfs_create_partitions(hd, i);
else
driverfs_remove_partitions(hd, i);
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1); devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
} }
......
...@@ -716,6 +716,7 @@ struct request_sense { ...@@ -716,6 +716,7 @@ struct request_sense {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <linux/device.h>
struct cdrom_write_settings { struct cdrom_write_settings {
unsigned char fpacket; /* fixed/variable packets */ unsigned char fpacket; /* fixed/variable packets */
...@@ -730,6 +731,7 @@ struct cdrom_device_info { ...@@ -730,6 +731,7 @@ struct cdrom_device_info {
struct cdrom_device_info *next; /* next device_info for this major */ struct cdrom_device_info *next; /* next device_info for this major */
void *handle; /* driver-dependent data */ void *handle; /* driver-dependent data */
devfs_handle_t de; /* real driver should create this */ devfs_handle_t de; /* real driver should create this */
struct device cdrom_driverfs_dev; /* driverfs implementation */
int number; /* generic driver updates this */ int number; /* generic driver updates this */
/* specifications */ /* specifications */
kdev_t dev; /* device number */ kdev_t dev; /* device number */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/device.h>
enum { enum {
/* These three have identical behaviour; use the second one if DOS fdisk gets /* These three have identical behaviour; use the second one if DOS fdisk gets
...@@ -62,6 +63,7 @@ struct hd_struct { ...@@ -62,6 +63,7 @@ struct hd_struct {
unsigned long nr_sects; unsigned long nr_sects;
devfs_handle_t de; /* primary (master) devfs entry */ devfs_handle_t de; /* primary (master) devfs entry */
int number; /* stupid old code wastes space */ int number; /* stupid old code wastes space */
struct device hd_driverfs_dev; /* support driverfs hiearchy */
}; };
#define GENHD_FL_REMOVABLE 1 #define GENHD_FL_REMOVABLE 1
...@@ -80,6 +82,7 @@ struct gendisk { ...@@ -80,6 +82,7 @@ struct gendisk {
struct block_device_operations *fops; struct block_device_operations *fops;
devfs_handle_t *de_arr; /* one per physical disc */ devfs_handle_t *de_arr; /* one per physical disc */
struct device **driverfs_dev_arr;/* support driverfs hierarchy */
char *flags; /* one per physical disc */ char *flags; /* one per physical disc */
}; };
...@@ -241,6 +244,7 @@ char *disk_name (struct gendisk *hd, int minor, char *buf); ...@@ -241,6 +244,7 @@ char *disk_name (struct gendisk *hd, int minor, char *buf);
extern void devfs_register_partitions (struct gendisk *dev, int minor, extern void devfs_register_partitions (struct gendisk *dev, int minor,
int unregister); int unregister);
extern void driverfs_remove_partitions (struct gendisk *hd, int minor);
static inline unsigned int disk_index (kdev_t dev) static inline unsigned int disk_index (kdev_t dev)
{ {
......
...@@ -335,6 +335,7 @@ EXPORT_SYMBOL(bdev_read_only); ...@@ -335,6 +335,7 @@ EXPORT_SYMBOL(bdev_read_only);
EXPORT_SYMBOL(set_device_ro); EXPORT_SYMBOL(set_device_ro);
EXPORT_SYMBOL(bmap); EXPORT_SYMBOL(bmap);
EXPORT_SYMBOL(devfs_register_partitions); EXPORT_SYMBOL(devfs_register_partitions);
EXPORT_SYMBOL(driverfs_remove_partitions);
EXPORT_SYMBOL(blkdev_open); EXPORT_SYMBOL(blkdev_open);
EXPORT_SYMBOL(blkdev_get); EXPORT_SYMBOL(blkdev_get);
EXPORT_SYMBOL(blkdev_put); EXPORT_SYMBOL(blkdev_put);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment