X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_iocb.c;h=5489d5024673a326b5345f5545151a7dab37a533;hb=9b610fda0df5d0f0b0c64242e37441ad1b384aac;hp=c5b3c610a32a2968219ca29c8a572cc35b0ac605;hpb=78cc3b78c4208d28e7f4ecded82e238224ed4d1c;p=linux-2.6 diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c5b3c610a3..5489d50246 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation + * Copyright (c) 2003-2008 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ @@ -11,9 +11,6 @@ #include -static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd); -static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *); -static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *); static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha); static void qla2x00_isp_cmd(scsi_qla_host_t *ha); @@ -155,6 +152,8 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, uint32_t *cur_dsd; scsi_qla_host_t *ha; struct scsi_cmnd *cmd; + struct scatterlist *sg; + int i; cmd = sp->cmd; @@ -163,7 +162,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, __constant_cpu_to_le32(COMMAND_TYPE); /* No data transfer */ - if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { cmd_pkt->byte_count = __constant_cpu_to_le32(0); return; } @@ -177,35 +176,23 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; /* Load data segments */ - if (cmd->use_sg != 0) { - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - end_seg = cur_seg + tot_dsds; - while (cur_seg < end_seg) { - cont_entry_t *cont_pkt; - - /* Allocate additional continuation packets? */ - if (avail_dsds == 0) { - /* - * Seven DSDs are available in the Continuation - * Type 0 IOCB. - */ - cont_pkt = qla2x00_prep_cont_type0_iocb(ha); - cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address; - avail_dsds = 7; - } - - *cur_dsd++ = cpu_to_le32(sg_dma_address(cur_seg)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); - avail_dsds--; - - cur_seg++; + scsi_for_each_sg(cmd, sg, tot_dsds, i) { + cont_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Seven DSDs are available in the Continuation + * Type 0 IOCB. + */ + cont_pkt = qla2x00_prep_cont_type0_iocb(ha); + cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address; + avail_dsds = 7; } - } else { - *cur_dsd++ = cpu_to_le32(sp->dma_handle); - *cur_dsd++ = cpu_to_le32(cmd->request_bufflen); + + *cur_dsd++ = cpu_to_le32(sg_dma_address(sg)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; } } @@ -224,6 +211,8 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, uint32_t *cur_dsd; scsi_qla_host_t *ha; struct scsi_cmnd *cmd; + struct scatterlist *sg; + int i; cmd = sp->cmd; @@ -232,7 +221,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, __constant_cpu_to_le32(COMMAND_A64_TYPE); /* No data transfer */ - if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { cmd_pkt->byte_count = __constant_cpu_to_le32(0); return; } @@ -246,39 +235,26 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; /* Load data segments */ - if (cmd->use_sg != 0) { - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - end_seg = cur_seg + tot_dsds; - while (cur_seg < end_seg) { - dma_addr_t sle_dma; - cont_a64_entry_t *cont_pkt; - - /* Allocate additional continuation packets? */ - if (avail_dsds == 0) { - /* - * Five DSDs are available in the Continuation - * Type 1 IOCB. - */ - cont_pkt = qla2x00_prep_cont_type1_iocb(ha); - cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; - avail_dsds = 5; - } - - sle_dma = sg_dma_address(cur_seg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); - avail_dsds--; - - cur_seg++; + scsi_for_each_sg(cmd, sg, tot_dsds, i) { + dma_addr_t sle_dma; + cont_a64_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Five DSDs are available in the Continuation + * Type 1 IOCB. + */ + cont_pkt = qla2x00_prep_cont_type1_iocb(ha); + cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; + avail_dsds = 5; } - } else { - *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle)); - *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle)); - *cur_dsd++ = cpu_to_le32(cmd->request_bufflen); + + sle_dma = sg_dma_address(sg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; } } @@ -291,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, int qla2x00_start_scsi(srb_t *sp) { - int ret; + int ret, nseg; unsigned long flags; scsi_qla_host_t *ha; struct scsi_cmnd *cmd; @@ -299,7 +275,6 @@ qla2x00_start_scsi(srb_t *sp) uint32_t index; uint32_t handle; cmd_entry_t *cmd_pkt; - struct scatterlist *sg; uint16_t cnt; uint16_t req_cnt; uint16_t tot_dsds; @@ -330,33 +305,25 @@ qla2x00_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ - if (cmd->use_sg) { - sg = (struct scatterlist *) cmd->request_buffer; - tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - if (tot_dsds == 0) - goto queuing_error; - } else if (cmd->request_bufflen) { - dma_addr_t req_dma; - - req_dma = pci_map_single(ha->pdev, cmd->request_buffer, - cmd->request_bufflen, cmd->sc_data_direction); - if (dma_mapping_error(req_dma)) + if (scsi_sg_count(cmd)) { + nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), + scsi_sg_count(cmd), cmd->sc_data_direction); + if (unlikely(!nseg)) goto queuing_error; + } else + nseg = 0; - sp->dma_handle = req_dma; - tot_dsds = 1; - } + tot_dsds = nseg; /* Calculate the number of request entries needed. */ - req_cnt = ha->isp_ops.calc_req_entries(tot_dsds); + req_cnt = ha->isp_ops->calc_req_entries(tot_dsds); if (ha->req_q_cnt < (req_cnt + 2)) { cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); if (ha->req_ring_index < cnt) @@ -391,10 +358,10 @@ qla2x00_start_scsi(srb_t *sp) /* Load SCSI command packet. */ memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len); - cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); /* Build IOCB segments */ - ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds); + ha->isp_ops->build_iocbs(sp, cmd_pkt, tot_dsds); /* Set total data segment count. */ cmd_pkt->entry_count = (uint8_t)req_cnt; @@ -423,14 +390,9 @@ qla2x00_start_scsi(srb_t *sp) return (QLA_SUCCESS); queuing_error: - if (cmd->use_sg && tot_dsds) { - sg = (struct scatterlist *) cmd->request_buffer; - pci_unmap_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - } else if (tot_dsds) { - pci_unmap_single(ha->pdev, sp->dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); - } + if (tot_dsds) + scsi_dma_unmap(cmd); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return (QLA_FUNCTION_FAILED); @@ -453,9 +415,10 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, { mrk_entry_t *mrk; struct mrk_entry_24xx *mrk24; + scsi_qla_host_t *pha = to_qla_parent(ha); mrk24 = NULL; - mrk = (mrk_entry_t *)qla2x00_req_pkt(ha); + mrk = (mrk_entry_t *)qla2x00_req_pkt(pha); if (mrk == NULL) { DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", __func__, ha->host_no)); @@ -466,12 +429,13 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->lun[1] = LSB(lun); mrk24->lun[2] = MSB(lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); + mrk24->vp_index = ha->vp_idx; } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16(lun); @@ -479,7 +443,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, } wmb(); - qla2x00_isp_cmd(ha); + qla2x00_isp_cmd(pha); return (QLA_SUCCESS); } @@ -520,7 +484,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) for (timer = HZ; timer; timer--) { if ((req_cnt + 2) >= ha->req_q_cnt) { /* Calculate number of free request entries. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) cnt = (uint16_t)RD_REG_DWORD( ®->isp24.req_q_out); else @@ -558,7 +522,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) /* Check for pending interrupts. */ /* During init we issue marker directly */ - if (!ha->marker_needed) + if (!ha->marker_needed && !ha->flags.init_done) qla2x00_poll(ha); spin_lock_irq(&ha->hardware_lock); @@ -594,7 +558,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) ha->request_ring_ptr++; /* Set chip new ring index. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); RD_REG_DWORD_RELAXED(®->isp24.req_q_in); } else { @@ -642,6 +606,8 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, uint32_t *cur_dsd; scsi_qla_host_t *ha; struct scsi_cmnd *cmd; + struct scatterlist *sg; + int i; cmd = sp->cmd; @@ -650,7 +616,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, __constant_cpu_to_le32(COMMAND_TYPE_7); /* No data transfer */ - if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { cmd_pkt->byte_count = __constant_cpu_to_le32(0); return; } @@ -670,39 +636,27 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; /* Load data segments */ - if (cmd->use_sg != 0) { - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - end_seg = cur_seg + tot_dsds; - while (cur_seg < end_seg) { - dma_addr_t sle_dma; - cont_a64_entry_t *cont_pkt; - - /* Allocate additional continuation packets? */ - if (avail_dsds == 0) { - /* - * Five DSDs are available in the Continuation - * Type 1 IOCB. - */ - cont_pkt = qla2x00_prep_cont_type1_iocb(ha); - cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; - avail_dsds = 5; - } - - sle_dma = sg_dma_address(cur_seg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); - avail_dsds--; - - cur_seg++; + + scsi_for_each_sg(cmd, sg, tot_dsds, i) { + dma_addr_t sle_dma; + cont_a64_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Five DSDs are available in the Continuation + * Type 1 IOCB. + */ + cont_pkt = qla2x00_prep_cont_type1_iocb(ha); + cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; + avail_dsds = 5; } - } else { - *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle)); - *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle)); - *cur_dsd++ = cpu_to_le32(cmd->request_bufflen); + + sle_dma = sg_dma_address(sg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; } } @@ -716,7 +670,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, int qla24xx_start_scsi(srb_t *sp) { - int ret; + int ret, nseg; unsigned long flags; scsi_qla_host_t *ha; struct scsi_cmnd *cmd; @@ -724,7 +678,6 @@ qla24xx_start_scsi(srb_t *sp) uint32_t index; uint32_t handle; struct cmd_type_7 *cmd_pkt; - struct scatterlist *sg; uint16_t cnt; uint16_t req_cnt; uint16_t tot_dsds; @@ -755,30 +708,22 @@ qla24xx_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) goto queuing_error; /* Map the sg table so we have an accurate count of sg entries needed */ - if (cmd->use_sg) { - sg = (struct scatterlist *) cmd->request_buffer; - tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - if (tot_dsds == 0) - goto queuing_error; - } else if (cmd->request_bufflen) { - dma_addr_t req_dma; - - req_dma = pci_map_single(ha->pdev, cmd->request_buffer, - cmd->request_bufflen, cmd->sc_data_direction); - if (dma_mapping_error(req_dma)) + if (scsi_sg_count(cmd)) { + nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), + scsi_sg_count(cmd), cmd->sc_data_direction); + if (unlikely(!nseg)) goto queuing_error; + } else + nseg = 0; - sp->dma_handle = req_dma; - tot_dsds = 1; - } + tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(tot_dsds); if (ha->req_q_cnt < (req_cnt + 2)) { @@ -813,6 +758,7 @@ qla24xx_start_scsi(srb_t *sp) cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; + cmd_pkt->vp_index = sp->fcport->vp_idx; int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); @@ -821,7 +767,7 @@ qla24xx_start_scsi(srb_t *sp) memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb)); - cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); + cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); /* Build IOCB segments */ qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds); @@ -853,14 +799,9 @@ qla24xx_start_scsi(srb_t *sp) return QLA_SUCCESS; queuing_error: - if (cmd->use_sg && tot_dsds) { - sg = (struct scatterlist *) cmd->request_buffer; - pci_unmap_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - } else if (tot_dsds) { - pci_unmap_single(ha->pdev, sp->dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); - } + if (tot_dsds) + scsi_dma_unmap(cmd); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_FUNCTION_FAILED;