Skip to content

Commit 9a908c1

Browse files
Herton Ronaldo KrzesinskiJames Bottomley
authored andcommitted
[SCSI] advansys: fix narrow board error path
Error handling on advansys_board_found is fixed, because it's buggy in the case we have an ASC_NARROW_BOARD set and failure happens on AscInitAsc1000Driver step: it was freeing items of wrong struct in the dvc_var union of struct asc_board, which could lead to an oops in the case we set some of the fields in struct of narrow board as code was choosing to always freeing wide board fields, and not everything was being freed/released properly. Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
1 parent be1066b commit 9a908c1

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

drivers/scsi/advansys.c

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4724,6 +4724,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
47244724
BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);
47254725
asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,
47264726
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
4727+
if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) {
4728+
warn_code = -ENOMEM;
4729+
goto err_dma_map;
4730+
}
47274731
phy_addr = cpu_to_le32(asc_dvc->overrun_dma);
47284732
AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
47294733
(uchar *)&phy_addr, 1);
@@ -4739,14 +4743,23 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
47394743
AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
47404744
if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
47414745
asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
4742-
return warn_code;
4746+
warn_code = UW_ERR;
4747+
goto err_mcode_start;
47434748
}
47444749
if (AscStartChip(iop_base) != 1) {
47454750
asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
4746-
return warn_code;
4751+
warn_code = UW_ERR;
4752+
goto err_mcode_start;
47474753
}
47484754

47494755
return warn_code;
4756+
4757+
err_mcode_start:
4758+
dma_unmap_single(board->dev, asc_dvc->overrun_dma,
4759+
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
4760+
err_dma_map:
4761+
asc_dvc->overrun_dma = 0;
4762+
return warn_code;
47504763
}
47514764

47524765
static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
@@ -4802,6 +4815,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
48024815
}
48034816
release_firmware(fw);
48044817
warn_code |= AscInitMicroCodeVar(asc_dvc);
4818+
if (!asc_dvc->overrun_dma)
4819+
return warn_code;
48054820
asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
48064821
AscEnableInterrupt(iop_base);
48074822
return warn_code;
@@ -7978,9 +7993,10 @@ static int advansys_reset(struct scsi_cmnd *scp)
79787993
status = AscInitAsc1000Driver(asc_dvc);
79797994

79807995
/* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */
7981-
if (asc_dvc->err_code) {
7996+
if (asc_dvc->err_code || !asc_dvc->overrun_dma) {
79827997
scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
7983-
"0x%x\n", asc_dvc->err_code);
7998+
"0x%x, status: 0x%x\n", asc_dvc->err_code,
7999+
status);
79848000
ret = FAILED;
79858001
} else if (status) {
79868002
scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
@@ -12311,7 +12327,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
1231112327
asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);
1231212328
if (!asc_dvc_varp->overrun_buf) {
1231312329
ret = -ENOMEM;
12314-
goto err_free_wide_mem;
12330+
goto err_free_irq;
1231512331
}
1231612332
warn_code = AscInitAsc1000Driver(asc_dvc_varp);
1231712333

@@ -12320,30 +12336,36 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
1232012336
"warn 0x%x, error 0x%x\n",
1232112337
asc_dvc_varp->init_state, warn_code,
1232212338
asc_dvc_varp->err_code);
12323-
if (asc_dvc_varp->err_code) {
12339+
if (!asc_dvc_varp->overrun_dma) {
1232412340
ret = -ENODEV;
12325-
kfree(asc_dvc_varp->overrun_buf);
12341+
goto err_free_mem;
1232612342
}
1232712343
}
1232812344
} else {
12329-
if (advansys_wide_init_chip(shost))
12345+
if (advansys_wide_init_chip(shost)) {
1233012346
ret = -ENODEV;
12347+
goto err_free_mem;
12348+
}
1233112349
}
1233212350

12333-
if (ret)
12334-
goto err_free_wide_mem;
12335-
1233612351
ASC_DBG_PRT_SCSI_HOST(2, shost);
1233712352

1233812353
ret = scsi_add_host(shost, boardp->dev);
1233912354
if (ret)
12340-
goto err_free_wide_mem;
12355+
goto err_free_mem;
1234112356

1234212357
scsi_scan_host(shost);
1234312358
return 0;
1234412359

12345-
err_free_wide_mem:
12346-
advansys_wide_free_mem(boardp);
12360+
err_free_mem:
12361+
if (ASC_NARROW_BOARD(boardp)) {
12362+
if (asc_dvc_varp->overrun_dma)
12363+
dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma,
12364+
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
12365+
kfree(asc_dvc_varp->overrun_buf);
12366+
} else
12367+
advansys_wide_free_mem(boardp);
12368+
err_free_irq:
1234712369
free_irq(boardp->irq, shost);
1234812370
err_free_dma:
1234912371
#ifdef CONFIG_ISA

0 commit comments

Comments
 (0)