diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-02-07 19:50:08 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-11 11:20:53 -0500 |
commit | 7d5d408c77cee95d1380511de46b7a4c8dc2211d (patch) | |
tree | bec3464f501145718b2426efde10b02229de4552 /drivers | |
parent | 19af35546de68c872dcb687613e0902a602cb20e (diff) |
[SCSI] advansys: fix overrun_buf aligned bug
struct asc_dvc_var needs overrun buffer to be placed on an 8 byte
boundary. advansys defines struct asc_dvc_var:
struct asc_dvc_var {
...
uchar overrun_buf[ASC_OVERRUN_BSIZE] __aligned(8);
The problem is that struct asc_dvc_var is placed on
shost->hostdata. So if the hostdata is not on an 8 byte boundary, the
advansys crashes. The hostdata is placed on a sizeof(unsigned long)
boundary so the 8 byte boundary is not garanteed with x86_32.
With 2.6.23 and 2.6.24, the hostdata is on an 8 byte boundary by
chance, but with the current git, it's not.
This patch removes overrun_buf static array and use kzalloc.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/advansys.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index ccef891d642f..3c2d6888bb8c 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -566,7 +566,7 @@ typedef struct asc_dvc_var { | |||
566 | ASC_SCSI_BIT_ID_TYPE unit_not_ready; | 566 | ASC_SCSI_BIT_ID_TYPE unit_not_ready; |
567 | ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; | 567 | ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; |
568 | ASC_SCSI_BIT_ID_TYPE start_motor; | 568 | ASC_SCSI_BIT_ID_TYPE start_motor; |
569 | uchar overrun_buf[ASC_OVERRUN_BSIZE] __aligned(8); | 569 | uchar *overrun_buf; |
570 | dma_addr_t overrun_dma; | 570 | dma_addr_t overrun_dma; |
571 | uchar scsi_reset_wait; | 571 | uchar scsi_reset_wait; |
572 | uchar chip_no; | 572 | uchar chip_no; |
@@ -13833,6 +13833,12 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, | |||
13833 | */ | 13833 | */ |
13834 | if (ASC_NARROW_BOARD(boardp)) { | 13834 | if (ASC_NARROW_BOARD(boardp)) { |
13835 | ASC_DBG(2, "AscInitAsc1000Driver()\n"); | 13835 | ASC_DBG(2, "AscInitAsc1000Driver()\n"); |
13836 | |||
13837 | asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL); | ||
13838 | if (!asc_dvc_varp->overrun_buf) { | ||
13839 | ret = -ENOMEM; | ||
13840 | goto err_free_wide_mem; | ||
13841 | } | ||
13836 | warn_code = AscInitAsc1000Driver(asc_dvc_varp); | 13842 | warn_code = AscInitAsc1000Driver(asc_dvc_varp); |
13837 | 13843 | ||
13838 | if (warn_code || asc_dvc_varp->err_code) { | 13844 | if (warn_code || asc_dvc_varp->err_code) { |
@@ -13840,8 +13846,10 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, | |||
13840 | "warn 0x%x, error 0x%x\n", | 13846 | "warn 0x%x, error 0x%x\n", |
13841 | asc_dvc_varp->init_state, warn_code, | 13847 | asc_dvc_varp->init_state, warn_code, |
13842 | asc_dvc_varp->err_code); | 13848 | asc_dvc_varp->err_code); |
13843 | if (asc_dvc_varp->err_code) | 13849 | if (asc_dvc_varp->err_code) { |
13844 | ret = -ENODEV; | 13850 | ret = -ENODEV; |
13851 | kfree(asc_dvc_varp->overrun_buf); | ||
13852 | } | ||
13845 | } | 13853 | } |
13846 | } else { | 13854 | } else { |
13847 | if (advansys_wide_init_chip(shost)) | 13855 | if (advansys_wide_init_chip(shost)) |
@@ -13894,6 +13902,7 @@ static int advansys_release(struct Scsi_Host *shost) | |||
13894 | dma_unmap_single(board->dev, | 13902 | dma_unmap_single(board->dev, |
13895 | board->dvc_var.asc_dvc_var.overrun_dma, | 13903 | board->dvc_var.asc_dvc_var.overrun_dma, |
13896 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); | 13904 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); |
13905 | kfree(board->dvc_var.asc_dvc_var.overrun_buf); | ||
13897 | } else { | 13906 | } else { |
13898 | iounmap(board->ioremap_addr); | 13907 | iounmap(board->ioremap_addr); |
13899 | advansys_wide_free_mem(board); | 13908 | advansys_wide_free_mem(board); |