diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2009-09-17 14:48:31 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-10-01 15:15:45 -0400 |
commit | 9cef0d2f4f68a5a2c6ea0495f958a074d21fbd07 (patch) | |
tree | aee97fb9d8de37c0aee1fec563192e29a2425c70 /drivers/block | |
parent | e272afecaf18912e971374df4605496975942e5c (diff) |
cciss: Dynamically allocate the drive_info_struct for each logical drive.
cciss: Dynamically allocate the drive_info_struct for each logical drive.
This reduces the size of the per-hba ctlr_info structure from 106936
bytes to 8132 bytes. That's on 32-bit systems. On 64-bit systems, the
improvement is even bigger. Without this, the ctlr_info struct is so big
that the driver won't even load on a 64 bit system if CISS_MAX_LUN was
at it's current setting of 1024 logical drives.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/cciss.c | 293 | ||||
-rw-r--r-- | drivers/block/cciss.h | 5 |
2 files changed, 168 insertions, 130 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b808e9287b73..04036ef8ea5a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -201,6 +201,7 @@ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); | |||
201 | static void cciss_hba_release(struct device *dev); | 201 | static void cciss_hba_release(struct device *dev); |
202 | static void cciss_device_release(struct device *dev); | 202 | static void cciss_device_release(struct device *dev); |
203 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index); | 203 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index); |
204 | static void cciss_free_drive_info(ctlr_info_t *h, int drv_index); | ||
204 | 205 | ||
205 | #ifdef CONFIG_PROC_FS | 206 | #ifdef CONFIG_PROC_FS |
206 | static void cciss_procinit(int i); | 207 | static void cciss_procinit(int i); |
@@ -327,7 +328,7 @@ static int cciss_seq_show(struct seq_file *seq, void *v) | |||
327 | ctlr_info_t *h = seq->private; | 328 | ctlr_info_t *h = seq->private; |
328 | unsigned ctlr = h->ctlr; | 329 | unsigned ctlr = h->ctlr; |
329 | loff_t *pos = v; | 330 | loff_t *pos = v; |
330 | drive_info_struct *drv = &h->drv[*pos]; | 331 | drive_info_struct *drv = h->drv[*pos]; |
331 | 332 | ||
332 | if (*pos > h->highest_lun) | 333 | if (*pos > h->highest_lun) |
333 | return 0; | 334 | return 0; |
@@ -461,6 +462,7 @@ static void __devinit cciss_procinit(int i) | |||
461 | #define MAX_PRODUCT_NAME_LEN 19 | 462 | #define MAX_PRODUCT_NAME_LEN 19 |
462 | 463 | ||
463 | #define to_hba(n) container_of(n, struct ctlr_info, dev) | 464 | #define to_hba(n) container_of(n, struct ctlr_info, dev) |
465 | #define to_drv(n) container_of(n, drive_info_struct, dev) | ||
464 | 466 | ||
465 | static ssize_t host_store_rescan(struct device *dev, | 467 | static ssize_t host_store_rescan(struct device *dev, |
466 | struct device_attribute *attr, | 468 | struct device_attribute *attr, |
@@ -480,8 +482,8 @@ static ssize_t dev_show_unique_id(struct device *dev, | |||
480 | struct device_attribute *attr, | 482 | struct device_attribute *attr, |
481 | char *buf) | 483 | char *buf) |
482 | { | 484 | { |
483 | drive_info_struct *drv = dev_get_drvdata(dev); | 485 | drive_info_struct *drv = to_drv(dev); |
484 | struct ctlr_info *h = to_hba(drv->dev->parent); | 486 | struct ctlr_info *h = to_hba(drv->dev.parent); |
485 | __u8 sn[16]; | 487 | __u8 sn[16]; |
486 | unsigned long flags; | 488 | unsigned long flags; |
487 | int ret = 0; | 489 | int ret = 0; |
@@ -510,8 +512,8 @@ static ssize_t dev_show_vendor(struct device *dev, | |||
510 | struct device_attribute *attr, | 512 | struct device_attribute *attr, |
511 | char *buf) | 513 | char *buf) |
512 | { | 514 | { |
513 | drive_info_struct *drv = dev_get_drvdata(dev); | 515 | drive_info_struct *drv = to_drv(dev); |
514 | struct ctlr_info *h = to_hba(drv->dev->parent); | 516 | struct ctlr_info *h = to_hba(drv->dev.parent); |
515 | char vendor[VENDOR_LEN + 1]; | 517 | char vendor[VENDOR_LEN + 1]; |
516 | unsigned long flags; | 518 | unsigned long flags; |
517 | int ret = 0; | 519 | int ret = 0; |
@@ -534,8 +536,8 @@ static ssize_t dev_show_model(struct device *dev, | |||
534 | struct device_attribute *attr, | 536 | struct device_attribute *attr, |
535 | char *buf) | 537 | char *buf) |
536 | { | 538 | { |
537 | drive_info_struct *drv = dev_get_drvdata(dev); | 539 | drive_info_struct *drv = to_drv(dev); |
538 | struct ctlr_info *h = to_hba(drv->dev->parent); | 540 | struct ctlr_info *h = to_hba(drv->dev.parent); |
539 | char model[MODEL_LEN + 1]; | 541 | char model[MODEL_LEN + 1]; |
540 | unsigned long flags; | 542 | unsigned long flags; |
541 | int ret = 0; | 543 | int ret = 0; |
@@ -558,8 +560,8 @@ static ssize_t dev_show_rev(struct device *dev, | |||
558 | struct device_attribute *attr, | 560 | struct device_attribute *attr, |
559 | char *buf) | 561 | char *buf) |
560 | { | 562 | { |
561 | drive_info_struct *drv = dev_get_drvdata(dev); | 563 | drive_info_struct *drv = to_drv(dev); |
562 | struct ctlr_info *h = to_hba(drv->dev->parent); | 564 | struct ctlr_info *h = to_hba(drv->dev.parent); |
563 | char rev[REV_LEN + 1]; | 565 | char rev[REV_LEN + 1]; |
564 | unsigned long flags; | 566 | unsigned long flags; |
565 | int ret = 0; | 567 | int ret = 0; |
@@ -581,8 +583,8 @@ DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL); | |||
581 | static ssize_t cciss_show_lunid(struct device *dev, | 583 | static ssize_t cciss_show_lunid(struct device *dev, |
582 | struct device_attribute *attr, char *buf) | 584 | struct device_attribute *attr, char *buf) |
583 | { | 585 | { |
584 | drive_info_struct *drv = dev_get_drvdata(dev); | 586 | drive_info_struct *drv = to_drv(dev); |
585 | struct ctlr_info *h = to_hba(drv->dev->parent); | 587 | struct ctlr_info *h = to_hba(drv->dev.parent); |
586 | unsigned long flags; | 588 | unsigned long flags; |
587 | unsigned char lunid[8]; | 589 | unsigned char lunid[8]; |
588 | 590 | ||
@@ -606,8 +608,8 @@ DEVICE_ATTR(lunid, S_IRUGO, cciss_show_lunid, NULL); | |||
606 | static ssize_t cciss_show_raid_level(struct device *dev, | 608 | static ssize_t cciss_show_raid_level(struct device *dev, |
607 | struct device_attribute *attr, char *buf) | 609 | struct device_attribute *attr, char *buf) |
608 | { | 610 | { |
609 | drive_info_struct *drv = dev_get_drvdata(dev); | 611 | drive_info_struct *drv = to_drv(dev); |
610 | struct ctlr_info *h = to_hba(drv->dev->parent); | 612 | struct ctlr_info *h = to_hba(drv->dev.parent); |
611 | int raid; | 613 | int raid; |
612 | unsigned long flags; | 614 | unsigned long flags; |
613 | 615 | ||
@@ -629,8 +631,8 @@ DEVICE_ATTR(raid_level, S_IRUGO, cciss_show_raid_level, NULL); | |||
629 | static ssize_t cciss_show_usage_count(struct device *dev, | 631 | static ssize_t cciss_show_usage_count(struct device *dev, |
630 | struct device_attribute *attr, char *buf) | 632 | struct device_attribute *attr, char *buf) |
631 | { | 633 | { |
632 | drive_info_struct *drv = dev_get_drvdata(dev); | 634 | drive_info_struct *drv = to_drv(dev); |
633 | struct ctlr_info *h = to_hba(drv->dev->parent); | 635 | struct ctlr_info *h = to_hba(drv->dev.parent); |
634 | unsigned long flags; | 636 | unsigned long flags; |
635 | int count; | 637 | int count; |
636 | 638 | ||
@@ -733,11 +735,12 @@ static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | |||
733 | } | 735 | } |
734 | 736 | ||
735 | /* cciss_device_release is called when the reference count | 737 | /* cciss_device_release is called when the reference count |
736 | * of h->drv[x].dev goes to zero. | 738 | * of h->drv[x]dev goes to zero. |
737 | */ | 739 | */ |
738 | static void cciss_device_release(struct device *dev) | 740 | static void cciss_device_release(struct device *dev) |
739 | { | 741 | { |
740 | kfree(dev); | 742 | drive_info_struct *drv = to_drv(dev); |
743 | kfree(drv); | ||
741 | } | 744 | } |
742 | 745 | ||
743 | /* | 746 | /* |
@@ -751,20 +754,16 @@ static long cciss_create_ld_sysfs_entry(struct ctlr_info *h, | |||
751 | { | 754 | { |
752 | struct device *dev; | 755 | struct device *dev; |
753 | 756 | ||
754 | /* Special case for c*d0, we only create it once. */ | 757 | if (h->drv[drv_index]->device_initialized) |
755 | if (drv_index == 0 && h->drv[drv_index].dev != NULL) | ||
756 | return 0; | 758 | return 0; |
757 | 759 | ||
758 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 760 | dev = &h->drv[drv_index]->dev; |
759 | if (!dev) | ||
760 | return -ENOMEM; | ||
761 | device_initialize(dev); | 761 | device_initialize(dev); |
762 | dev->type = &cciss_dev_type; | 762 | dev->type = &cciss_dev_type; |
763 | dev->bus = &cciss_bus_type; | 763 | dev->bus = &cciss_bus_type; |
764 | dev_set_name(dev, "c%dd%d", h->ctlr, drv_index); | 764 | dev_set_name(dev, "c%dd%d", h->ctlr, drv_index); |
765 | dev->parent = &h->dev; | 765 | dev->parent = &h->dev; |
766 | h->drv[drv_index].dev = dev; | 766 | h->drv[drv_index]->device_initialized = 1; |
767 | dev_set_drvdata(dev, &h->drv[drv_index]); | ||
768 | return device_add(dev); | 767 | return device_add(dev); |
769 | } | 768 | } |
770 | 769 | ||
@@ -774,7 +773,7 @@ static long cciss_create_ld_sysfs_entry(struct ctlr_info *h, | |||
774 | static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, | 773 | static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, |
775 | int ctlr_exiting) | 774 | int ctlr_exiting) |
776 | { | 775 | { |
777 | struct device *dev = h->drv[drv_index].dev; | 776 | struct device *dev = &h->drv[drv_index]->dev; |
778 | 777 | ||
779 | /* special case for c*d0, we only destroy it on controller exit */ | 778 | /* special case for c*d0, we only destroy it on controller exit */ |
780 | if (drv_index == 0 && !ctlr_exiting) | 779 | if (drv_index == 0 && !ctlr_exiting) |
@@ -782,7 +781,7 @@ static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, | |||
782 | 781 | ||
783 | device_del(dev); | 782 | device_del(dev); |
784 | put_device(dev); /* the "final" put. */ | 783 | put_device(dev); /* the "final" put. */ |
785 | h->drv[drv_index].dev = NULL; | 784 | h->drv[drv_index] = NULL; |
786 | } | 785 | } |
787 | 786 | ||
788 | /* | 787 | /* |
@@ -1625,7 +1624,10 @@ static void cciss_check_queues(ctlr_info_t *h) | |||
1625 | /* make sure the disk has been added and the drive is real | 1624 | /* make sure the disk has been added and the drive is real |
1626 | * because this can be called from the middle of init_one. | 1625 | * because this can be called from the middle of init_one. |
1627 | */ | 1626 | */ |
1628 | if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads)) | 1627 | if (!h->drv[curr_queue]) |
1628 | continue; | ||
1629 | if (!(h->drv[curr_queue]->queue) || | ||
1630 | !(h->drv[curr_queue]->heads)) | ||
1629 | continue; | 1631 | continue; |
1630 | blk_start_queue(h->gendisk[curr_queue]->queue); | 1632 | blk_start_queue(h->gendisk[curr_queue]->queue); |
1631 | 1633 | ||
@@ -1685,8 +1687,8 @@ static void cciss_softirq_done(struct request *rq) | |||
1685 | static inline void log_unit_to_scsi3addr(ctlr_info_t *h, | 1687 | static inline void log_unit_to_scsi3addr(ctlr_info_t *h, |
1686 | unsigned char scsi3addr[], uint32_t log_unit) | 1688 | unsigned char scsi3addr[], uint32_t log_unit) |
1687 | { | 1689 | { |
1688 | memcpy(scsi3addr, h->drv[log_unit].LunID, | 1690 | memcpy(scsi3addr, h->drv[log_unit]->LunID, |
1689 | sizeof(h->drv[log_unit].LunID)); | 1691 | sizeof(h->drv[log_unit]->LunID)); |
1690 | } | 1692 | } |
1691 | 1693 | ||
1692 | /* This function gets the SCSI vendor, model, and revision of a logical drive | 1694 | /* This function gets the SCSI vendor, model, and revision of a logical drive |
@@ -1776,12 +1778,10 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1776 | disk->major = h->major; | 1778 | disk->major = h->major; |
1777 | disk->first_minor = drv_index << NWD_SHIFT; | 1779 | disk->first_minor = drv_index << NWD_SHIFT; |
1778 | disk->fops = &cciss_fops; | 1780 | disk->fops = &cciss_fops; |
1779 | if (h->drv[drv_index].dev == NULL) { | 1781 | if (cciss_create_ld_sysfs_entry(h, drv_index)) |
1780 | if (cciss_create_ld_sysfs_entry(h, drv_index)) | 1782 | goto cleanup_queue; |
1781 | goto cleanup_queue; | 1783 | disk->private_data = h->drv[drv_index]; |
1782 | } | 1784 | disk->driverfs_dev = &h->drv[drv_index]->dev; |
1783 | disk->private_data = &h->drv[drv_index]; | ||
1784 | disk->driverfs_dev = h->drv[drv_index].dev; | ||
1785 | 1785 | ||
1786 | /* Set up queue information */ | 1786 | /* Set up queue information */ |
1787 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); | 1787 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); |
@@ -1799,13 +1799,13 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1799 | disk->queue->queuedata = h; | 1799 | disk->queue->queuedata = h; |
1800 | 1800 | ||
1801 | blk_queue_logical_block_size(disk->queue, | 1801 | blk_queue_logical_block_size(disk->queue, |
1802 | h->drv[drv_index].block_size); | 1802 | h->drv[drv_index]->block_size); |
1803 | 1803 | ||
1804 | /* Make sure all queue data is written out before */ | 1804 | /* Make sure all queue data is written out before */ |
1805 | /* setting h->drv[drv_index].queue, as setting this */ | 1805 | /* setting h->drv[drv_index]->queue, as setting this */ |
1806 | /* allows the interrupt handler to start the queue */ | 1806 | /* allows the interrupt handler to start the queue */ |
1807 | wmb(); | 1807 | wmb(); |
1808 | h->drv[drv_index].queue = disk->queue; | 1808 | h->drv[drv_index]->queue = disk->queue; |
1809 | add_disk(disk); | 1809 | add_disk(disk); |
1810 | return 0; | 1810 | return 0; |
1811 | 1811 | ||
@@ -1840,7 +1840,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, | |||
1840 | 1840 | ||
1841 | /* Get information about the disk and modify the driver structure */ | 1841 | /* Get information about the disk and modify the driver structure */ |
1842 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 1842 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); |
1843 | drvinfo = kmalloc(sizeof(*drvinfo), GFP_KERNEL); | 1843 | drvinfo = kzalloc(sizeof(*drvinfo), GFP_KERNEL); |
1844 | if (inq_buff == NULL || drvinfo == NULL) | 1844 | if (inq_buff == NULL || drvinfo == NULL) |
1845 | goto mem_msg; | 1845 | goto mem_msg; |
1846 | 1846 | ||
@@ -1876,16 +1876,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, | |||
1876 | drvinfo->model, drvinfo->rev); | 1876 | drvinfo->model, drvinfo->rev); |
1877 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, | 1877 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, |
1878 | sizeof(drvinfo->serial_no)); | 1878 | sizeof(drvinfo->serial_no)); |
1879 | /* Save the lunid in case we deregister the disk, below. */ | ||
1880 | memcpy(drvinfo->LunID, h->drv[drv_index]->LunID, | ||
1881 | sizeof(drvinfo->LunID)); | ||
1879 | 1882 | ||
1880 | /* Is it the same disk we already know, and nothing's changed? */ | 1883 | /* Is it the same disk we already know, and nothing's changed? */ |
1881 | if (h->drv[drv_index].raid_level != -1 && | 1884 | if (h->drv[drv_index]->raid_level != -1 && |
1882 | ((memcmp(drvinfo->serial_no, | 1885 | ((memcmp(drvinfo->serial_no, |
1883 | h->drv[drv_index].serial_no, 16) == 0) && | 1886 | h->drv[drv_index]->serial_no, 16) == 0) && |
1884 | drvinfo->block_size == h->drv[drv_index].block_size && | 1887 | drvinfo->block_size == h->drv[drv_index]->block_size && |
1885 | drvinfo->nr_blocks == h->drv[drv_index].nr_blocks && | 1888 | drvinfo->nr_blocks == h->drv[drv_index]->nr_blocks && |
1886 | drvinfo->heads == h->drv[drv_index].heads && | 1889 | drvinfo->heads == h->drv[drv_index]->heads && |
1887 | drvinfo->sectors == h->drv[drv_index].sectors && | 1890 | drvinfo->sectors == h->drv[drv_index]->sectors && |
1888 | drvinfo->cylinders == h->drv[drv_index].cylinders)) | 1891 | drvinfo->cylinders == h->drv[drv_index]->cylinders)) |
1889 | /* The disk is unchanged, nothing to update */ | 1892 | /* The disk is unchanged, nothing to update */ |
1890 | goto freeret; | 1893 | goto freeret; |
1891 | 1894 | ||
@@ -1895,18 +1898,17 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, | |||
1895 | * If the disk already exists then deregister it before proceeding | 1898 | * If the disk already exists then deregister it before proceeding |
1896 | * (unless it's the first disk (for the controller node). | 1899 | * (unless it's the first disk (for the controller node). |
1897 | */ | 1900 | */ |
1898 | if (h->drv[drv_index].raid_level != -1 && drv_index != 0) { | 1901 | if (h->drv[drv_index]->raid_level != -1 && drv_index != 0) { |
1899 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); | 1902 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); |
1900 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1903 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1901 | h->drv[drv_index].busy_configuring = 1; | 1904 | h->drv[drv_index]->busy_configuring = 1; |
1902 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1905 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
1903 | 1906 | ||
1904 | /* deregister_disk sets h->drv[drv_index].queue = NULL | 1907 | /* deregister_disk sets h->drv[drv_index]->queue = NULL |
1905 | * which keeps the interrupt handler from starting | 1908 | * which keeps the interrupt handler from starting |
1906 | * the queue. | 1909 | * the queue. |
1907 | */ | 1910 | */ |
1908 | ret = deregister_disk(h, drv_index, 0, via_ioctl); | 1911 | ret = deregister_disk(h, drv_index, 0, via_ioctl); |
1909 | h->drv[drv_index].busy_configuring = 0; | ||
1910 | } | 1912 | } |
1911 | 1913 | ||
1912 | /* If the disk is in use return */ | 1914 | /* If the disk is in use return */ |
@@ -1914,22 +1916,31 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, | |||
1914 | goto freeret; | 1916 | goto freeret; |
1915 | 1917 | ||
1916 | /* Save the new information from cciss_geometry_inquiry | 1918 | /* Save the new information from cciss_geometry_inquiry |
1917 | * and serial number inquiry. | 1919 | * and serial number inquiry. If the disk was deregistered |
1920 | * above, then h->drv[drv_index] will be NULL. | ||
1918 | */ | 1921 | */ |
1919 | h->drv[drv_index].block_size = drvinfo->block_size; | 1922 | if (h->drv[drv_index] == NULL) { |
1920 | h->drv[drv_index].nr_blocks = drvinfo->nr_blocks; | 1923 | drvinfo->device_initialized = 0; |
1921 | h->drv[drv_index].heads = drvinfo->heads; | 1924 | h->drv[drv_index] = drvinfo; |
1922 | h->drv[drv_index].sectors = drvinfo->sectors; | 1925 | drvinfo = NULL; /* so it won't be freed below. */ |
1923 | h->drv[drv_index].cylinders = drvinfo->cylinders; | 1926 | } else { |
1924 | h->drv[drv_index].raid_level = drvinfo->raid_level; | 1927 | /* special case for cxd0 */ |
1925 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); | 1928 | h->drv[drv_index]->block_size = drvinfo->block_size; |
1926 | memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1); | 1929 | h->drv[drv_index]->nr_blocks = drvinfo->nr_blocks; |
1927 | memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1); | 1930 | h->drv[drv_index]->heads = drvinfo->heads; |
1928 | memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1); | 1931 | h->drv[drv_index]->sectors = drvinfo->sectors; |
1932 | h->drv[drv_index]->cylinders = drvinfo->cylinders; | ||
1933 | h->drv[drv_index]->raid_level = drvinfo->raid_level; | ||
1934 | memcpy(h->drv[drv_index]->serial_no, drvinfo->serial_no, 16); | ||
1935 | memcpy(h->drv[drv_index]->vendor, drvinfo->vendor, | ||
1936 | VENDOR_LEN + 1); | ||
1937 | memcpy(h->drv[drv_index]->model, drvinfo->model, MODEL_LEN + 1); | ||
1938 | memcpy(h->drv[drv_index]->rev, drvinfo->rev, REV_LEN + 1); | ||
1939 | } | ||
1929 | 1940 | ||
1930 | ++h->num_luns; | 1941 | ++h->num_luns; |
1931 | disk = h->gendisk[drv_index]; | 1942 | disk = h->gendisk[drv_index]; |
1932 | set_capacity(disk, h->drv[drv_index].nr_blocks); | 1943 | set_capacity(disk, h->drv[drv_index]->nr_blocks); |
1933 | 1944 | ||
1934 | /* If it's not disk 0 (drv_index != 0) | 1945 | /* If it's not disk 0 (drv_index != 0) |
1935 | * or if it was disk 0, but there was previously | 1946 | * or if it was disk 0, but there was previously |
@@ -1940,6 +1951,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, | |||
1940 | if (drv_index || first_time) { | 1951 | if (drv_index || first_time) { |
1941 | if (cciss_add_disk(h, disk, drv_index) != 0) { | 1952 | if (cciss_add_disk(h, disk, drv_index) != 0) { |
1942 | cciss_free_gendisk(h, drv_index); | 1953 | cciss_free_gendisk(h, drv_index); |
1954 | cciss_free_drive_info(h, drv_index); | ||
1943 | printk(KERN_WARNING "cciss:%d could not update " | 1955 | printk(KERN_WARNING "cciss:%d could not update " |
1944 | "disk %d\n", h->ctlr, drv_index); | 1956 | "disk %d\n", h->ctlr, drv_index); |
1945 | --h->num_luns; | 1957 | --h->num_luns; |
@@ -1956,28 +1968,64 @@ mem_msg: | |||
1956 | } | 1968 | } |
1957 | 1969 | ||
1958 | /* This function will find the first index of the controllers drive array | 1970 | /* This function will find the first index of the controllers drive array |
1959 | * that has a -1 for the raid_level and will return that index. This is | 1971 | * that has a null drv pointer and allocate the drive info struct and |
1960 | * where new drives will be added. If the index to be returned is greater | 1972 | * will return that index This is where new drives will be added. |
1961 | * than the highest_lun index for the controller then highest_lun is set | 1973 | * If the index to be returned is greater than the highest_lun index for |
1962 | * to this new index. If there are no available indexes then -1 is returned. | 1974 | * the controller then highest_lun is set * to this new index. |
1963 | * "controller_node" is used to know if this is a real logical drive, or just | 1975 | * If there are no available indexes or if tha allocation fails, then -1 |
1964 | * the controller node, which determines if this counts towards highest_lun. | 1976 | * is returned. * "controller_node" is used to know if this is a real |
1977 | * logical drive, or just the controller node, which determines if this | ||
1978 | * counts towards highest_lun. | ||
1965 | */ | 1979 | */ |
1966 | static int cciss_find_free_drive_index(int ctlr, int controller_node) | 1980 | static int cciss_alloc_drive_info(ctlr_info_t *h, int controller_node) |
1967 | { | 1981 | { |
1968 | int i; | 1982 | int i; |
1983 | drive_info_struct *drv; | ||
1969 | 1984 | ||
1985 | /* Search for an empty slot for our drive info */ | ||
1970 | for (i = 0; i < CISS_MAX_LUN; i++) { | 1986 | for (i = 0; i < CISS_MAX_LUN; i++) { |
1971 | if (hba[ctlr]->drv[i].raid_level == -1) { | 1987 | |
1972 | if (i > hba[ctlr]->highest_lun) | 1988 | /* if not cxd0 case, and it's occupied, skip it. */ |
1973 | if (!controller_node) | 1989 | if (h->drv[i] && i != 0) |
1974 | hba[ctlr]->highest_lun = i; | 1990 | continue; |
1991 | /* | ||
1992 | * If it's cxd0 case, and drv is alloc'ed already, and a | ||
1993 | * disk is configured there, skip it. | ||
1994 | */ | ||
1995 | if (i == 0 && h->drv[i] && h->drv[i]->raid_level != -1) | ||
1996 | continue; | ||
1997 | |||
1998 | /* | ||
1999 | * We've found an empty slot. Update highest_lun | ||
2000 | * provided this isn't just the fake cxd0 controller node. | ||
2001 | */ | ||
2002 | if (i > h->highest_lun && !controller_node) | ||
2003 | h->highest_lun = i; | ||
2004 | |||
2005 | /* If adding a real disk at cxd0, and it's already alloc'ed */ | ||
2006 | if (i == 0 && h->drv[i] != NULL) | ||
1975 | return i; | 2007 | return i; |
1976 | } | 2008 | |
2009 | /* | ||
2010 | * Found an empty slot, not already alloc'ed. Allocate it. | ||
2011 | * Mark it with raid_level == -1, so we know it's new later on. | ||
2012 | */ | ||
2013 | drv = kzalloc(sizeof(*drv), GFP_KERNEL); | ||
2014 | if (!drv) | ||
2015 | return -1; | ||
2016 | drv->raid_level = -1; /* so we know it's new */ | ||
2017 | h->drv[i] = drv; | ||
2018 | return i; | ||
1977 | } | 2019 | } |
1978 | return -1; | 2020 | return -1; |
1979 | } | 2021 | } |
1980 | 2022 | ||
2023 | static void cciss_free_drive_info(ctlr_info_t *h, int drv_index) | ||
2024 | { | ||
2025 | kfree(h->drv[drv_index]); | ||
2026 | h->drv[drv_index] = NULL; | ||
2027 | } | ||
2028 | |||
1981 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index) | 2029 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index) |
1982 | { | 2030 | { |
1983 | put_disk(h->gendisk[drv_index]); | 2031 | put_disk(h->gendisk[drv_index]); |
@@ -1998,7 +2046,7 @@ static int cciss_add_gendisk(ctlr_info_t *h, unsigned char lunid[], | |||
1998 | { | 2046 | { |
1999 | int drv_index; | 2047 | int drv_index; |
2000 | 2048 | ||
2001 | drv_index = cciss_find_free_drive_index(h->ctlr, controller_node); | 2049 | drv_index = cciss_alloc_drive_info(h, controller_node); |
2002 | if (drv_index == -1) | 2050 | if (drv_index == -1) |
2003 | return -1; | 2051 | return -1; |
2004 | 2052 | ||
@@ -2010,24 +2058,24 @@ static int cciss_add_gendisk(ctlr_info_t *h, unsigned char lunid[], | |||
2010 | printk(KERN_ERR "cciss%d: could not " | 2058 | printk(KERN_ERR "cciss%d: could not " |
2011 | "allocate a new disk %d\n", | 2059 | "allocate a new disk %d\n", |
2012 | h->ctlr, drv_index); | 2060 | h->ctlr, drv_index); |
2013 | return -1; | 2061 | goto err_free_drive_info; |
2014 | } | 2062 | } |
2015 | } | 2063 | } |
2016 | memcpy(h->drv[drv_index].LunID, lunid, | 2064 | memcpy(h->drv[drv_index]->LunID, lunid, |
2017 | sizeof(h->drv[drv_index].LunID)); | 2065 | sizeof(h->drv[drv_index]->LunID)); |
2018 | if (h->drv[drv_index].dev == NULL) { | 2066 | if (cciss_create_ld_sysfs_entry(h, drv_index)) |
2019 | if (cciss_create_ld_sysfs_entry(h, drv_index)) | 2067 | goto err_free_disk; |
2020 | goto err_free_disk; | ||
2021 | } | ||
2022 | /* Don't need to mark this busy because nobody */ | 2068 | /* Don't need to mark this busy because nobody */ |
2023 | /* else knows about this disk yet to contend */ | 2069 | /* else knows about this disk yet to contend */ |
2024 | /* for access to it. */ | 2070 | /* for access to it. */ |
2025 | h->drv[drv_index].busy_configuring = 0; | 2071 | h->drv[drv_index]->busy_configuring = 0; |
2026 | wmb(); | 2072 | wmb(); |
2027 | return drv_index; | 2073 | return drv_index; |
2028 | 2074 | ||
2029 | err_free_disk: | 2075 | err_free_disk: |
2030 | cciss_free_gendisk(h, drv_index); | 2076 | cciss_free_gendisk(h, drv_index); |
2077 | err_free_drive_info: | ||
2078 | cciss_free_drive_info(h, drv_index); | ||
2031 | return -1; | 2079 | return -1; |
2032 | } | 2080 | } |
2033 | 2081 | ||
@@ -2047,17 +2095,18 @@ static void cciss_add_controller_node(ctlr_info_t *h) | |||
2047 | drv_index = cciss_add_gendisk(h, CTLR_LUNID, 1); | 2095 | drv_index = cciss_add_gendisk(h, CTLR_LUNID, 1); |
2048 | if (drv_index == -1) | 2096 | if (drv_index == -1) |
2049 | goto error; | 2097 | goto error; |
2050 | h->drv[drv_index].block_size = 512; | 2098 | h->drv[drv_index]->block_size = 512; |
2051 | h->drv[drv_index].nr_blocks = 0; | 2099 | h->drv[drv_index]->nr_blocks = 0; |
2052 | h->drv[drv_index].heads = 0; | 2100 | h->drv[drv_index]->heads = 0; |
2053 | h->drv[drv_index].sectors = 0; | 2101 | h->drv[drv_index]->sectors = 0; |
2054 | h->drv[drv_index].cylinders = 0; | 2102 | h->drv[drv_index]->cylinders = 0; |
2055 | h->drv[drv_index].raid_level = -1; | 2103 | h->drv[drv_index]->raid_level = -1; |
2056 | memset(h->drv[drv_index].serial_no, 0, 16); | 2104 | memset(h->drv[drv_index]->serial_no, 0, 16); |
2057 | disk = h->gendisk[drv_index]; | 2105 | disk = h->gendisk[drv_index]; |
2058 | if (cciss_add_disk(h, disk, drv_index) == 0) | 2106 | if (cciss_add_disk(h, disk, drv_index) == 0) |
2059 | return; | 2107 | return; |
2060 | cciss_free_gendisk(h, drv_index); | 2108 | cciss_free_gendisk(h, drv_index); |
2109 | cciss_free_drive_info(h, drv_index); | ||
2061 | error: | 2110 | error: |
2062 | printk(KERN_WARNING "cciss%d: could not " | 2111 | printk(KERN_WARNING "cciss%d: could not " |
2063 | "add disk 0.\n", h->ctlr); | 2112 | "add disk 0.\n", h->ctlr); |
@@ -2136,12 +2185,12 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time, | |||
2136 | drv_found = 0; | 2185 | drv_found = 0; |
2137 | 2186 | ||
2138 | /* skip holes in the array from already deleted drives */ | 2187 | /* skip holes in the array from already deleted drives */ |
2139 | if (h->drv[i].raid_level == -1) | 2188 | if (h->drv[i] == NULL) |
2140 | continue; | 2189 | continue; |
2141 | 2190 | ||
2142 | for (j = 0; j < num_luns; j++) { | 2191 | for (j = 0; j < num_luns; j++) { |
2143 | memcpy(lunid, &ld_buff->LUN[j][0], sizeof(lunid)); | 2192 | memcpy(lunid, &ld_buff->LUN[j][0], sizeof(lunid)); |
2144 | if (memcmp(h->drv[i].LunID, lunid, | 2193 | if (memcmp(h->drv[i]->LunID, lunid, |
2145 | sizeof(lunid)) == 0) { | 2194 | sizeof(lunid)) == 0) { |
2146 | drv_found = 1; | 2195 | drv_found = 1; |
2147 | break; | 2196 | break; |
@@ -2150,10 +2199,11 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time, | |||
2150 | if (!drv_found) { | 2199 | if (!drv_found) { |
2151 | /* Deregister it from the OS, it's gone. */ | 2200 | /* Deregister it from the OS, it's gone. */ |
2152 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2201 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
2153 | h->drv[i].busy_configuring = 1; | 2202 | h->drv[i]->busy_configuring = 1; |
2154 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 2203 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
2155 | return_code = deregister_disk(h, i, 1, via_ioctl); | 2204 | return_code = deregister_disk(h, i, 1, via_ioctl); |
2156 | h->drv[i].busy_configuring = 0; | 2205 | if (h->drv[i] != NULL) |
2206 | h->drv[i]->busy_configuring = 0; | ||
2157 | } | 2207 | } |
2158 | } | 2208 | } |
2159 | 2209 | ||
@@ -2174,9 +2224,9 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time, | |||
2174 | * the first free index and add it. | 2224 | * the first free index and add it. |
2175 | */ | 2225 | */ |
2176 | for (j = 0; j <= h->highest_lun; j++) { | 2226 | for (j = 0; j <= h->highest_lun; j++) { |
2177 | if (h->drv[j].raid_level != -1 && | 2227 | if (h->drv[j] != NULL && |
2178 | memcmp(h->drv[j].LunID, lunid, | 2228 | memcmp(h->drv[j]->LunID, lunid, |
2179 | sizeof(h->drv[j].LunID)) == 0) { | 2229 | sizeof(h->drv[j]->LunID)) == 0) { |
2180 | drv_index = j; | 2230 | drv_index = j; |
2181 | drv_found = 1; | 2231 | drv_found = 1; |
2182 | break; | 2232 | break; |
@@ -2253,11 +2303,12 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2253 | int i; | 2303 | int i; |
2254 | struct gendisk *disk; | 2304 | struct gendisk *disk; |
2255 | drive_info_struct *drv; | 2305 | drive_info_struct *drv; |
2306 | int recalculate_highest_lun; | ||
2256 | 2307 | ||
2257 | if (!capable(CAP_SYS_RAWIO)) | 2308 | if (!capable(CAP_SYS_RAWIO)) |
2258 | return -EPERM; | 2309 | return -EPERM; |
2259 | 2310 | ||
2260 | drv = &h->drv[drv_index]; | 2311 | drv = h->drv[drv_index]; |
2261 | disk = h->gendisk[drv_index]; | 2312 | disk = h->gendisk[drv_index]; |
2262 | 2313 | ||
2263 | /* make sure logical volume is NOT is use */ | 2314 | /* make sure logical volume is NOT is use */ |
@@ -2267,6 +2318,8 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2267 | } else if (drv->usage_count > 0) | 2318 | } else if (drv->usage_count > 0) |
2268 | return -EBUSY; | 2319 | return -EBUSY; |
2269 | 2320 | ||
2321 | recalculate_highest_lun = (drv == h->drv[h->highest_lun]); | ||
2322 | |||
2270 | /* invalidate the devices and deregister the disk. If it is disk | 2323 | /* invalidate the devices and deregister the disk. If it is disk |
2271 | * zero do not deregister it but just zero out it's values. This | 2324 | * zero do not deregister it but just zero out it's values. This |
2272 | * allows us to delete disk zero but keep the controller registered. | 2325 | * allows us to delete disk zero but keep the controller registered. |
@@ -2277,14 +2330,8 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2277 | cciss_destroy_ld_sysfs_entry(h, drv_index, 0); | 2330 | cciss_destroy_ld_sysfs_entry(h, drv_index, 0); |
2278 | del_gendisk(disk); | 2331 | del_gendisk(disk); |
2279 | } | 2332 | } |
2280 | if (q) { | 2333 | if (q) |
2281 | blk_cleanup_queue(q); | 2334 | blk_cleanup_queue(q); |
2282 | /* Set drv->queue to NULL so that we do not try | ||
2283 | * to call blk_start_queue on this queue in the | ||
2284 | * interrupt handler | ||
2285 | */ | ||
2286 | drv->queue = NULL; | ||
2287 | } | ||
2288 | /* If clear_all is set then we are deleting the logical | 2335 | /* If clear_all is set then we are deleting the logical |
2289 | * drive, not just refreshing its info. For drives | 2336 | * drive, not just refreshing its info. For drives |
2290 | * other than disk 0 we will call put_disk. We do not | 2337 | * other than disk 0 we will call put_disk. We do not |
@@ -2307,24 +2354,20 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2307 | } | 2354 | } |
2308 | } else { | 2355 | } else { |
2309 | set_capacity(disk, 0); | 2356 | set_capacity(disk, 0); |
2357 | cciss_clear_drive_info(drv); | ||
2310 | } | 2358 | } |
2311 | 2359 | ||
2312 | --h->num_luns; | 2360 | --h->num_luns; |
2313 | cciss_clear_drive_info(drv); | 2361 | |
2314 | 2362 | /* if it was the last disk, find the new hightest lun */ | |
2315 | if (clear_all) { | 2363 | if (clear_all && recalculate_highest_lun) { |
2316 | /* check to see if it was the last disk */ | 2364 | int i, newhighest = -1; |
2317 | if (drv == h->drv + h->highest_lun) { | 2365 | for (i = 0; i <= h->highest_lun; i++) { |
2318 | /* if so, find the new hightest lun */ | 2366 | /* if the disk has size > 0, it is available */ |
2319 | int i, newhighest = -1; | 2367 | if (h->drv[i] && h->drv[i]->heads) |
2320 | for (i = 0; i <= h->highest_lun; i++) { | 2368 | newhighest = i; |
2321 | /* if the disk has size > 0, it is available */ | ||
2322 | if (h->drv[i].heads) | ||
2323 | newhighest = i; | ||
2324 | } | ||
2325 | h->highest_lun = newhighest; | ||
2326 | } | 2369 | } |
2327 | memset(drv->LunID, 0, sizeof(drv->LunID)); | 2370 | h->highest_lun = newhighest; |
2328 | } | 2371 | } |
2329 | return 0; | 2372 | return 0; |
2330 | } | 2373 | } |
@@ -2755,7 +2798,7 @@ static int cciss_revalidate(struct gendisk *disk) | |||
2755 | InquiryData_struct *inq_buff = NULL; | 2798 | InquiryData_struct *inq_buff = NULL; |
2756 | 2799 | ||
2757 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { | 2800 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { |
2758 | if (memcmp(h->drv[logvol].LunID, drv->LunID, | 2801 | if (memcmp(h->drv[logvol]->LunID, drv->LunID, |
2759 | sizeof(drv->LunID)) == 0) { | 2802 | sizeof(drv->LunID)) == 0) { |
2760 | FOUND = 1; | 2803 | FOUND = 1; |
2761 | break; | 2804 | break; |
@@ -4293,8 +4336,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
4293 | hba[i]->num_luns = 0; | 4336 | hba[i]->num_luns = 0; |
4294 | hba[i]->highest_lun = -1; | 4337 | hba[i]->highest_lun = -1; |
4295 | for (j = 0; j < CISS_MAX_LUN; j++) { | 4338 | for (j = 0; j < CISS_MAX_LUN; j++) { |
4296 | hba[i]->drv[j].raid_level = -1; | 4339 | hba[i]->drv[j] = NULL; |
4297 | hba[i]->drv[j].queue = NULL; | ||
4298 | hba[i]->gendisk[j] = NULL; | 4340 | hba[i]->gendisk[j] = NULL; |
4299 | } | 4341 | } |
4300 | 4342 | ||
@@ -4349,12 +4391,7 @@ clean1: | |||
4349 | cciss_destroy_hba_sysfs_entry(hba[i]); | 4391 | cciss_destroy_hba_sysfs_entry(hba[i]); |
4350 | clean0: | 4392 | clean0: |
4351 | hba[i]->busy_initializing = 0; | 4393 | hba[i]->busy_initializing = 0; |
4352 | /* cleanup any queues that may have been initialized */ | 4394 | |
4353 | for (j=0; j <= hba[i]->highest_lun; j++){ | ||
4354 | drive_info_struct *drv = &(hba[i]->drv[j]); | ||
4355 | if (drv->queue) | ||
4356 | blk_cleanup_queue(drv->queue); | ||
4357 | } | ||
4358 | /* | 4395 | /* |
4359 | * Deliberately omit pci_disable_device(): it does something nasty to | 4396 | * Deliberately omit pci_disable_device(): it does something nasty to |
4360 | * Smart Array controllers that pci_enable_device does not undo | 4397 | * Smart Array controllers that pci_enable_device does not undo |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 5188f713d1b0..31524cf42c77 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -45,13 +45,14 @@ 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 | */ |
52 | char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */ | 52 | char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */ |
53 | char model[MODEL_LEN + 1]; /* SCSI model string */ | 53 | char model[MODEL_LEN + 1]; /* SCSI model string */ |
54 | char rev[REV_LEN + 1]; /* SCSI revision string */ | 54 | char rev[REV_LEN + 1]; /* SCSI revision string */ |
55 | char device_initialized; /* indicates whether dev is initialized */ | ||
55 | } drive_info_struct; | 56 | } drive_info_struct; |
56 | 57 | ||
57 | struct ctlr_info | 58 | struct ctlr_info |
@@ -87,7 +88,7 @@ struct ctlr_info | |||
87 | BYTE cciss_read_capacity; | 88 | BYTE cciss_read_capacity; |
88 | 89 | ||
89 | // information about each logical volume | 90 | // information about each logical volume |
90 | drive_info_struct drv[CISS_MAX_LUN]; | 91 | drive_info_struct *drv[CISS_MAX_LUN]; |
91 | 92 | ||
92 | struct access_method access; | 93 | struct access_method access; |
93 | 94 | ||