qla1280: sg chaining support
Interesting hardware setup... Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
parent
b0f655d0ef
commit
a044189137
1 changed files with 37 additions and 29 deletions
|
@ -2775,7 +2775,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
struct device_reg __iomem *reg = ha->iobase;
|
struct device_reg __iomem *reg = ha->iobase;
|
||||||
struct scsi_cmnd *cmd = sp->cmd;
|
struct scsi_cmnd *cmd = sp->cmd;
|
||||||
cmd_a64_entry_t *pkt;
|
cmd_a64_entry_t *pkt;
|
||||||
struct scatterlist *sg = NULL;
|
struct scatterlist *sg = NULL, *s;
|
||||||
__le32 *dword_ptr;
|
__le32 *dword_ptr;
|
||||||
dma_addr_t dma_handle;
|
dma_addr_t dma_handle;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
@ -2889,13 +2889,16 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
* Load data segments.
|
* Load data segments.
|
||||||
*/
|
*/
|
||||||
if (seg_cnt) { /* If data transfer. */
|
if (seg_cnt) { /* If data transfer. */
|
||||||
|
int remseg = seg_cnt;
|
||||||
/* Setup packet address segment pointer. */
|
/* Setup packet address segment pointer. */
|
||||||
dword_ptr = (u32 *)&pkt->dseg_0_address;
|
dword_ptr = (u32 *)&pkt->dseg_0_address;
|
||||||
|
|
||||||
if (cmd->use_sg) { /* If scatter gather */
|
if (cmd->use_sg) { /* If scatter gather */
|
||||||
/* Load command entry data segments. */
|
/* Load command entry data segments. */
|
||||||
for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) {
|
for_each_sg(sg, s, seg_cnt, cnt) {
|
||||||
dma_handle = sg_dma_address(sg);
|
if (cnt == 2)
|
||||||
|
break;
|
||||||
|
dma_handle = sg_dma_address(s);
|
||||||
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
|
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
|
||||||
if (ha->flags.use_pci_vchannel)
|
if (ha->flags.use_pci_vchannel)
|
||||||
sn_pci_set_vchan(ha->pdev,
|
sn_pci_set_vchan(ha->pdev,
|
||||||
|
@ -2906,12 +2909,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
cpu_to_le32(pci_dma_lo32(dma_handle));
|
cpu_to_le32(pci_dma_lo32(dma_handle));
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(pci_dma_hi32(dma_handle));
|
cpu_to_le32(pci_dma_hi32(dma_handle));
|
||||||
*dword_ptr++ = cpu_to_le32(sg_dma_len(sg));
|
*dword_ptr++ = cpu_to_le32(sg_dma_len(s));
|
||||||
sg++;
|
|
||||||
dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n",
|
dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n",
|
||||||
cpu_to_le32(pci_dma_hi32(dma_handle)),
|
cpu_to_le32(pci_dma_hi32(dma_handle)),
|
||||||
cpu_to_le32(pci_dma_lo32(dma_handle)),
|
cpu_to_le32(pci_dma_lo32(dma_handle)),
|
||||||
cpu_to_le32(sg_dma_len(sg)));
|
cpu_to_le32(sg_dma_len(sg_next(s))));
|
||||||
|
remseg--;
|
||||||
}
|
}
|
||||||
dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather "
|
dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather "
|
||||||
"command packet data - b %i, t %i, l %i \n",
|
"command packet data - b %i, t %i, l %i \n",
|
||||||
|
@ -2926,7 +2929,9 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
dprintk(3, "S/G Building Continuation...seg_cnt=0x%x "
|
dprintk(3, "S/G Building Continuation...seg_cnt=0x%x "
|
||||||
"remains\n", seg_cnt);
|
"remains\n", seg_cnt);
|
||||||
|
|
||||||
while (seg_cnt > 0) {
|
while (remseg > 0) {
|
||||||
|
/* Update sg start */
|
||||||
|
sg = s;
|
||||||
/* Adjust ring index. */
|
/* Adjust ring index. */
|
||||||
ha->req_ring_index++;
|
ha->req_ring_index++;
|
||||||
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
|
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
|
||||||
|
@ -2952,9 +2957,10 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
(u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address;
|
(u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address;
|
||||||
|
|
||||||
/* Load continuation entry data segments. */
|
/* Load continuation entry data segments. */
|
||||||
for (cnt = 0; cnt < 5 && seg_cnt;
|
for_each_sg(sg, s, remseg, cnt) {
|
||||||
cnt++, seg_cnt--) {
|
if (cnt == 5)
|
||||||
dma_handle = sg_dma_address(sg);
|
break;
|
||||||
|
dma_handle = sg_dma_address(s);
|
||||||
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
|
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
|
||||||
if (ha->flags.use_pci_vchannel)
|
if (ha->flags.use_pci_vchannel)
|
||||||
sn_pci_set_vchan(ha->pdev,
|
sn_pci_set_vchan(ha->pdev,
|
||||||
|
@ -2966,12 +2972,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(pci_dma_hi32(dma_handle));
|
cpu_to_le32(pci_dma_hi32(dma_handle));
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(sg_dma_len(sg));
|
cpu_to_le32(sg_dma_len(s));
|
||||||
dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n",
|
dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n",
|
||||||
cpu_to_le32(pci_dma_hi32(dma_handle)),
|
cpu_to_le32(pci_dma_hi32(dma_handle)),
|
||||||
cpu_to_le32(pci_dma_lo32(dma_handle)),
|
cpu_to_le32(pci_dma_lo32(dma_handle)),
|
||||||
cpu_to_le32(sg_dma_len(sg)));
|
cpu_to_le32(sg_dma_len(s)));
|
||||||
sg++;
|
remseg--;
|
||||||
}
|
}
|
||||||
dprintk(5, "qla1280_64bit_start_scsi: "
|
dprintk(5, "qla1280_64bit_start_scsi: "
|
||||||
"continuation packet data - b %i, t "
|
"continuation packet data - b %i, t "
|
||||||
|
@ -3062,7 +3068,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
struct device_reg __iomem *reg = ha->iobase;
|
struct device_reg __iomem *reg = ha->iobase;
|
||||||
struct scsi_cmnd *cmd = sp->cmd;
|
struct scsi_cmnd *cmd = sp->cmd;
|
||||||
struct cmd_entry *pkt;
|
struct cmd_entry *pkt;
|
||||||
struct scatterlist *sg = NULL;
|
struct scatterlist *sg = NULL, *s;
|
||||||
__le32 *dword_ptr;
|
__le32 *dword_ptr;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
@ -3188,6 +3194,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
* Load data segments.
|
* Load data segments.
|
||||||
*/
|
*/
|
||||||
if (seg_cnt) {
|
if (seg_cnt) {
|
||||||
|
int remseg = seg_cnt;
|
||||||
/* Setup packet address segment pointer. */
|
/* Setup packet address segment pointer. */
|
||||||
dword_ptr = &pkt->dseg_0_address;
|
dword_ptr = &pkt->dseg_0_address;
|
||||||
|
|
||||||
|
@ -3196,22 +3203,25 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
qla1280_dump_buffer(1, (char *)sg, 4 * 16);
|
qla1280_dump_buffer(1, (char *)sg, 4 * 16);
|
||||||
|
|
||||||
/* Load command entry data segments. */
|
/* Load command entry data segments. */
|
||||||
for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) {
|
for_each_sg(sg, s, seg_cnt, cnt) {
|
||||||
|
if (cnt == 4)
|
||||||
|
break;
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
|
cpu_to_le32(pci_dma_lo32(sg_dma_address(s)));
|
||||||
*dword_ptr++ =
|
*dword_ptr++ = cpu_to_le32(sg_dma_len(s));
|
||||||
cpu_to_le32(sg_dma_len(sg));
|
|
||||||
dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n",
|
dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n",
|
||||||
(pci_dma_lo32(sg_dma_address(sg))),
|
(pci_dma_lo32(sg_dma_address(s))),
|
||||||
(sg_dma_len(sg)));
|
(sg_dma_len(s)));
|
||||||
sg++;
|
remseg--;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Build continuation packets.
|
* Build continuation packets.
|
||||||
*/
|
*/
|
||||||
dprintk(3, "S/G Building Continuation"
|
dprintk(3, "S/G Building Continuation"
|
||||||
"...seg_cnt=0x%x remains\n", seg_cnt);
|
"...seg_cnt=0x%x remains\n", seg_cnt);
|
||||||
while (seg_cnt > 0) {
|
while (remseg > 0) {
|
||||||
|
/* Continue from end point */
|
||||||
|
sg = s;
|
||||||
/* Adjust ring index. */
|
/* Adjust ring index. */
|
||||||
ha->req_ring_index++;
|
ha->req_ring_index++;
|
||||||
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
|
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
|
||||||
|
@ -3239,18 +3249,16 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
|
||||||
&((struct cont_entry *) pkt)->dseg_0_address;
|
&((struct cont_entry *) pkt)->dseg_0_address;
|
||||||
|
|
||||||
/* Load continuation entry data segments. */
|
/* Load continuation entry data segments. */
|
||||||
for (cnt = 0; cnt < 7 && seg_cnt;
|
for_each_sg(sg, s, remseg, cnt) {
|
||||||
cnt++, seg_cnt--) {
|
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
|
cpu_to_le32(pci_dma_lo32(sg_dma_address(s)));
|
||||||
*dword_ptr++ =
|
*dword_ptr++ =
|
||||||
cpu_to_le32(sg_dma_len(sg));
|
cpu_to_le32(sg_dma_len(s));
|
||||||
dprintk(1,
|
dprintk(1,
|
||||||
"S/G Segment Cont. phys_addr=0x%x, "
|
"S/G Segment Cont. phys_addr=0x%x, "
|
||||||
"len=0x%x\n",
|
"len=0x%x\n",
|
||||||
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
|
cpu_to_le32(pci_dma_lo32(sg_dma_address(s))),
|
||||||
cpu_to_le32(sg_dma_len(sg)));
|
cpu_to_le32(sg_dma_len(s)));
|
||||||
sg++;
|
|
||||||
}
|
}
|
||||||
dprintk(5, "qla1280_32bit_start_scsi: "
|
dprintk(5, "qla1280_32bit_start_scsi: "
|
||||||
"continuation packet data - "
|
"continuation packet data - "
|
||||||
|
|
Reference in a new issue