X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_iocb.c;h=710a88d67c60177fa025c948598c5f7e23a7f7ae;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=0baccf130294417d40a7a8981aa2179d500d9e69;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 0baccf130..710a88d67 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -17,9 +17,11 @@ * ******************************************************************************/ -#include "qla_os.h" #include "qla_def.h" +#include +#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 *); @@ -42,28 +44,6 @@ qla2x00_get_cmd_direction(struct scsi_cmnd *cmd) cflags = CF_WRITE; else if (cmd->sc_data_direction == DMA_FROM_DEVICE) cflags = CF_READ; - else { - switch (cmd->data_cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: - case WRITE_BUFFER: - case WRITE_LONG: - case WRITE_SAME: - case WRITE_VERIFY: - case WRITE_VERIFY_12: - case FORMAT_UNIT: - case SEND_VOLUME_TAG: - case MODE_SELECT: - case SEND_DIAGNOSTIC: - case MODE_SELECT_10: - cflags = CF_WRITE; - break; - default: - cflags = CF_READ; - break; - } - } return (cflags); } @@ -350,11 +330,12 @@ qla2x00_start_scsi(srb_t *sp) uint32_t *clr_ptr; uint32_t index; uint32_t handle; - uint16_t cnt; cmd_entry_t *cmd_pkt; uint32_t timeout; struct scatterlist *sg; - + uint16_t cnt; + uint16_t req_cnt; + uint16_t tot_dsds; device_reg_t *reg; /* Setup device pointers. */ @@ -372,72 +353,60 @@ qla2x00_start_scsi(srb_t *sp) ha->marker_needed = 0; } - /* Calculate number of segments and entries required. */ - if (sp->req_cnt == 0) { - sp->tot_dsds = 0; - if (cmd->use_sg) { - sg = (struct scatterlist *) cmd->request_buffer; - sp->tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - } else if (cmd->request_bufflen) { - sp->tot_dsds++; - } - sp->req_cnt = (ha->calc_request_entries)(sp->tot_dsds); - } - /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); - if (ha->req_q_cnt < (sp->req_cnt + 2)) { - /* Calculate number of free request entries */ - cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = ha->request_q_length - - (ha->req_ring_index - cnt); - } - - /* If no room for request in request ring */ - if (ha->req_q_cnt < (sp->req_cnt + 2)) { - DEBUG5(printk("scsi(%ld): in-ptr=%x req_q_cnt=%x " - "tot_dsds=%x.\n", - ha->host_no, ha->req_ring_index, ha->req_q_cnt, - sp->tot_dsds)); - - goto queuing_error; - } - /* Check for room in outstanding command list. */ handle = ha->current_outstanding_cmd; for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) { - ha->current_outstanding_cmd = handle; + if (ha->outstanding_cmds[handle] == 0) break; - } } - if (index == MAX_OUTSTANDING_COMMANDS) { - DEBUG5(printk("scsi(%ld): Unable to queue command -- NO ROOM " - "IN OUTSTANDING ARRAY (req_q_cnt=%x).\n", - ha->host_no, ha->req_q_cnt)); + if (index == MAX_OUTSTANDING_COMMANDS) goto queuing_error; + + /* Calculate the number of request entries needed. */ + req_cnt = (ha->calc_request_entries)(cmd->request->nr_hw_segments); + 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) + ha->req_q_cnt = cnt - ha->req_ring_index; + else + ha->req_q_cnt = ha->request_q_length - + (ha->req_ring_index - cnt); + } + if (ha->req_q_cnt < (req_cnt + 2)) + goto queuing_error; + + /* Finally, we have enough space, now perform mappings. */ + tot_dsds = 0; + 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) { + tot_dsds++; } + req_cnt = (ha->calc_request_entries)(tot_dsds); /* Build command packet */ + ha->current_outstanding_cmd = handle; ha->outstanding_cmds[handle] = sp; sp->ha = ha; sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; - ha->req_q_cnt -= sp->req_cnt; + ha->req_q_cnt -= req_cnt; cmd_pkt = (cmd_entry_t *)ha->request_ring_ptr; cmd_pkt->handle = handle; /* Zero out remaining portion of packet. */ clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); - cmd_pkt->dseg_count = cpu_to_le16(sp->tot_dsds); + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); /* Set target ID */ SET_TARGET_ID(ha, cmd_pkt->target, fclun->fcport->loop_id); @@ -477,10 +446,11 @@ qla2x00_start_scsi(srb_t *sp) cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen); /* Build IOCB segments */ - (ha->build_scsi_iocbs)(sp, cmd_pkt, sp->tot_dsds); + (ha->build_scsi_iocbs)(sp, cmd_pkt, tot_dsds); /* Set total data segment count. */ - cmd_pkt->entry_count = (uint8_t)sp->req_cnt; + cmd_pkt->entry_count = (uint8_t)req_cnt; + wmb(); /* Adjust ring index. */ ha->req_ring_index++; @@ -541,6 +511,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, pkt->lun = cpu_to_le16(lun); SET_TARGET_ID(ha, pkt->target, loop_id); } + wmb(); /* Issue command to ISP */ qla2x00_isp_cmd(ha);