aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorScott Teel <scott.teel@hp.com>2012-01-19 15:01:30 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 09:08:57 -0500
commitbd9244f7b9508a5945dcbd015db334110a9cdecf (patch)
tree595b66138bf997b5d7d9d8326ffdda212ade0b9b /drivers/scsi/hpsa.c
parent4f4eb9f1d8f8eb91d0dd486deafd4800b425f289 (diff)
[SCSI] hpsa: update device attributes when they change
Certain types of changes to devices should not be interpreted as a device change that would cause the device to be removed and re-added. These include RAID level and Firmware revision changes. However, these attribute changes DO need to be reflected in the controller info structure's dev structure list, so that sysfs and /proc info files for the devices will reflect the new values. Signed-off-by: Scott Teel <scott.stacy.teel@hp.com> Acked-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 74326b3b5341..13195072b234 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -677,6 +677,20 @@ lun_assigned:
677 return 0; 677 return 0;
678} 678}
679 679
680/* Update an entry in h->dev[] array. */
681static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
682 int entry, struct hpsa_scsi_dev_t *new_entry)
683{
684 /* assumes h->devlock is held */
685 BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES);
686
687 /* Raid level changed. */
688 h->dev[entry]->raid_level = new_entry->raid_level;
689 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d updated.\n",
690 scsi_device_type(new_entry->devtype), hostno, new_entry->bus,
691 new_entry->target, new_entry->lun);
692}
693
680/* Replace an entry from h->dev[] array. */ 694/* Replace an entry from h->dev[] array. */
681static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, 695static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
682 int entry, struct hpsa_scsi_dev_t *new_entry, 696 int entry, struct hpsa_scsi_dev_t *new_entry,
@@ -783,10 +797,25 @@ static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
783 return 1; 797 return 1;
784} 798}
785 799
800static inline int device_updated(struct hpsa_scsi_dev_t *dev1,
801 struct hpsa_scsi_dev_t *dev2)
802{
803 /* Device attributes that can change, but don't mean
804 * that the device is a different device, nor that the OS
805 * needs to be told anything about the change.
806 */
807 if (dev1->raid_level != dev2->raid_level)
808 return 1;
809 return 0;
810}
811
786/* Find needle in haystack. If exact match found, return DEVICE_SAME, 812/* Find needle in haystack. If exact match found, return DEVICE_SAME,
787 * and return needle location in *index. If scsi3addr matches, but not 813 * and return needle location in *index. If scsi3addr matches, but not
788 * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 814 * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle
789 * location in *index. If needle not found, return DEVICE_NOT_FOUND. 815 * location in *index.
816 * In the case of a minor device attribute change, such as RAID level, just
817 * return DEVICE_UPDATED, along with the updated device's location in index.
818 * If needle not found, return DEVICE_NOT_FOUND.
790 */ 819 */
791static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 820static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
792 struct hpsa_scsi_dev_t *haystack[], int haystack_size, 821 struct hpsa_scsi_dev_t *haystack[], int haystack_size,
@@ -796,15 +825,19 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
796#define DEVICE_NOT_FOUND 0 825#define DEVICE_NOT_FOUND 0
797#define DEVICE_CHANGED 1 826#define DEVICE_CHANGED 1
798#define DEVICE_SAME 2 827#define DEVICE_SAME 2
828#define DEVICE_UPDATED 3
799 for (i = 0; i < haystack_size; i++) { 829 for (i = 0; i < haystack_size; i++) {
800 if (haystack[i] == NULL) /* previously removed. */ 830 if (haystack[i] == NULL) /* previously removed. */
801 continue; 831 continue;
802 if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 832 if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) {
803 *index = i; 833 *index = i;
804 if (device_is_the_same(needle, haystack[i])) 834 if (device_is_the_same(needle, haystack[i])) {
835 if (device_updated(needle, haystack[i]))
836 return DEVICE_UPDATED;
805 return DEVICE_SAME; 837 return DEVICE_SAME;
806 else 838 } else {
807 return DEVICE_CHANGED; 839 return DEVICE_CHANGED;
840 }
808 } 841 }
809 } 842 }
810 *index = -1; 843 *index = -1;
@@ -840,6 +873,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
840 * sd[] and remove them from h->dev[], and for any 873 * sd[] and remove them from h->dev[], and for any
841 * devices which have changed, remove the old device 874 * devices which have changed, remove the old device
842 * info and add the new device info. 875 * info and add the new device info.
876 * If minor device attributes change, just update
877 * the existing device structure.
843 */ 878 */
844 i = 0; 879 i = 0;
845 nremoved = 0; 880 nremoved = 0;
@@ -860,6 +895,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
860 * at the bottom of hpsa_update_scsi_devices() 895 * at the bottom of hpsa_update_scsi_devices()
861 */ 896 */
862 sd[entry] = NULL; 897 sd[entry] = NULL;
898 } else if (device_change == DEVICE_UPDATED) {
899 hpsa_scsi_update_entry(h, hostno, i, sd[entry]);
863 } 900 }
864 i++; 901 i++;
865 } 902 }