aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndrew Patterson <andrew.patterson@hp.com>2009-06-02 08:48:39 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-06-02 08:48:39 -0400
commit7fe063268e73681cdca1a6496a25f93d3332f517 (patch)
tree97c9b5f53012908343af83c481c0b8fad888690e /drivers
parent88f627ae394eadd75ada669904269f1a4a77b3bd (diff)
cciss: add cciss driver sysfs entries
Add sysfs entries to the cciss driver needed for the dm/multipath tools. A file for vendor, model, rev, and unique_id is added for each logical drive under directory /sys/bus/pci/devices/<dev>/ccissX/cXdY. Where X = the controller (or host) number and Y is the logical drive number. A link from /sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY to /sys/block/cciss!cXdY/device is also created. A bus is created in /sys/bus/cciss. A link is created from the pci ccissX entry to /sys/bus/cciss/devices/ccissX. Please consider this for inclusion. Signed-off-by: Mike Miller <mike.miller@hp.com> Cc: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/cciss.c267
-rw-r--r--drivers/block/cciss.h24
2 files changed, 281 insertions, 10 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index cb43fb3af159..e7d00952dd4f 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -437,6 +437,194 @@ static void __devinit cciss_procinit(int i)
437} 437}
438#endif /* CONFIG_PROC_FS */ 438#endif /* CONFIG_PROC_FS */
439 439
440#define MAX_PRODUCT_NAME_LEN 19
441
442#define to_hba(n) container_of(n, struct ctlr_info, dev)
443#define to_drv(n) container_of(n, drive_info_struct, dev)
444
445static struct device_type cciss_host_type = {
446 .name = "cciss_host",
447};
448
449static ssize_t dev_show_unique_id(struct device *dev,
450 struct device_attribute *attr,
451 char *buf)
452{
453 drive_info_struct *drv = to_drv(dev);
454 struct ctlr_info *h = to_hba(drv->dev.parent);
455 __u8 sn[16];
456 unsigned long flags;
457 int ret = 0;
458
459 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
460 if (h->busy_configuring)
461 ret = -EBUSY;
462 else
463 memcpy(sn, drv->serial_no, sizeof(sn));
464 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
465
466 if (ret)
467 return ret;
468 else
469 return snprintf(buf, 16 * 2 + 2,
470 "%02X%02X%02X%02X%02X%02X%02X%02X"
471 "%02X%02X%02X%02X%02X%02X%02X%02X\n",
472 sn[0], sn[1], sn[2], sn[3],
473 sn[4], sn[5], sn[6], sn[7],
474 sn[8], sn[9], sn[10], sn[11],
475 sn[12], sn[13], sn[14], sn[15]);
476}
477DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL);
478
479static ssize_t dev_show_vendor(struct device *dev,
480 struct device_attribute *attr,
481 char *buf)
482{
483 drive_info_struct *drv = to_drv(dev);
484 struct ctlr_info *h = to_hba(drv->dev.parent);
485 char vendor[VENDOR_LEN + 1];
486 unsigned long flags;
487 int ret = 0;
488
489 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
490 if (h->busy_configuring)
491 ret = -EBUSY;
492 else
493 memcpy(vendor, drv->vendor, VENDOR_LEN + 1);
494 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
495
496 if (ret)
497 return ret;
498 else
499 return snprintf(buf, sizeof(vendor) + 1, "%s\n", drv->vendor);
500}
501DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL);
502
503static ssize_t dev_show_model(struct device *dev,
504 struct device_attribute *attr,
505 char *buf)
506{
507 drive_info_struct *drv = to_drv(dev);
508 struct ctlr_info *h = to_hba(drv->dev.parent);
509 char model[MODEL_LEN + 1];
510 unsigned long flags;
511 int ret = 0;
512
513 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
514 if (h->busy_configuring)
515 ret = -EBUSY;
516 else
517 memcpy(model, drv->model, MODEL_LEN + 1);
518 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
519
520 if (ret)
521 return ret;
522 else
523 return snprintf(buf, sizeof(model) + 1, "%s\n", drv->model);
524}
525DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL);
526
527static ssize_t dev_show_rev(struct device *dev,
528 struct device_attribute *attr,
529 char *buf)
530{
531 drive_info_struct *drv = to_drv(dev);
532 struct ctlr_info *h = to_hba(drv->dev.parent);
533 char rev[REV_LEN + 1];
534 unsigned long flags;
535 int ret = 0;
536
537 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
538 if (h->busy_configuring)
539 ret = -EBUSY;
540 else
541 memcpy(rev, drv->rev, REV_LEN + 1);
542 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
543
544 if (ret)
545 return ret;
546 else
547 return snprintf(buf, sizeof(rev) + 1, "%s\n", drv->rev);
548}
549DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL);
550
551static struct attribute *cciss_dev_attrs[] = {
552 &dev_attr_unique_id.attr,
553 &dev_attr_model.attr,
554 &dev_attr_vendor.attr,
555 &dev_attr_rev.attr,
556 NULL
557};
558
559static struct attribute_group cciss_dev_attr_group = {
560 .attrs = cciss_dev_attrs,
561};
562
563static struct attribute_group *cciss_dev_attr_groups[] = {
564 &cciss_dev_attr_group,
565 NULL
566};
567
568static struct device_type cciss_dev_type = {
569 .name = "cciss_device",
570 .groups = cciss_dev_attr_groups,
571};
572
573static struct bus_type cciss_bus_type = {
574 .name = "cciss",
575};
576
577
578/*
579 * Initialize sysfs entry for each controller. This sets up and registers
580 * the 'cciss#' directory for each individual controller under
581 * /sys/bus/pci/devices/<dev>/.
582 */
583static int cciss_create_hba_sysfs_entry(struct ctlr_info *h)
584{
585 device_initialize(&h->dev);
586 h->dev.type = &cciss_host_type;
587 h->dev.bus = &cciss_bus_type;
588 dev_set_name(&h->dev, "%s", h->devname);
589 h->dev.parent = &h->pdev->dev;
590
591 return device_add(&h->dev);
592}
593
594/*
595 * Remove sysfs entries for an hba.
596 */
597static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h)
598{
599 device_del(&h->dev);
600}
601
602/*
603 * Initialize sysfs for each logical drive. This sets up and registers
604 * the 'c#d#' directory for each individual logical drive under
605 * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from
606 * /sys/block/cciss!c#d# to this entry.
607 */
608static int cciss_create_ld_sysfs_entry(struct ctlr_info *h,
609 drive_info_struct *drv,
610 int drv_index)
611{
612 device_initialize(&drv->dev);
613 drv->dev.type = &cciss_dev_type;
614 drv->dev.bus = &cciss_bus_type;
615 dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index);
616 drv->dev.parent = &h->dev;
617 return device_add(&drv->dev);
618}
619
620/*
621 * Remove sysfs entries for a logical drive.
622 */
623static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv)
624{
625 device_del(&drv->dev);
626}
627
440/* 628/*
441 * For operations that cannot sleep, a command block is allocated at init, 629 * For operations that cannot sleep, a command block is allocated at init,
442 * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track 630 * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
@@ -1332,6 +1520,45 @@ static void cciss_softirq_done(struct request *rq)
1332 spin_unlock_irqrestore(&h->lock, flags); 1520 spin_unlock_irqrestore(&h->lock, flags);
1333} 1521}
1334 1522
1523/* This function gets the SCSI vendor, model, and revision of a logical drive
1524 * via the inquiry page 0. Model, vendor, and rev are set to empty strings if
1525 * they cannot be read.
1526 */
1527static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
1528 char *vendor, char *model, char *rev)
1529{
1530 int rc;
1531 InquiryData_struct *inq_buf;
1532
1533 *vendor = '\0';
1534 *model = '\0';
1535 *rev = '\0';
1536
1537 inq_buf = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
1538 if (!inq_buf)
1539 return;
1540
1541 if (withirq)
1542 rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf,
1543 sizeof(InquiryData_struct), 1, logvol,
1544 0, TYPE_CMD);
1545 else
1546 rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf,
1547 sizeof(InquiryData_struct), 1, logvol, 0, NULL,
1548 TYPE_CMD);
1549 if (rc == IO_OK) {
1550 memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN);
1551 vendor[VENDOR_LEN] = '\0';
1552 memcpy(model, &inq_buf->data_byte[16], MODEL_LEN);
1553 model[MODEL_LEN] = '\0';
1554 memcpy(rev, &inq_buf->data_byte[32], REV_LEN);
1555 rev[REV_LEN] = '\0';
1556 }
1557
1558 kfree(inq_buf);
1559 return;
1560}
1561
1335/* This function gets the serial number of a logical drive via 1562/* This function gets the serial number of a logical drive via
1336 * inquiry page 0x83. Serial no. is 16 bytes. If the serial 1563 * inquiry page 0x83. Serial no. is 16 bytes. If the serial
1337 * number cannot be had, for whatever reason, 16 bytes of 0xff 1564 * number cannot be had, for whatever reason, 16 bytes of 0xff
@@ -1372,7 +1599,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
1372 disk->first_minor = drv_index << NWD_SHIFT; 1599 disk->first_minor = drv_index << NWD_SHIFT;
1373 disk->fops = &cciss_fops; 1600 disk->fops = &cciss_fops;
1374 disk->private_data = &h->drv[drv_index]; 1601 disk->private_data = &h->drv[drv_index];
1375 disk->driverfs_dev = &h->pdev->dev; 1602 disk->driverfs_dev = &h->drv[drv_index].dev;
1376 1603
1377 /* Set up queue information */ 1604 /* Set up queue information */
1378 blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); 1605 blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
@@ -1463,6 +1690,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
1463 drvinfo->block_size = block_size; 1690 drvinfo->block_size = block_size;
1464 drvinfo->nr_blocks = total_size + 1; 1691 drvinfo->nr_blocks = total_size + 1;
1465 1692
1693 cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor,
1694 drvinfo->model, drvinfo->rev);
1466 cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, 1695 cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
1467 sizeof(drvinfo->serial_no)); 1696 sizeof(drvinfo->serial_no));
1468 1697
@@ -1512,6 +1741,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
1512 h->drv[drv_index].cylinders = drvinfo->cylinders; 1741 h->drv[drv_index].cylinders = drvinfo->cylinders;
1513 h->drv[drv_index].raid_level = drvinfo->raid_level; 1742 h->drv[drv_index].raid_level = drvinfo->raid_level;
1514 memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); 1743 memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16);
1744 memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1);
1745 memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1);
1746 memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1);
1515 1747
1516 ++h->num_luns; 1748 ++h->num_luns;
1517 disk = h->gendisk[drv_index]; 1749 disk = h->gendisk[drv_index];
@@ -1586,6 +1818,8 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
1586 } 1818 }
1587 } 1819 }
1588 h->drv[drv_index].LunID = lunid; 1820 h->drv[drv_index].LunID = lunid;
1821 if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index))
1822 goto err_free_disk;
1589 1823
1590 /* Don't need to mark this busy because nobody */ 1824 /* Don't need to mark this busy because nobody */
1591 /* else knows about this disk yet to contend */ 1825 /* else knows about this disk yet to contend */
@@ -1593,6 +1827,11 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
1593 h->drv[drv_index].busy_configuring = 0; 1827 h->drv[drv_index].busy_configuring = 0;
1594 wmb(); 1828 wmb();
1595 return drv_index; 1829 return drv_index;
1830
1831err_free_disk:
1832 put_disk(h->gendisk[drv_index]);
1833 h->gendisk[drv_index] = NULL;
1834 return -1;
1596} 1835}
1597 1836
1598/* This is for the special case of a controller which 1837/* This is for the special case of a controller which
@@ -1713,6 +1952,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time)
1713 h->drv[i].busy_configuring = 1; 1952 h->drv[i].busy_configuring = 1;
1714 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); 1953 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1715 return_code = deregister_disk(h, i, 1); 1954 return_code = deregister_disk(h, i, 1);
1955 cciss_destroy_ld_sysfs_entry(&h->drv[i]);
1716 h->drv[i].busy_configuring = 0; 1956 h->drv[i].busy_configuring = 0;
1717 } 1957 }
1718 } 1958 }
@@ -3719,12 +3959,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
3719 INIT_HLIST_HEAD(&hba[i]->reqQ); 3959 INIT_HLIST_HEAD(&hba[i]->reqQ);
3720 3960
3721 if (cciss_pci_init(hba[i], pdev) != 0) 3961 if (cciss_pci_init(hba[i], pdev) != 0)
3722 goto clean1; 3962 goto clean0;
3723 3963
3724 sprintf(hba[i]->devname, "cciss%d", i); 3964 sprintf(hba[i]->devname, "cciss%d", i);
3725 hba[i]->ctlr = i; 3965 hba[i]->ctlr = i;
3726 hba[i]->pdev = pdev; 3966 hba[i]->pdev = pdev;
3727 3967
3968 if (cciss_create_hba_sysfs_entry(hba[i]))
3969 goto clean0;
3970
3728 /* configure PCI DMA stuff */ 3971 /* configure PCI DMA stuff */
3729 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) 3972 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
3730 dac = 1; 3973 dac = 1;
@@ -3868,6 +4111,8 @@ clean4:
3868clean2: 4111clean2:
3869 unregister_blkdev(hba[i]->major, hba[i]->devname); 4112 unregister_blkdev(hba[i]->major, hba[i]->devname);
3870clean1: 4113clean1:
4114 cciss_destroy_hba_sysfs_entry(hba[i]);
4115clean0:
3871 hba[i]->busy_initializing = 0; 4116 hba[i]->busy_initializing = 0;
3872 /* cleanup any queues that may have been initialized */ 4117 /* cleanup any queues that may have been initialized */
3873 for (j=0; j <= hba[i]->highest_lun; j++){ 4118 for (j=0; j <= hba[i]->highest_lun; j++){
@@ -3978,6 +4223,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
3978 */ 4223 */
3979 pci_release_regions(pdev); 4224 pci_release_regions(pdev);
3980 pci_set_drvdata(pdev, NULL); 4225 pci_set_drvdata(pdev, NULL);
4226 cciss_destroy_hba_sysfs_entry(hba[i]);
3981 free_hba(i); 4227 free_hba(i);
3982} 4228}
3983 4229
@@ -3995,6 +4241,8 @@ static struct pci_driver cciss_pci_driver = {
3995 */ 4241 */
3996static int __init cciss_init(void) 4242static int __init cciss_init(void)
3997{ 4243{
4244 int err;
4245
3998 /* 4246 /*
3999 * The hardware requires that commands are aligned on a 64-bit 4247 * The hardware requires that commands are aligned on a 64-bit
4000 * boundary. Given that we use pci_alloc_consistent() to allocate an 4248 * boundary. Given that we use pci_alloc_consistent() to allocate an
@@ -4004,8 +4252,20 @@ static int __init cciss_init(void)
4004 4252
4005 printk(KERN_INFO DRIVER_NAME "\n"); 4253 printk(KERN_INFO DRIVER_NAME "\n");
4006 4254
4255 err = bus_register(&cciss_bus_type);
4256 if (err)
4257 return err;
4258
4007 /* Register for our PCI devices */ 4259 /* Register for our PCI devices */
4008 return pci_register_driver(&cciss_pci_driver); 4260 err = pci_register_driver(&cciss_pci_driver);
4261 if (err)
4262 goto err_bus_register;
4263
4264 return 0;
4265
4266err_bus_register:
4267 bus_unregister(&cciss_bus_type);
4268 return err;
4009} 4269}
4010 4270
4011static void __exit cciss_cleanup(void) 4271static void __exit cciss_cleanup(void)
@@ -4022,6 +4282,7 @@ static void __exit cciss_cleanup(void)
4022 } 4282 }
4023 } 4283 }
4024 remove_proc_entry("driver/cciss", NULL); 4284 remove_proc_entry("driver/cciss", NULL);
4285 bus_unregister(&cciss_bus_type);
4025} 4286}
4026 4287
4027static void fail_all_cmds(unsigned long ctlr) 4288static void fail_all_cmds(unsigned long ctlr)
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 703e08038fb9..dd1926d8cd97 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -12,6 +12,10 @@
12#define IO_OK 0 12#define IO_OK 0
13#define IO_ERROR 1 13#define IO_ERROR 1
14 14
15#define VENDOR_LEN 8
16#define MODEL_LEN 16
17#define REV_LEN 4
18
15struct ctlr_info; 19struct ctlr_info;
16typedef struct ctlr_info ctlr_info_t; 20typedef struct ctlr_info ctlr_info_t;
17 21
@@ -34,13 +38,18 @@ typedef struct _drive_info_struct
34 int cylinders; 38 int cylinders;
35 int raid_level; /* set to -1 to indicate that 39 int raid_level; /* set to -1 to indicate that
36 * the drive is not in use/configured 40 * the drive is not in use/configured
37 */ 41 */
38 int busy_configuring; /*This is set when the drive is being removed 42 int busy_configuring; /* This is set when a drive is being removed
39 *to prevent it from being opened or it's queue 43 * to prevent it from being opened or it's
40 *from being started. 44 * queue from being started.
41 */ 45 */
42 __u8 serial_no[16]; /* from inquiry page 0x83, */ 46 struct device dev;
43 /* not necc. null terminated. */ 47 __u8 serial_no[16]; /* from inquiry page 0x83,
48 * not necc. null terminated.
49 */
50 char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */
51 char model[MODEL_LEN + 1]; /* SCSI model string */
52 char rev[REV_LEN + 1]; /* SCSI revision string */
44} drive_info_struct; 53} drive_info_struct;
45 54
46#ifdef CONFIG_CISS_SCSI_TAPE 55#ifdef CONFIG_CISS_SCSI_TAPE
@@ -123,6 +132,7 @@ struct ctlr_info
123 unsigned char alive; 132 unsigned char alive;
124 struct completion *rescan_wait; 133 struct completion *rescan_wait;
125 struct task_struct *cciss_scan_thread; 134 struct task_struct *cciss_scan_thread;
135 struct device dev;
126}; 136};
127 137
128/* Defining the diffent access_menthods */ 138/* Defining the diffent access_menthods */