diff options
author | Don Brace <don.brace@microsemi.com> | 2016-07-01 14:37:31 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-07-15 15:40:39 -0400 |
commit | 64ce60cab24603ac0fcd59c9fbc3be78f4c4d229 (patch) | |
tree | c45c5bc174ed56461c455b22c90c0735068d321a /drivers/scsi | |
parent | 094f71c70b5c25176709081cedda23228a0d82ab (diff) |
hpsa: correct skipping masked peripherals
The SA controller spins down RAID drive spares.
A REGNEWD event causes an inquiry to be sent to all physical
drives. This causes the SA controller to spin up the spare.
The controller suspends all I/O to a logical volume until
the spare is spun up. The spin-up can take over 50 seconds.
This can result in one or both of the following:
- SML sends down aborts and resets to the logical volume
and can cause the logical volume to be off-lined.
- a negative impact on the logical volume's I/O performance
each time a REGNEWD is triggered.
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/hpsa.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ff8dcd5b0631..375a39632a7a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -4105,6 +4105,70 @@ static int hpsa_set_local_logical_count(struct ctlr_info *h, | |||
4105 | return rc; | 4105 | return rc; |
4106 | } | 4106 | } |
4107 | 4107 | ||
4108 | static bool hpsa_is_disk_spare(struct ctlr_info *h, u8 *lunaddrbytes) | ||
4109 | { | ||
4110 | struct bmic_identify_physical_device *id_phys; | ||
4111 | bool is_spare = false; | ||
4112 | int rc; | ||
4113 | |||
4114 | id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL); | ||
4115 | if (!id_phys) | ||
4116 | return false; | ||
4117 | |||
4118 | rc = hpsa_bmic_id_physical_device(h, | ||
4119 | lunaddrbytes, | ||
4120 | GET_BMIC_DRIVE_NUMBER(lunaddrbytes), | ||
4121 | id_phys, sizeof(*id_phys)); | ||
4122 | if (rc == 0) | ||
4123 | is_spare = (id_phys->more_flags >> 6) & 0x01; | ||
4124 | |||
4125 | kfree(id_phys); | ||
4126 | return is_spare; | ||
4127 | } | ||
4128 | |||
4129 | #define RPL_DEV_FLAG_NON_DISK 0x1 | ||
4130 | #define RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED 0x2 | ||
4131 | #define RPL_DEV_FLAG_UNCONFIG_DISK 0x4 | ||
4132 | |||
4133 | #define BMIC_DEVICE_TYPE_ENCLOSURE 6 | ||
4134 | |||
4135 | static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, | ||
4136 | struct ext_report_lun_entry *rle) | ||
4137 | { | ||
4138 | u8 device_flags; | ||
4139 | u8 device_type; | ||
4140 | |||
4141 | if (!MASKED_DEVICE(lunaddrbytes)) | ||
4142 | return false; | ||
4143 | |||
4144 | device_flags = rle->device_flags; | ||
4145 | device_type = rle->device_type; | ||
4146 | |||
4147 | if (device_flags & RPL_DEV_FLAG_NON_DISK) { | ||
4148 | if (device_type == BMIC_DEVICE_TYPE_ENCLOSURE) | ||
4149 | return false; | ||
4150 | return true; | ||
4151 | } | ||
4152 | |||
4153 | if (!(device_flags & RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED)) | ||
4154 | return false; | ||
4155 | |||
4156 | if (device_flags & RPL_DEV_FLAG_UNCONFIG_DISK) | ||
4157 | return false; | ||
4158 | |||
4159 | /* | ||
4160 | * Spares may be spun down, we do not want to | ||
4161 | * do an Inquiry to a RAID set spare drive as | ||
4162 | * that would have them spun up, that is a | ||
4163 | * performance hit because I/O to the RAID device | ||
4164 | * stops while the spin up occurs which can take | ||
4165 | * over 50 seconds. | ||
4166 | */ | ||
4167 | if (hpsa_is_disk_spare(h, lunaddrbytes)) | ||
4168 | return true; | ||
4169 | |||
4170 | return false; | ||
4171 | } | ||
4108 | 4172 | ||
4109 | static void hpsa_update_scsi_devices(struct ctlr_info *h) | 4173 | static void hpsa_update_scsi_devices(struct ctlr_info *h) |
4110 | { | 4174 | { |
@@ -4198,6 +4262,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) | |||
4198 | u8 *lunaddrbytes, is_OBDR = 0; | 4262 | u8 *lunaddrbytes, is_OBDR = 0; |
4199 | int rc = 0; | 4263 | int rc = 0; |
4200 | int phys_dev_index = i - (raid_ctlr_position == 0); | 4264 | int phys_dev_index = i - (raid_ctlr_position == 0); |
4265 | bool skip_device = false; | ||
4201 | 4266 | ||
4202 | physical_device = i < nphysicals + (raid_ctlr_position == 0); | 4267 | physical_device = i < nphysicals + (raid_ctlr_position == 0); |
4203 | 4268 | ||
@@ -4205,11 +4270,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) | |||
4205 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, | 4270 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, |
4206 | i, nphysicals, nlogicals, physdev_list, logdev_list); | 4271 | i, nphysicals, nlogicals, physdev_list, logdev_list); |
4207 | 4272 | ||
4208 | /* skip masked non-disk devices */ | 4273 | /* |
4209 | if (MASKED_DEVICE(lunaddrbytes) && physical_device && | 4274 | * Skip over some devices such as a spare. |
4210 | (physdev_list->LUN[phys_dev_index].device_type != 0x06) && | 4275 | */ |
4211 | (physdev_list->LUN[phys_dev_index].device_flags & 0x01)) | 4276 | if (!tmpdevice->external && physical_device) { |
4212 | continue; | 4277 | skip_device = hpsa_skip_device(h, lunaddrbytes, |
4278 | &physdev_list->LUN[phys_dev_index]); | ||
4279 | if (skip_device) | ||
4280 | continue; | ||
4281 | } | ||
4213 | 4282 | ||
4214 | /* Get device type, vendor, model, device id */ | 4283 | /* Get device type, vendor, model, device id */ |
4215 | rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, | 4284 | rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, |