diff options
-rw-r--r-- | drivers/block/cciss.c | 98 | ||||
-rw-r--r-- | drivers/block/cciss.h | 2 |
2 files changed, 73 insertions, 27 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e15f4acf08a2..30b328aefe7d 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -198,6 +198,8 @@ static void fail_all_cmds(unsigned long ctlr); | |||
198 | static int add_to_scan_list(struct ctlr_info *h); | 198 | static int add_to_scan_list(struct ctlr_info *h); |
199 | static int scan_thread(void *data); | 199 | static int scan_thread(void *data); |
200 | static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); | 200 | static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); |
201 | static void cciss_hba_release(struct device *dev); | ||
202 | static void cciss_device_release(struct device *dev); | ||
201 | 203 | ||
202 | #ifdef CONFIG_PROC_FS | 204 | #ifdef CONFIG_PROC_FS |
203 | static void cciss_procinit(int i); | 205 | static void cciss_procinit(int i); |
@@ -459,7 +461,6 @@ static void __devinit cciss_procinit(int i) | |||
459 | #define MAX_PRODUCT_NAME_LEN 19 | 461 | #define MAX_PRODUCT_NAME_LEN 19 |
460 | 462 | ||
461 | #define to_hba(n) container_of(n, struct ctlr_info, dev) | 463 | #define to_hba(n) container_of(n, struct ctlr_info, dev) |
462 | #define to_drv(n) container_of(n, drive_info_struct, dev) | ||
463 | 464 | ||
464 | static ssize_t host_store_rescan(struct device *dev, | 465 | static ssize_t host_store_rescan(struct device *dev, |
465 | struct device_attribute *attr, | 466 | struct device_attribute *attr, |
@@ -479,8 +480,8 @@ static ssize_t dev_show_unique_id(struct device *dev, | |||
479 | struct device_attribute *attr, | 480 | struct device_attribute *attr, |
480 | char *buf) | 481 | char *buf) |
481 | { | 482 | { |
482 | drive_info_struct *drv = to_drv(dev); | 483 | drive_info_struct *drv = dev_get_drvdata(dev); |
483 | struct ctlr_info *h = to_hba(drv->dev.parent); | 484 | struct ctlr_info *h = to_hba(drv->dev->parent); |
484 | __u8 sn[16]; | 485 | __u8 sn[16]; |
485 | unsigned long flags; | 486 | unsigned long flags; |
486 | int ret = 0; | 487 | int ret = 0; |
@@ -509,8 +510,8 @@ static ssize_t dev_show_vendor(struct device *dev, | |||
509 | struct device_attribute *attr, | 510 | struct device_attribute *attr, |
510 | char *buf) | 511 | char *buf) |
511 | { | 512 | { |
512 | drive_info_struct *drv = to_drv(dev); | 513 | drive_info_struct *drv = dev_get_drvdata(dev); |
513 | struct ctlr_info *h = to_hba(drv->dev.parent); | 514 | struct ctlr_info *h = to_hba(drv->dev->parent); |
514 | char vendor[VENDOR_LEN + 1]; | 515 | char vendor[VENDOR_LEN + 1]; |
515 | unsigned long flags; | 516 | unsigned long flags; |
516 | int ret = 0; | 517 | int ret = 0; |
@@ -533,8 +534,8 @@ static ssize_t dev_show_model(struct device *dev, | |||
533 | struct device_attribute *attr, | 534 | struct device_attribute *attr, |
534 | char *buf) | 535 | char *buf) |
535 | { | 536 | { |
536 | drive_info_struct *drv = to_drv(dev); | 537 | drive_info_struct *drv = dev_get_drvdata(dev); |
537 | struct ctlr_info *h = to_hba(drv->dev.parent); | 538 | struct ctlr_info *h = to_hba(drv->dev->parent); |
538 | char model[MODEL_LEN + 1]; | 539 | char model[MODEL_LEN + 1]; |
539 | unsigned long flags; | 540 | unsigned long flags; |
540 | int ret = 0; | 541 | int ret = 0; |
@@ -557,8 +558,8 @@ static ssize_t dev_show_rev(struct device *dev, | |||
557 | struct device_attribute *attr, | 558 | struct device_attribute *attr, |
558 | char *buf) | 559 | char *buf) |
559 | { | 560 | { |
560 | drive_info_struct *drv = to_drv(dev); | 561 | drive_info_struct *drv = dev_get_drvdata(dev); |
561 | struct ctlr_info *h = to_hba(drv->dev.parent); | 562 | struct ctlr_info *h = to_hba(drv->dev->parent); |
562 | char rev[REV_LEN + 1]; | 563 | char rev[REV_LEN + 1]; |
563 | unsigned long flags; | 564 | unsigned long flags; |
564 | int ret = 0; | 565 | int ret = 0; |
@@ -594,6 +595,7 @@ static struct attribute_group *cciss_host_attr_groups[] = { | |||
594 | static struct device_type cciss_host_type = { | 595 | static struct device_type cciss_host_type = { |
595 | .name = "cciss_host", | 596 | .name = "cciss_host", |
596 | .groups = cciss_host_attr_groups, | 597 | .groups = cciss_host_attr_groups, |
598 | .release = cciss_hba_release, | ||
597 | }; | 599 | }; |
598 | 600 | ||
599 | static struct attribute *cciss_dev_attrs[] = { | 601 | static struct attribute *cciss_dev_attrs[] = { |
@@ -616,12 +618,24 @@ static const struct attribute_group *cciss_dev_attr_groups[] = { | |||
616 | static struct device_type cciss_dev_type = { | 618 | static struct device_type cciss_dev_type = { |
617 | .name = "cciss_device", | 619 | .name = "cciss_device", |
618 | .groups = cciss_dev_attr_groups, | 620 | .groups = cciss_dev_attr_groups, |
621 | .release = cciss_device_release, | ||
619 | }; | 622 | }; |
620 | 623 | ||
621 | static struct bus_type cciss_bus_type = { | 624 | static struct bus_type cciss_bus_type = { |
622 | .name = "cciss", | 625 | .name = "cciss", |
623 | }; | 626 | }; |
624 | 627 | ||
628 | /* | ||
629 | * cciss_hba_release is called when the reference count | ||
630 | * of h->dev goes to zero. | ||
631 | */ | ||
632 | static void cciss_hba_release(struct device *dev) | ||
633 | { | ||
634 | /* | ||
635 | * nothing to do, but need this to avoid a warning | ||
636 | * about not having a release handler from lib/kref.c. | ||
637 | */ | ||
638 | } | ||
625 | 639 | ||
626 | /* | 640 | /* |
627 | * Initialize sysfs entry for each controller. This sets up and registers | 641 | * Initialize sysfs entry for each controller. This sets up and registers |
@@ -645,6 +659,15 @@ static int cciss_create_hba_sysfs_entry(struct ctlr_info *h) | |||
645 | static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | 659 | static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) |
646 | { | 660 | { |
647 | device_del(&h->dev); | 661 | device_del(&h->dev); |
662 | put_device(&h->dev); /* final put. */ | ||
663 | } | ||
664 | |||
665 | /* cciss_device_release is called when the reference count | ||
666 | * of h->drv[x].dev goes to zero. | ||
667 | */ | ||
668 | static void cciss_device_release(struct device *dev) | ||
669 | { | ||
670 | kfree(dev); | ||
648 | } | 671 | } |
649 | 672 | ||
650 | /* | 673 | /* |
@@ -653,24 +676,33 @@ static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | |||
653 | * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from | 676 | * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from |
654 | * /sys/block/cciss!c#d# to this entry. | 677 | * /sys/block/cciss!c#d# to this entry. |
655 | */ | 678 | */ |
656 | static int cciss_create_ld_sysfs_entry(struct ctlr_info *h, | 679 | static long cciss_create_ld_sysfs_entry(struct ctlr_info *h, |
657 | drive_info_struct *drv, | ||
658 | int drv_index) | 680 | int drv_index) |
659 | { | 681 | { |
660 | device_initialize(&drv->dev); | 682 | struct device *dev; |
661 | drv->dev.type = &cciss_dev_type; | 683 | |
662 | drv->dev.bus = &cciss_bus_type; | 684 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
663 | dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index); | 685 | if (!dev) |
664 | drv->dev.parent = &h->dev; | 686 | return -ENOMEM; |
665 | return device_add(&drv->dev); | 687 | device_initialize(dev); |
688 | dev->type = &cciss_dev_type; | ||
689 | dev->bus = &cciss_bus_type; | ||
690 | dev_set_name(dev, "c%dd%d", h->ctlr, drv_index); | ||
691 | dev->parent = &h->dev; | ||
692 | h->drv[drv_index].dev = dev; | ||
693 | dev_set_drvdata(dev, &h->drv[drv_index]); | ||
694 | return device_add(dev); | ||
666 | } | 695 | } |
667 | 696 | ||
668 | /* | 697 | /* |
669 | * Remove sysfs entries for a logical drive. | 698 | * Remove sysfs entries for a logical drive. |
670 | */ | 699 | */ |
671 | static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv) | 700 | static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index) |
672 | { | 701 | { |
673 | device_del(&drv->dev); | 702 | struct device *dev = h->drv[drv_index].dev; |
703 | device_del(dev); | ||
704 | put_device(dev); /* the "final" put. */ | ||
705 | h->drv[drv_index].dev = NULL; | ||
674 | } | 706 | } |
675 | 707 | ||
676 | /* | 708 | /* |
@@ -1651,7 +1683,10 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | |||
1651 | return; | 1683 | return; |
1652 | } | 1684 | } |
1653 | 1685 | ||
1654 | static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | 1686 | /* |
1687 | * cciss_add_disk sets up the block device queue for a logical drive | ||
1688 | */ | ||
1689 | static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | ||
1655 | int drv_index) | 1690 | int drv_index) |
1656 | { | 1691 | { |
1657 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | 1692 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); |
@@ -1659,8 +1694,12 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1659 | disk->major = h->major; | 1694 | disk->major = h->major; |
1660 | disk->first_minor = drv_index << NWD_SHIFT; | 1695 | disk->first_minor = drv_index << NWD_SHIFT; |
1661 | disk->fops = &cciss_fops; | 1696 | disk->fops = &cciss_fops; |
1697 | if (h->drv[drv_index].dev == NULL) { | ||
1698 | if (cciss_create_ld_sysfs_entry(h, drv_index)) | ||
1699 | goto cleanup_queue; | ||
1700 | } | ||
1662 | disk->private_data = &h->drv[drv_index]; | 1701 | disk->private_data = &h->drv[drv_index]; |
1663 | disk->driverfs_dev = &h->drv[drv_index].dev; | 1702 | disk->driverfs_dev = h->drv[drv_index].dev; |
1664 | 1703 | ||
1665 | /* Set up queue information */ | 1704 | /* Set up queue information */ |
1666 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); | 1705 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); |
@@ -1686,6 +1725,12 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1686 | wmb(); | 1725 | wmb(); |
1687 | h->drv[drv_index].queue = disk->queue; | 1726 | h->drv[drv_index].queue = disk->queue; |
1688 | add_disk(disk); | 1727 | add_disk(disk); |
1728 | return 0; | ||
1729 | |||
1730 | cleanup_queue: | ||
1731 | blk_cleanup_queue(disk->queue); | ||
1732 | disk->queue = NULL; | ||
1733 | return -1; | ||
1689 | } | 1734 | } |
1690 | 1735 | ||
1691 | /* This function will check the usage_count of the drive to be updated/added. | 1736 | /* This function will check the usage_count of the drive to be updated/added. |
@@ -1871,7 +1916,7 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node) | |||
1871 | } | 1916 | } |
1872 | } | 1917 | } |
1873 | h->drv[drv_index].LunID = lunid; | 1918 | h->drv[drv_index].LunID = lunid; |
1874 | if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index)) | 1919 | if (cciss_create_ld_sysfs_entry(h, drv_index)) |
1875 | goto err_free_disk; | 1920 | goto err_free_disk; |
1876 | 1921 | ||
1877 | /* Don't need to mark this busy because nobody */ | 1922 | /* Don't need to mark this busy because nobody */ |
@@ -2145,7 +2190,7 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2145 | * indicate that this element of the drive | 2190 | * indicate that this element of the drive |
2146 | * array is free. | 2191 | * array is free. |
2147 | */ | 2192 | */ |
2148 | cciss_destroy_ld_sysfs_entry(drv); | 2193 | cciss_destroy_ld_sysfs_entry(h, drv_index); |
2149 | 2194 | ||
2150 | if (clear_all) { | 2195 | if (clear_all) { |
2151 | /* check to see if it was the last disk */ | 2196 | /* check to see if it was the last disk */ |
@@ -4268,8 +4313,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
4268 | if (q) | 4313 | if (q) |
4269 | blk_cleanup_queue(q); | 4314 | blk_cleanup_queue(q); |
4270 | } | 4315 | } |
4271 | if (hba[i]->drv[j].raid_level != -1) | 4316 | if (hba[i]->drv[j].dev != NULL && |
4272 | cciss_destroy_ld_sysfs_entry(&hba[i]->drv[j]); | 4317 | (j == 0 || hba[i]->drv[j].raid_level != -1)) |
4318 | cciss_destroy_ld_sysfs_entry(hba[i], j); | ||
4273 | 4319 | ||
4274 | } | 4320 | } |
4275 | 4321 | ||
@@ -4345,7 +4391,7 @@ static int __init cciss_init(void) | |||
4345 | if (err) | 4391 | if (err) |
4346 | goto err_thread_stop; | 4392 | goto err_thread_stop; |
4347 | 4393 | ||
4348 | return 0; | 4394 | return err; |
4349 | 4395 | ||
4350 | err_thread_stop: | 4396 | err_thread_stop: |
4351 | kthread_stop(cciss_scan_thread); | 4397 | kthread_stop(cciss_scan_thread); |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 4fb3639b6cff..96793425688e 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -45,7 +45,7 @@ typedef struct _drive_info_struct | |||
45 | * to prevent it from being opened or it's | 45 | * to prevent it from being opened or it's |
46 | * queue from being started. | 46 | * queue from being started. |
47 | */ | 47 | */ |
48 | struct device dev; | 48 | struct device *dev; |
49 | __u8 serial_no[16]; /* from inquiry page 0x83, | 49 | __u8 serial_no[16]; /* from inquiry page 0x83, |
50 | * not necc. null terminated. | 50 | * not necc. null terminated. |
51 | */ | 51 | */ |