diff options
author | Joe Carnuccio <joe.carnuccio@qlogic.com> | 2007-09-20 17:07:35 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:49:42 -0400 |
commit | b7cc176c9eb3aa6989ac099efd8bdd6d0eaa784a (patch) | |
tree | d0fb43580ecc2c84625b7bc7a3d86d2e72853a4c /drivers/scsi/qla2xxx/qla_attr.c | |
parent | 338c9161e406591afbc1a6635a68d3b6d5362e00 (diff) |
[SCSI] qla2xxx: Allow region-based flash-part accesses.
Additional cleanups and
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 108 |
1 files changed, 90 insertions, 18 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 0f2a9f5d801c..8e7e00cf7e81 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, | |||
175 | 175 | ||
176 | if (ha->optrom_state != QLA_SREADING) | 176 | if (ha->optrom_state != QLA_SREADING) |
177 | return 0; | 177 | return 0; |
178 | if (off > ha->optrom_size) | 178 | if (off > ha->optrom_region_size) |
179 | return 0; | 179 | return 0; |
180 | if (off + count > ha->optrom_size) | 180 | if (off + count > ha->optrom_region_size) |
181 | count = ha->optrom_size - off; | 181 | count = ha->optrom_region_size - off; |
182 | 182 | ||
183 | memcpy(buf, &ha->optrom_buffer[off], count); | 183 | memcpy(buf, &ha->optrom_buffer[off], count); |
184 | 184 | ||
@@ -195,10 +195,10 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj, | |||
195 | 195 | ||
196 | if (ha->optrom_state != QLA_SWRITING) | 196 | if (ha->optrom_state != QLA_SWRITING) |
197 | return -EINVAL; | 197 | return -EINVAL; |
198 | if (off > ha->optrom_size) | 198 | if (off > ha->optrom_region_size) |
199 | return -ERANGE; | 199 | return -ERANGE; |
200 | if (off + count > ha->optrom_size) | 200 | if (off + count > ha->optrom_region_size) |
201 | count = ha->optrom_size - off; | 201 | count = ha->optrom_region_size - off; |
202 | 202 | ||
203 | memcpy(&ha->optrom_buffer[off], buf, count); | 203 | memcpy(&ha->optrom_buffer[off], buf, count); |
204 | 204 | ||
@@ -222,12 +222,16 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
222 | { | 222 | { |
223 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 223 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
224 | struct device, kobj))); | 224 | struct device, kobj))); |
225 | int val; | 225 | uint32_t start = 0; |
226 | uint32_t size = ha->optrom_size; | ||
227 | int val, valid; | ||
226 | 228 | ||
227 | if (off) | 229 | if (off) |
228 | return 0; | 230 | return 0; |
229 | 231 | ||
230 | if (sscanf(buf, "%d", &val) != 1) | 232 | if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) |
233 | return -EINVAL; | ||
234 | if (start > ha->optrom_size) | ||
231 | return -EINVAL; | 235 | return -EINVAL; |
232 | 236 | ||
233 | switch (val) { | 237 | switch (val) { |
@@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
237 | break; | 241 | break; |
238 | 242 | ||
239 | ha->optrom_state = QLA_SWAITING; | 243 | ha->optrom_state = QLA_SWAITING; |
244 | |||
245 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
246 | "Freeing flash region allocation -- 0x%x bytes.\n", | ||
247 | ha->optrom_region_size)); | ||
248 | |||
240 | vfree(ha->optrom_buffer); | 249 | vfree(ha->optrom_buffer); |
241 | ha->optrom_buffer = NULL; | 250 | ha->optrom_buffer = NULL; |
242 | break; | 251 | break; |
@@ -244,44 +253,107 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
244 | if (ha->optrom_state != QLA_SWAITING) | 253 | if (ha->optrom_state != QLA_SWAITING) |
245 | break; | 254 | break; |
246 | 255 | ||
256 | if (start & 0xfff) { | ||
257 | qla_printk(KERN_WARNING, ha, | ||
258 | "Invalid start region 0x%x/0x%x.\n", start, size); | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | |||
262 | ha->optrom_region_start = start; | ||
263 | ha->optrom_region_size = start + size > ha->optrom_size ? | ||
264 | ha->optrom_size - start : size; | ||
265 | |||
247 | ha->optrom_state = QLA_SREADING; | 266 | ha->optrom_state = QLA_SREADING; |
248 | ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); | 267 | ha->optrom_buffer = vmalloc(ha->optrom_region_size); |
249 | if (ha->optrom_buffer == NULL) { | 268 | if (ha->optrom_buffer == NULL) { |
250 | qla_printk(KERN_WARNING, ha, | 269 | qla_printk(KERN_WARNING, ha, |
251 | "Unable to allocate memory for optrom retrieval " | 270 | "Unable to allocate memory for optrom retrieval " |
252 | "(%x).\n", ha->optrom_size); | 271 | "(%x).\n", ha->optrom_region_size); |
253 | 272 | ||
254 | ha->optrom_state = QLA_SWAITING; | 273 | ha->optrom_state = QLA_SWAITING; |
255 | return count; | 274 | return count; |
256 | } | 275 | } |
257 | 276 | ||
258 | memset(ha->optrom_buffer, 0, ha->optrom_size); | 277 | DEBUG2(qla_printk(KERN_INFO, ha, |
259 | ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, | 278 | "Reading flash region -- 0x%x/0x%x.\n", |
260 | ha->optrom_size); | 279 | ha->optrom_region_start, ha->optrom_region_size)); |
280 | |||
281 | memset(ha->optrom_buffer, 0, ha->optrom_region_size); | ||
282 | ha->isp_ops->read_optrom(ha, ha->optrom_buffer, | ||
283 | ha->optrom_region_start, ha->optrom_region_size); | ||
261 | break; | 284 | break; |
262 | case 2: | 285 | case 2: |
263 | if (ha->optrom_state != QLA_SWAITING) | 286 | if (ha->optrom_state != QLA_SWAITING) |
264 | break; | 287 | break; |
265 | 288 | ||
289 | /* | ||
290 | * We need to be more restrictive on which FLASH regions are | ||
291 | * allowed to be updated via user-space. Regions accessible | ||
292 | * via this method include: | ||
293 | * | ||
294 | * ISP21xx/ISP22xx/ISP23xx type boards: | ||
295 | * | ||
296 | * 0x000000 -> 0x020000 -- Boot code. | ||
297 | * | ||
298 | * ISP2322/ISP24xx type boards: | ||
299 | * | ||
300 | * 0x000000 -> 0x07ffff -- Boot code. | ||
301 | * 0x080000 -> 0x0fffff -- Firmware. | ||
302 | * | ||
303 | * ISP25xx type boards: | ||
304 | * | ||
305 | * 0x000000 -> 0x07ffff -- Boot code. | ||
306 | * 0x080000 -> 0x0fffff -- Firmware. | ||
307 | * 0x120000 -> 0x12ffff -- VPD and HBA parameters. | ||
308 | */ | ||
309 | valid = 0; | ||
310 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) | ||
311 | valid = 1; | ||
312 | else if (start == (FA_BOOT_CODE_ADDR*4) || | ||
313 | start == (FA_RISC_CODE_ADDR*4)) | ||
314 | valid = 1; | ||
315 | else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) | ||
316 | valid = 1; | ||
317 | if (!valid) { | ||
318 | qla_printk(KERN_WARNING, ha, | ||
319 | "Invalid start region 0x%x/0x%x.\n", start, size); | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | ha->optrom_region_start = start; | ||
324 | ha->optrom_region_size = start + size > ha->optrom_size ? | ||
325 | ha->optrom_size - start : size; | ||
326 | |||
266 | ha->optrom_state = QLA_SWRITING; | 327 | ha->optrom_state = QLA_SWRITING; |
267 | ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); | 328 | ha->optrom_buffer = vmalloc(ha->optrom_region_size); |
268 | if (ha->optrom_buffer == NULL) { | 329 | if (ha->optrom_buffer == NULL) { |
269 | qla_printk(KERN_WARNING, ha, | 330 | qla_printk(KERN_WARNING, ha, |
270 | "Unable to allocate memory for optrom update " | 331 | "Unable to allocate memory for optrom update " |
271 | "(%x).\n", ha->optrom_size); | 332 | "(%x).\n", ha->optrom_region_size); |
272 | 333 | ||
273 | ha->optrom_state = QLA_SWAITING; | 334 | ha->optrom_state = QLA_SWAITING; |
274 | return count; | 335 | return count; |
275 | } | 336 | } |
276 | memset(ha->optrom_buffer, 0, ha->optrom_size); | 337 | |
338 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
339 | "Staging flash region write -- 0x%x/0x%x.\n", | ||
340 | ha->optrom_region_start, ha->optrom_region_size)); | ||
341 | |||
342 | memset(ha->optrom_buffer, 0, ha->optrom_region_size); | ||
277 | break; | 343 | break; |
278 | case 3: | 344 | case 3: |
279 | if (ha->optrom_state != QLA_SWRITING) | 345 | if (ha->optrom_state != QLA_SWRITING) |
280 | break; | 346 | break; |
281 | 347 | ||
282 | ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, | 348 | DEBUG2(qla_printk(KERN_INFO, ha, |
283 | ha->optrom_size); | 349 | "Writing flash region -- 0x%x/0x%x.\n", |
350 | ha->optrom_region_start, ha->optrom_region_size)); | ||
351 | |||
352 | ha->isp_ops->write_optrom(ha, ha->optrom_buffer, | ||
353 | ha->optrom_region_start, ha->optrom_region_size); | ||
284 | break; | 354 | break; |
355 | default: | ||
356 | count = -EINVAL; | ||
285 | } | 357 | } |
286 | return count; | 358 | return count; |
287 | } | 359 | } |