提交 9a908c1a 编写于 作者: H Herton Ronaldo Krzesinski 提交者: James Bottomley

[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: NHerton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: NJames Bottomley <James.Bottomley@suse.de>
上级 be1066bb
......@@ -4724,6 +4724,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);
asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) {
warn_code = -ENOMEM;
goto err_dma_map;
}
phy_addr = cpu_to_le32(asc_dvc->overrun_dma);
AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
(uchar *)&phy_addr, 1);
......@@ -4739,14 +4743,23 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
return warn_code;
warn_code = UW_ERR;
goto err_mcode_start;
}
if (AscStartChip(iop_base) != 1) {
asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
return warn_code;
warn_code = UW_ERR;
goto err_mcode_start;
}
return warn_code;
err_mcode_start:
dma_unmap_single(board->dev, asc_dvc->overrun_dma,
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
err_dma_map:
asc_dvc->overrun_dma = 0;
return warn_code;
}
static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
......@@ -4802,6 +4815,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
}
release_firmware(fw);
warn_code |= AscInitMicroCodeVar(asc_dvc);
if (!asc_dvc->overrun_dma)
return warn_code;
asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
AscEnableInterrupt(iop_base);
return warn_code;
......@@ -7978,9 +7993,10 @@ static int advansys_reset(struct scsi_cmnd *scp)
status = AscInitAsc1000Driver(asc_dvc);
/* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */
if (asc_dvc->err_code) {
if (asc_dvc->err_code || !asc_dvc->overrun_dma) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
"0x%x\n", asc_dvc->err_code);
"0x%x, status: 0x%x\n", asc_dvc->err_code,
status);
ret = FAILED;
} else if (status) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
......@@ -12311,7 +12327,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);
if (!asc_dvc_varp->overrun_buf) {
ret = -ENOMEM;
goto err_free_wide_mem;
goto err_free_irq;
}
warn_code = AscInitAsc1000Driver(asc_dvc_varp);
......@@ -12320,30 +12336,36 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
"warn 0x%x, error 0x%x\n",
asc_dvc_varp->init_state, warn_code,
asc_dvc_varp->err_code);
if (asc_dvc_varp->err_code) {
if (!asc_dvc_varp->overrun_dma) {
ret = -ENODEV;
kfree(asc_dvc_varp->overrun_buf);
goto err_free_mem;
}
}
} else {
if (advansys_wide_init_chip(shost))
if (advansys_wide_init_chip(shost)) {
ret = -ENODEV;
goto err_free_mem;
}
}
if (ret)
goto err_free_wide_mem;
ASC_DBG_PRT_SCSI_HOST(2, shost);
ret = scsi_add_host(shost, boardp->dev);
if (ret)
goto err_free_wide_mem;
goto err_free_mem;
scsi_scan_host(shost);
return 0;
err_free_wide_mem:
advansys_wide_free_mem(boardp);
err_free_mem:
if (ASC_NARROW_BOARD(boardp)) {
if (asc_dvc_varp->overrun_dma)
dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma,
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
kfree(asc_dvc_varp->overrun_buf);
} else
advansys_wide_free_mem(boardp);
err_free_irq:
free_irq(boardp->irq, shost);
err_free_dma:
#ifdef CONFIG_ISA
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册