Skip to content

Commit b7cc176

Browse files
joecar-James Bottomley
authored andcommitted
[SCSI] qla2xxx: Allow region-based flash-part accesses.
Additional cleanups and Signed-off-by: Andrew Vasquez <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 338c916 commit b7cc176

File tree

4 files changed

+96
-20
lines changed

4 files changed

+96
-20
lines changed

drivers/scsi/qla2xxx/qla_attr.c

Lines changed: 90 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
175175

176176
if (ha->optrom_state != QLA_SREADING)
177177
return 0;
178-
if (off > ha->optrom_size)
178+
if (off > ha->optrom_region_size)
179179
return 0;
180-
if (off + count > ha->optrom_size)
181-
count = ha->optrom_size - off;
180+
if (off + count > ha->optrom_region_size)
181+
count = ha->optrom_region_size - off;
182182

183183
memcpy(buf, &ha->optrom_buffer[off], count);
184184

@@ -195,10 +195,10 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj,
195195

196196
if (ha->optrom_state != QLA_SWRITING)
197197
return -EINVAL;
198-
if (off > ha->optrom_size)
198+
if (off > ha->optrom_region_size)
199199
return -ERANGE;
200-
if (off + count > ha->optrom_size)
201-
count = ha->optrom_size - off;
200+
if (off + count > ha->optrom_region_size)
201+
count = ha->optrom_region_size - off;
202202

203203
memcpy(&ha->optrom_buffer[off], buf, count);
204204

@@ -222,12 +222,16 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
222222
{
223223
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
224224
struct device, kobj)));
225-
int val;
225+
uint32_t start = 0;
226+
uint32_t size = ha->optrom_size;
227+
int val, valid;
226228

227229
if (off)
228230
return 0;
229231

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)
231235
return -EINVAL;
232236

233237
switch (val) {
@@ -237,51 +241,119 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
237241
break;
238242

239243
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+
240249
vfree(ha->optrom_buffer);
241250
ha->optrom_buffer = NULL;
242251
break;
243252
case 1:
244253
if (ha->optrom_state != QLA_SWAITING)
245254
break;
246255

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+
247266
ha->optrom_state = QLA_SREADING;
248-
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
267+
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
249268
if (ha->optrom_buffer == NULL) {
250269
qla_printk(KERN_WARNING, ha,
251270
"Unable to allocate memory for optrom retrieval "
252-
"(%x).\n", ha->optrom_size);
271+
"(%x).\n", ha->optrom_region_size);
253272

254273
ha->optrom_state = QLA_SWAITING;
255274
return count;
256275
}
257276

258-
memset(ha->optrom_buffer, 0, ha->optrom_size);
259-
ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0,
260-
ha->optrom_size);
277+
DEBUG2(qla_printk(KERN_INFO, ha,
278+
"Reading flash region -- 0x%x/0x%x.\n",
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);
261284
break;
262285
case 2:
263286
if (ha->optrom_state != QLA_SWAITING)
264287
break;
265288

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+
266327
ha->optrom_state = QLA_SWRITING;
267-
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
328+
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
268329
if (ha->optrom_buffer == NULL) {
269330
qla_printk(KERN_WARNING, ha,
270331
"Unable to allocate memory for optrom update "
271-
"(%x).\n", ha->optrom_size);
332+
"(%x).\n", ha->optrom_region_size);
272333

273334
ha->optrom_state = QLA_SWAITING;
274335
return count;
275336
}
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);
277343
break;
278344
case 3:
279345
if (ha->optrom_state != QLA_SWRITING)
280346
break;
281347

282-
ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0,
283-
ha->optrom_size);
348+
DEBUG2(qla_printk(KERN_INFO, ha,
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);
284354
break;
355+
default:
356+
count = -EINVAL;
285357
}
286358
return count;
287359
}

drivers/scsi/qla2xxx/qla_def.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,8 @@ typedef struct scsi_qla_host {
24782478
#define QLA_SWAITING 0
24792479
#define QLA_SREADING 1
24802480
#define QLA_SWRITING 2
2481+
uint32_t optrom_region_start;
2482+
uint32_t optrom_region_size;
24812483

24822484
/* PCI expansion ROM image information. */
24832485
#define ROM_CODE_TYPE_BIOS 0

drivers/scsi/qla2xxx/qla_fw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,8 @@ struct device_reg_24xx {
779779
#define FA_NVRAM_VPD_SIZE 0x200
780780
#define FA_NVRAM_VPD0_ADDR 0x00
781781
#define FA_NVRAM_VPD1_ADDR 0x100
782+
783+
#define FA_BOOT_CODE_ADDR 0x00000
782784
/*
783785
* RISC code begins at offset 512KB
784786
* within flash. Consisting of two

drivers/scsi/qla2xxx/qla_sup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
559559
ret = QLA_SUCCESS;
560560

561561
/* Prepare burst-capable write on supported ISPs. */
562-
if (IS_QLA25XX(ha) && !(faddr & ~OPTROM_BURST_SIZE) &&
562+
if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
563563
dwords > OPTROM_BURST_DWORDS) {
564564
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
565565
&optrom_dma, GFP_KERNEL);
@@ -1824,7 +1824,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
18241824
uint8_t *pbuf;
18251825
uint32_t faddr, left, burst;
18261826

1827-
if (offset & ~OPTROM_BURST_SIZE)
1827+
if (offset & 0xfff)
18281828
goto slow_read;
18291829
if (length < OPTROM_BURST_SIZE)
18301830
goto slow_read;

0 commit comments

Comments
 (0)