[SCSI] pm80xx: 4G boundary fix.
Firmware is having an issue. When a single IO request crosses 4G boundary, system will crash. To avoid the issue single sg is converted into extended sg. Signed-off-by: Anandkumar.Santhanam@pmcs.com Reviewed-by: Jack Wang <jinpu.wang@profitbricks.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
f9cd6cbd80
commit
0ecdf00ba6
@ -3610,7 +3610,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
|
||||
struct ssp_ini_io_start_req ssp_cmd;
|
||||
u32 tag = ccb->ccb_tag;
|
||||
int ret;
|
||||
u64 phys_addr;
|
||||
u64 phys_addr, start_addr, end_addr;
|
||||
u32 end_addr_high, end_addr_low;
|
||||
struct inbound_queue_table *circularQ;
|
||||
u32 q_index;
|
||||
u32 opc = OPC_INB_SSPINIIOSTART;
|
||||
@ -3664,6 +3665,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
|
||||
cpu_to_le32(upper_32_bits(dma_addr));
|
||||
ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
|
||||
ssp_cmd.enc_esgl = 0;
|
||||
/* Check 4G Boundary */
|
||||
start_addr = cpu_to_le64(dma_addr);
|
||||
end_addr = (start_addr + ssp_cmd.enc_len) - 1;
|
||||
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
|
||||
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
|
||||
if (end_addr_high != ssp_cmd.enc_addr_high) {
|
||||
PM8001_FAIL_DBG(pm8001_ha,
|
||||
pm8001_printk("The sg list address "
|
||||
"start_addr=0x%016llx data_len=0x%x "
|
||||
"end_addr_high=0x%08x end_addr_low="
|
||||
"0x%08x has crossed 4G boundary\n",
|
||||
start_addr, ssp_cmd.enc_len,
|
||||
end_addr_high, end_addr_low));
|
||||
pm8001_chip_make_sg(task->scatter, 1,
|
||||
ccb->buf_prd);
|
||||
phys_addr = ccb->ccb_dma_handle +
|
||||
offsetof(struct pm8001_ccb_info,
|
||||
buf_prd[0]);
|
||||
ssp_cmd.enc_addr_low =
|
||||
cpu_to_le32(lower_32_bits(phys_addr));
|
||||
ssp_cmd.enc_addr_high =
|
||||
cpu_to_le32(upper_32_bits(phys_addr));
|
||||
ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
|
||||
}
|
||||
} else if (task->num_scatter == 0) {
|
||||
ssp_cmd.enc_addr_low = 0;
|
||||
ssp_cmd.enc_addr_high = 0;
|
||||
@ -3699,6 +3724,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
|
||||
cpu_to_le32(upper_32_bits(dma_addr));
|
||||
ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
|
||||
ssp_cmd.esgl = 0;
|
||||
/* Check 4G Boundary */
|
||||
start_addr = cpu_to_le64(dma_addr);
|
||||
end_addr = (start_addr + ssp_cmd.len) - 1;
|
||||
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
|
||||
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
|
||||
if (end_addr_high != ssp_cmd.addr_high) {
|
||||
PM8001_FAIL_DBG(pm8001_ha,
|
||||
pm8001_printk("The sg list address "
|
||||
"start_addr=0x%016llx data_len=0x%x "
|
||||
"end_addr_high=0x%08x end_addr_low="
|
||||
"0x%08x has crossed 4G boundary\n",
|
||||
start_addr, ssp_cmd.len,
|
||||
end_addr_high, end_addr_low));
|
||||
pm8001_chip_make_sg(task->scatter, 1,
|
||||
ccb->buf_prd);
|
||||
phys_addr = ccb->ccb_dma_handle +
|
||||
offsetof(struct pm8001_ccb_info,
|
||||
buf_prd[0]);
|
||||
ssp_cmd.addr_low =
|
||||
cpu_to_le32(lower_32_bits(phys_addr));
|
||||
ssp_cmd.addr_high =
|
||||
cpu_to_le32(upper_32_bits(phys_addr));
|
||||
ssp_cmd.esgl = cpu_to_le32(1<<31);
|
||||
}
|
||||
} else if (task->num_scatter == 0) {
|
||||
ssp_cmd.addr_low = 0;
|
||||
ssp_cmd.addr_high = 0;
|
||||
@ -3723,7 +3772,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
|
||||
u32 q_index;
|
||||
struct sata_start_req sata_cmd;
|
||||
u32 hdr_tag, ncg_tag = 0;
|
||||
u64 phys_addr;
|
||||
u64 phys_addr, start_addr, end_addr;
|
||||
u32 end_addr_high, end_addr_low;
|
||||
u32 ATAP = 0x0;
|
||||
u32 dir;
|
||||
struct inbound_queue_table *circularQ;
|
||||
@ -3792,6 +3842,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
|
||||
sata_cmd.enc_addr_high = upper_32_bits(dma_addr);
|
||||
sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
|
||||
sata_cmd.enc_esgl = 0;
|
||||
/* Check 4G Boundary */
|
||||
start_addr = cpu_to_le64(dma_addr);
|
||||
end_addr = (start_addr + sata_cmd.enc_len) - 1;
|
||||
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
|
||||
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
|
||||
if (end_addr_high != sata_cmd.enc_addr_high) {
|
||||
PM8001_FAIL_DBG(pm8001_ha,
|
||||
pm8001_printk("The sg list address "
|
||||
"start_addr=0x%016llx data_len=0x%x "
|
||||
"end_addr_high=0x%08x end_addr_low"
|
||||
"=0x%08x has crossed 4G boundary\n",
|
||||
start_addr, sata_cmd.enc_len,
|
||||
end_addr_high, end_addr_low));
|
||||
pm8001_chip_make_sg(task->scatter, 1,
|
||||
ccb->buf_prd);
|
||||
phys_addr = ccb->ccb_dma_handle +
|
||||
offsetof(struct pm8001_ccb_info,
|
||||
buf_prd[0]);
|
||||
sata_cmd.enc_addr_low =
|
||||
lower_32_bits(phys_addr);
|
||||
sata_cmd.enc_addr_high =
|
||||
upper_32_bits(phys_addr);
|
||||
sata_cmd.enc_esgl =
|
||||
cpu_to_le32(1 << 31);
|
||||
}
|
||||
} else if (task->num_scatter == 0) {
|
||||
sata_cmd.enc_addr_low = 0;
|
||||
sata_cmd.enc_addr_high = 0;
|
||||
@ -3833,6 +3908,30 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
|
||||
sata_cmd.addr_high = upper_32_bits(dma_addr);
|
||||
sata_cmd.len = cpu_to_le32(task->total_xfer_len);
|
||||
sata_cmd.esgl = 0;
|
||||
/* Check 4G Boundary */
|
||||
start_addr = cpu_to_le64(dma_addr);
|
||||
end_addr = (start_addr + sata_cmd.len) - 1;
|
||||
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
|
||||
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
|
||||
if (end_addr_high != sata_cmd.addr_high) {
|
||||
PM8001_FAIL_DBG(pm8001_ha,
|
||||
pm8001_printk("The sg list address "
|
||||
"start_addr=0x%016llx data_len=0x%x"
|
||||
"end_addr_high=0x%08x end_addr_low="
|
||||
"0x%08x has crossed 4G boundary\n",
|
||||
start_addr, sata_cmd.len,
|
||||
end_addr_high, end_addr_low));
|
||||
pm8001_chip_make_sg(task->scatter, 1,
|
||||
ccb->buf_prd);
|
||||
phys_addr = ccb->ccb_dma_handle +
|
||||
offsetof(struct pm8001_ccb_info,
|
||||
buf_prd[0]);
|
||||
sata_cmd.addr_low =
|
||||
lower_32_bits(phys_addr);
|
||||
sata_cmd.addr_high =
|
||||
upper_32_bits(phys_addr);
|
||||
sata_cmd.esgl = cpu_to_le32(1 << 31);
|
||||
}
|
||||
} else if (task->num_scatter == 0) {
|
||||
sata_cmd.addr_low = 0;
|
||||
sata_cmd.addr_high = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user