aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c108
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c4
4 files changed, 96 insertions, 20 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 0f2a9f5d801..8e7e00cf7e8 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}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 4af08561883..e1e342889b2 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2478,6 +2478,8 @@ typedef struct scsi_qla_host {
2478#define QLA_SWAITING 0 2478#define QLA_SWAITING 0
2479#define QLA_SREADING 1 2479#define QLA_SREADING 1
2480#define QLA_SWRITING 2 2480#define QLA_SWRITING 2
2481 uint32_t optrom_region_start;
2482 uint32_t optrom_region_size;
2481 2483
2482 /* PCI expansion ROM image information. */ 2484 /* PCI expansion ROM image information. */
2483#define ROM_CODE_TYPE_BIOS 0 2485#define ROM_CODE_TYPE_BIOS 0
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 99fe49618d6..d5344d7a862 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -779,6 +779,8 @@ struct device_reg_24xx {
779#define FA_NVRAM_VPD_SIZE 0x200 779#define FA_NVRAM_VPD_SIZE 0x200
780#define FA_NVRAM_VPD0_ADDR 0x00 780#define FA_NVRAM_VPD0_ADDR 0x00
781#define FA_NVRAM_VPD1_ADDR 0x100 781#define FA_NVRAM_VPD1_ADDR 0x100
782
783#define FA_BOOT_CODE_ADDR 0x00000
782 /* 784 /*
783 * RISC code begins at offset 512KB 785 * RISC code begins at offset 512KB
784 * within flash. Consisting of two 786 * within flash. Consisting of two
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index ad3d1de51d8..40b059fc198 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -559,7 +559,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
559 ret = QLA_SUCCESS; 559 ret = QLA_SUCCESS;
560 560
561 /* Prepare burst-capable write on supported ISPs. */ 561 /* Prepare burst-capable write on supported ISPs. */
562 if (IS_QLA25XX(ha) && !(faddr & ~OPTROM_BURST_SIZE) && 562 if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
563 dwords > OPTROM_BURST_DWORDS) { 563 dwords > OPTROM_BURST_DWORDS) {
564 optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, 564 optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
565 &optrom_dma, GFP_KERNEL); 565 &optrom_dma, GFP_KERNEL);
@@ -1824,7 +1824,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
1824 uint8_t *pbuf; 1824 uint8_t *pbuf;
1825 uint32_t faddr, left, burst; 1825 uint32_t faddr, left, burst;
1826 1826
1827 if (offset & ~OPTROM_BURST_SIZE) 1827 if (offset & 0xfff)
1828 goto slow_read; 1828 goto slow_read;
1829 if (length < OPTROM_BURST_SIZE) 1829 if (length < OPTROM_BURST_SIZE)
1830 goto slow_read; 1830 goto slow_read;