1afaf5a2dSDavid Somayajulu /* 2afaf5a2dSDavid Somayajulu * QLogic iSCSI HBA Driver 3afaf5a2dSDavid Somayajulu * Copyright (c) 2003-2006 QLogic Corporation 4afaf5a2dSDavid Somayajulu * 5afaf5a2dSDavid Somayajulu * See LICENSE.qla4xxx for copyright and licensing details. 6afaf5a2dSDavid Somayajulu */ 7afaf5a2dSDavid Somayajulu 8afaf5a2dSDavid Somayajulu #include "ql4_def.h" 9afaf5a2dSDavid Somayajulu 10afaf5a2dSDavid Somayajulu #include <scsi/scsi_tcq.h> 11afaf5a2dSDavid Somayajulu 12afaf5a2dSDavid Somayajulu /** 13afaf5a2dSDavid Somayajulu * qla4xxx_get_req_pkt - returns a valid entry in request queue. 14afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 15afaf5a2dSDavid Somayajulu * @queue_entry: Pointer to pointer to queue entry structure 16afaf5a2dSDavid Somayajulu * 17afaf5a2dSDavid Somayajulu * This routine performs the following tasks: 18afaf5a2dSDavid Somayajulu * - returns the current request_in pointer (if queue not full) 19afaf5a2dSDavid Somayajulu * - advances the request_in pointer 20afaf5a2dSDavid Somayajulu * - checks for queue full 21afaf5a2dSDavid Somayajulu **/ 22afaf5a2dSDavid Somayajulu int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, 23afaf5a2dSDavid Somayajulu struct queue_entry **queue_entry) 24afaf5a2dSDavid Somayajulu { 25afaf5a2dSDavid Somayajulu uint16_t request_in; 26afaf5a2dSDavid Somayajulu uint8_t status = QLA_SUCCESS; 27afaf5a2dSDavid Somayajulu 28afaf5a2dSDavid Somayajulu *queue_entry = ha->request_ptr; 29afaf5a2dSDavid Somayajulu 30afaf5a2dSDavid Somayajulu /* get the latest request_in and request_out index */ 31afaf5a2dSDavid Somayajulu request_in = ha->request_in; 32afaf5a2dSDavid Somayajulu ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); 33afaf5a2dSDavid Somayajulu 34afaf5a2dSDavid Somayajulu /* Advance request queue pointer and check for queue full */ 35afaf5a2dSDavid Somayajulu if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { 36afaf5a2dSDavid Somayajulu request_in = 0; 37afaf5a2dSDavid Somayajulu ha->request_ptr = ha->request_ring; 38afaf5a2dSDavid Somayajulu } else { 39afaf5a2dSDavid Somayajulu request_in++; 40afaf5a2dSDavid Somayajulu ha->request_ptr++; 41afaf5a2dSDavid Somayajulu } 42afaf5a2dSDavid Somayajulu 43afaf5a2dSDavid Somayajulu /* request queue is full, try again later */ 44afaf5a2dSDavid Somayajulu if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { 45afaf5a2dSDavid Somayajulu /* restore request pointer */ 46afaf5a2dSDavid Somayajulu ha->request_ptr = *queue_entry; 47afaf5a2dSDavid Somayajulu status = QLA_ERROR; 48afaf5a2dSDavid Somayajulu } else { 49afaf5a2dSDavid Somayajulu ha->request_in = request_in; 50afaf5a2dSDavid Somayajulu memset(*queue_entry, 0, sizeof(**queue_entry)); 51afaf5a2dSDavid Somayajulu } 52afaf5a2dSDavid Somayajulu 53afaf5a2dSDavid Somayajulu return status; 54afaf5a2dSDavid Somayajulu } 55afaf5a2dSDavid Somayajulu 56afaf5a2dSDavid Somayajulu /** 57afaf5a2dSDavid Somayajulu * qla4xxx_send_marker_iocb - issues marker iocb to HBA 58afaf5a2dSDavid Somayajulu * @ha: Pointer to host adapter structure. 59afaf5a2dSDavid Somayajulu * @ddb_entry: Pointer to device database entry 60afaf5a2dSDavid Somayajulu * @lun: SCSI LUN 61afaf5a2dSDavid Somayajulu * @marker_type: marker identifier 62afaf5a2dSDavid Somayajulu * 63afaf5a2dSDavid Somayajulu * This routine issues a marker IOCB. 64afaf5a2dSDavid Somayajulu **/ 65afaf5a2dSDavid Somayajulu int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, 66afaf5a2dSDavid Somayajulu struct ddb_entry *ddb_entry, int lun) 67afaf5a2dSDavid Somayajulu { 68afaf5a2dSDavid Somayajulu struct marker_entry *marker_entry; 69afaf5a2dSDavid Somayajulu unsigned long flags = 0; 70afaf5a2dSDavid Somayajulu uint8_t status = QLA_SUCCESS; 71afaf5a2dSDavid Somayajulu 72afaf5a2dSDavid Somayajulu /* Acquire hardware specific lock */ 73afaf5a2dSDavid Somayajulu spin_lock_irqsave(&ha->hardware_lock, flags); 74afaf5a2dSDavid Somayajulu 75afaf5a2dSDavid Somayajulu /* Get pointer to the queue entry for the marker */ 76afaf5a2dSDavid Somayajulu if (qla4xxx_get_req_pkt(ha, (struct queue_entry **) &marker_entry) != 77afaf5a2dSDavid Somayajulu QLA_SUCCESS) { 78afaf5a2dSDavid Somayajulu status = QLA_ERROR; 79afaf5a2dSDavid Somayajulu goto exit_send_marker; 80afaf5a2dSDavid Somayajulu } 81afaf5a2dSDavid Somayajulu 82afaf5a2dSDavid Somayajulu /* Put the marker in the request queue */ 83afaf5a2dSDavid Somayajulu marker_entry->hdr.entryType = ET_MARKER; 84afaf5a2dSDavid Somayajulu marker_entry->hdr.entryCount = 1; 85afaf5a2dSDavid Somayajulu marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); 86afaf5a2dSDavid Somayajulu marker_entry->modifier = cpu_to_le16(MM_LUN_RESET); 87afaf5a2dSDavid Somayajulu int_to_scsilun(lun, &marker_entry->lun); 88afaf5a2dSDavid Somayajulu wmb(); 89afaf5a2dSDavid Somayajulu 90afaf5a2dSDavid Somayajulu /* Tell ISP it's got a new I/O request */ 91afaf5a2dSDavid Somayajulu writel(ha->request_in, &ha->reg->req_q_in); 92afaf5a2dSDavid Somayajulu readl(&ha->reg->req_q_in); 93afaf5a2dSDavid Somayajulu 94afaf5a2dSDavid Somayajulu exit_send_marker: 95afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 96afaf5a2dSDavid Somayajulu return status; 97afaf5a2dSDavid Somayajulu } 98afaf5a2dSDavid Somayajulu 99afaf5a2dSDavid Somayajulu struct continuation_t1_entry* qla4xxx_alloc_cont_entry( 100afaf5a2dSDavid Somayajulu struct scsi_qla_host *ha) 101afaf5a2dSDavid Somayajulu { 102afaf5a2dSDavid Somayajulu struct continuation_t1_entry *cont_entry; 103afaf5a2dSDavid Somayajulu 104afaf5a2dSDavid Somayajulu cont_entry = (struct continuation_t1_entry *)ha->request_ptr; 105afaf5a2dSDavid Somayajulu 106afaf5a2dSDavid Somayajulu /* Advance request queue pointer */ 107afaf5a2dSDavid Somayajulu if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { 108afaf5a2dSDavid Somayajulu ha->request_in = 0; 109afaf5a2dSDavid Somayajulu ha->request_ptr = ha->request_ring; 110afaf5a2dSDavid Somayajulu } else { 111afaf5a2dSDavid Somayajulu ha->request_in++; 112afaf5a2dSDavid Somayajulu ha->request_ptr++; 113afaf5a2dSDavid Somayajulu } 114afaf5a2dSDavid Somayajulu 115afaf5a2dSDavid Somayajulu /* Load packet defaults */ 116afaf5a2dSDavid Somayajulu cont_entry->hdr.entryType = ET_CONTINUE; 117afaf5a2dSDavid Somayajulu cont_entry->hdr.entryCount = 1; 118afaf5a2dSDavid Somayajulu cont_entry->hdr.systemDefined = (uint8_t) cpu_to_le16(ha->request_in); 119afaf5a2dSDavid Somayajulu 120afaf5a2dSDavid Somayajulu return cont_entry; 121afaf5a2dSDavid Somayajulu } 122afaf5a2dSDavid Somayajulu 123afaf5a2dSDavid Somayajulu uint16_t qla4xxx_calc_request_entries(uint16_t dsds) 124afaf5a2dSDavid Somayajulu { 125afaf5a2dSDavid Somayajulu uint16_t iocbs; 126afaf5a2dSDavid Somayajulu 127afaf5a2dSDavid Somayajulu iocbs = 1; 128afaf5a2dSDavid Somayajulu if (dsds > COMMAND_SEG) { 129afaf5a2dSDavid Somayajulu iocbs += (dsds - COMMAND_SEG) / CONTINUE_SEG; 130afaf5a2dSDavid Somayajulu if ((dsds - COMMAND_SEG) % CONTINUE_SEG) 131afaf5a2dSDavid Somayajulu iocbs++; 132afaf5a2dSDavid Somayajulu } 133afaf5a2dSDavid Somayajulu return iocbs; 134afaf5a2dSDavid Somayajulu } 135afaf5a2dSDavid Somayajulu 136afaf5a2dSDavid Somayajulu void qla4xxx_build_scsi_iocbs(struct srb *srb, 137afaf5a2dSDavid Somayajulu struct command_t3_entry *cmd_entry, 138afaf5a2dSDavid Somayajulu uint16_t tot_dsds) 139afaf5a2dSDavid Somayajulu { 140afaf5a2dSDavid Somayajulu struct scsi_qla_host *ha; 141afaf5a2dSDavid Somayajulu uint16_t avail_dsds; 142afaf5a2dSDavid Somayajulu struct data_seg_a64 *cur_dsd; 143afaf5a2dSDavid Somayajulu struct scsi_cmnd *cmd; 144afaf5a2dSDavid Somayajulu 145afaf5a2dSDavid Somayajulu cmd = srb->cmd; 146afaf5a2dSDavid Somayajulu ha = srb->ha; 147afaf5a2dSDavid Somayajulu 148afaf5a2dSDavid Somayajulu if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) { 149afaf5a2dSDavid Somayajulu /* No data being transferred */ 150afaf5a2dSDavid Somayajulu cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0); 151afaf5a2dSDavid Somayajulu return; 152afaf5a2dSDavid Somayajulu } 153afaf5a2dSDavid Somayajulu 154afaf5a2dSDavid Somayajulu avail_dsds = COMMAND_SEG; 155afaf5a2dSDavid Somayajulu cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]); 156afaf5a2dSDavid Somayajulu 157afaf5a2dSDavid Somayajulu /* Load data segments */ 158afaf5a2dSDavid Somayajulu if (cmd->use_sg) { 159afaf5a2dSDavid Somayajulu struct scatterlist *cur_seg; 160afaf5a2dSDavid Somayajulu struct scatterlist *end_seg; 161afaf5a2dSDavid Somayajulu 162afaf5a2dSDavid Somayajulu cur_seg = (struct scatterlist *)cmd->request_buffer; 163afaf5a2dSDavid Somayajulu end_seg = cur_seg + tot_dsds; 164afaf5a2dSDavid Somayajulu while (cur_seg < end_seg) { 165afaf5a2dSDavid Somayajulu dma_addr_t sle_dma; 166afaf5a2dSDavid Somayajulu 167afaf5a2dSDavid Somayajulu /* Allocate additional continuation packets? */ 168afaf5a2dSDavid Somayajulu if (avail_dsds == 0) { 169afaf5a2dSDavid Somayajulu struct continuation_t1_entry *cont_entry; 170afaf5a2dSDavid Somayajulu 171afaf5a2dSDavid Somayajulu cont_entry = qla4xxx_alloc_cont_entry(ha); 172afaf5a2dSDavid Somayajulu cur_dsd = 173afaf5a2dSDavid Somayajulu (struct data_seg_a64 *) 174afaf5a2dSDavid Somayajulu &cont_entry->dataseg[0]; 175afaf5a2dSDavid Somayajulu avail_dsds = CONTINUE_SEG; 176afaf5a2dSDavid Somayajulu } 177afaf5a2dSDavid Somayajulu 178afaf5a2dSDavid Somayajulu sle_dma = sg_dma_address(cur_seg); 179afaf5a2dSDavid Somayajulu cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma)); 180afaf5a2dSDavid Somayajulu cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma)); 181afaf5a2dSDavid Somayajulu cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg)); 182afaf5a2dSDavid Somayajulu avail_dsds--; 183afaf5a2dSDavid Somayajulu 184afaf5a2dSDavid Somayajulu cur_dsd++; 185afaf5a2dSDavid Somayajulu cur_seg++; 186afaf5a2dSDavid Somayajulu } 187afaf5a2dSDavid Somayajulu } else { 188afaf5a2dSDavid Somayajulu cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle)); 189afaf5a2dSDavid Somayajulu cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle)); 190afaf5a2dSDavid Somayajulu cur_dsd->count = cpu_to_le32(cmd->request_bufflen); 191afaf5a2dSDavid Somayajulu } 192afaf5a2dSDavid Somayajulu } 193afaf5a2dSDavid Somayajulu 194afaf5a2dSDavid Somayajulu /** 195afaf5a2dSDavid Somayajulu * qla4xxx_send_command_to_isp - issues command to HBA 196afaf5a2dSDavid Somayajulu * @ha: pointer to host adapter structure. 197afaf5a2dSDavid Somayajulu * @srb: pointer to SCSI Request Block to be sent to ISP 198afaf5a2dSDavid Somayajulu * 199afaf5a2dSDavid Somayajulu * This routine is called by qla4xxx_queuecommand to build an ISP 200afaf5a2dSDavid Somayajulu * command and pass it to the ISP for execution. 201afaf5a2dSDavid Somayajulu **/ 202afaf5a2dSDavid Somayajulu int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) 203afaf5a2dSDavid Somayajulu { 204afaf5a2dSDavid Somayajulu struct scsi_cmnd *cmd = srb->cmd; 205afaf5a2dSDavid Somayajulu struct ddb_entry *ddb_entry; 206afaf5a2dSDavid Somayajulu struct command_t3_entry *cmd_entry; 207afaf5a2dSDavid Somayajulu struct scatterlist *sg = NULL; 208afaf5a2dSDavid Somayajulu 209afaf5a2dSDavid Somayajulu uint16_t tot_dsds; 210afaf5a2dSDavid Somayajulu uint16_t req_cnt; 211afaf5a2dSDavid Somayajulu 212afaf5a2dSDavid Somayajulu unsigned long flags; 213afaf5a2dSDavid Somayajulu uint16_t cnt; 214afaf5a2dSDavid Somayajulu uint32_t index; 215afaf5a2dSDavid Somayajulu char tag[2]; 216afaf5a2dSDavid Somayajulu 217afaf5a2dSDavid Somayajulu /* Get real lun and adapter */ 218afaf5a2dSDavid Somayajulu ddb_entry = srb->ddb; 219afaf5a2dSDavid Somayajulu 220afaf5a2dSDavid Somayajulu /* Send marker(s) if needed. */ 221afaf5a2dSDavid Somayajulu if (ha->marker_needed == 1) { 222afaf5a2dSDavid Somayajulu if (qla4xxx_send_marker_iocb(ha, ddb_entry, 223afaf5a2dSDavid Somayajulu cmd->device->lun) != QLA_SUCCESS) 224afaf5a2dSDavid Somayajulu return QLA_ERROR; 225afaf5a2dSDavid Somayajulu 226afaf5a2dSDavid Somayajulu ha->marker_needed = 0; 227afaf5a2dSDavid Somayajulu } 228afaf5a2dSDavid Somayajulu tot_dsds = 0; 229afaf5a2dSDavid Somayajulu 230afaf5a2dSDavid Somayajulu /* Acquire hardware specific lock */ 231afaf5a2dSDavid Somayajulu spin_lock_irqsave(&ha->hardware_lock, flags); 232afaf5a2dSDavid Somayajulu 233afaf5a2dSDavid Somayajulu index = (uint32_t)cmd->request->tag; 234afaf5a2dSDavid Somayajulu 235afaf5a2dSDavid Somayajulu /* Calculate the number of request entries needed. */ 236afaf5a2dSDavid Somayajulu if (cmd->use_sg) { 237afaf5a2dSDavid Somayajulu sg = (struct scatterlist *)cmd->request_buffer; 238afaf5a2dSDavid Somayajulu tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg, 239afaf5a2dSDavid Somayajulu cmd->sc_data_direction); 240afaf5a2dSDavid Somayajulu if (tot_dsds == 0) 241afaf5a2dSDavid Somayajulu goto queuing_error; 242afaf5a2dSDavid Somayajulu } else if (cmd->request_bufflen) { 243afaf5a2dSDavid Somayajulu dma_addr_t req_dma; 244afaf5a2dSDavid Somayajulu 245afaf5a2dSDavid Somayajulu req_dma = pci_map_single(ha->pdev, cmd->request_buffer, 246afaf5a2dSDavid Somayajulu cmd->request_bufflen, 247afaf5a2dSDavid Somayajulu cmd->sc_data_direction); 248afaf5a2dSDavid Somayajulu if (dma_mapping_error(req_dma)) 249afaf5a2dSDavid Somayajulu goto queuing_error; 250afaf5a2dSDavid Somayajulu 251afaf5a2dSDavid Somayajulu srb->dma_handle = req_dma; 252afaf5a2dSDavid Somayajulu tot_dsds = 1; 253afaf5a2dSDavid Somayajulu } 254afaf5a2dSDavid Somayajulu req_cnt = qla4xxx_calc_request_entries(tot_dsds); 255afaf5a2dSDavid Somayajulu 256afaf5a2dSDavid Somayajulu if (ha->req_q_count < (req_cnt + 2)) { 257afaf5a2dSDavid Somayajulu cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); 258afaf5a2dSDavid Somayajulu if (ha->request_in < cnt) 259afaf5a2dSDavid Somayajulu ha->req_q_count = cnt - ha->request_in; 260afaf5a2dSDavid Somayajulu else 261afaf5a2dSDavid Somayajulu ha->req_q_count = REQUEST_QUEUE_DEPTH - 262afaf5a2dSDavid Somayajulu (ha->request_in - cnt); 263afaf5a2dSDavid Somayajulu } 264afaf5a2dSDavid Somayajulu 265afaf5a2dSDavid Somayajulu if (ha->req_q_count < (req_cnt + 2)) 266afaf5a2dSDavid Somayajulu goto queuing_error; 267afaf5a2dSDavid Somayajulu 268afaf5a2dSDavid Somayajulu /* total iocbs active */ 269afaf5a2dSDavid Somayajulu if ((ha->iocb_cnt + req_cnt) >= REQUEST_QUEUE_DEPTH) 270afaf5a2dSDavid Somayajulu goto queuing_error; 271afaf5a2dSDavid Somayajulu 272afaf5a2dSDavid Somayajulu /* Build command packet */ 273afaf5a2dSDavid Somayajulu cmd_entry = (struct command_t3_entry *) ha->request_ptr; 274afaf5a2dSDavid Somayajulu memset(cmd_entry, 0, sizeof(struct command_t3_entry)); 275afaf5a2dSDavid Somayajulu cmd_entry->hdr.entryType = ET_COMMAND; 276afaf5a2dSDavid Somayajulu cmd_entry->handle = cpu_to_le32(index); 277afaf5a2dSDavid Somayajulu cmd_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index); 278afaf5a2dSDavid Somayajulu cmd_entry->connection_id = cpu_to_le16(ddb_entry->connection_id); 279afaf5a2dSDavid Somayajulu 280afaf5a2dSDavid Somayajulu int_to_scsilun(cmd->device->lun, &cmd_entry->lun); 281afaf5a2dSDavid Somayajulu cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn); 282afaf5a2dSDavid Somayajulu cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen); 283afaf5a2dSDavid Somayajulu memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len); 284afaf5a2dSDavid Somayajulu cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds); 285afaf5a2dSDavid Somayajulu cmd_entry->hdr.entryCount = req_cnt; 286afaf5a2dSDavid Somayajulu 287afaf5a2dSDavid Somayajulu /* Set data transfer direction control flags 288afaf5a2dSDavid Somayajulu * NOTE: Look at data_direction bits iff there is data to be 289afaf5a2dSDavid Somayajulu * transferred, as the data direction bit is sometimed filled 290afaf5a2dSDavid Somayajulu * in when there is no data to be transferred */ 291afaf5a2dSDavid Somayajulu cmd_entry->control_flags = CF_NO_DATA; 292afaf5a2dSDavid Somayajulu if (cmd->request_bufflen) { 293afaf5a2dSDavid Somayajulu if (cmd->sc_data_direction == DMA_TO_DEVICE) 294afaf5a2dSDavid Somayajulu cmd_entry->control_flags = CF_WRITE; 295afaf5a2dSDavid Somayajulu else if (cmd->sc_data_direction == DMA_FROM_DEVICE) 296afaf5a2dSDavid Somayajulu cmd_entry->control_flags = CF_READ; 297afaf5a2dSDavid Somayajulu } 298afaf5a2dSDavid Somayajulu 299afaf5a2dSDavid Somayajulu /* Set tagged queueing control flags */ 300afaf5a2dSDavid Somayajulu cmd_entry->control_flags |= CF_SIMPLE_TAG; 301afaf5a2dSDavid Somayajulu if (scsi_populate_tag_msg(cmd, tag)) 302afaf5a2dSDavid Somayajulu switch (tag[0]) { 303afaf5a2dSDavid Somayajulu case MSG_HEAD_TAG: 304afaf5a2dSDavid Somayajulu cmd_entry->control_flags |= CF_HEAD_TAG; 305afaf5a2dSDavid Somayajulu break; 306afaf5a2dSDavid Somayajulu case MSG_ORDERED_TAG: 307afaf5a2dSDavid Somayajulu cmd_entry->control_flags |= CF_ORDERED_TAG; 308afaf5a2dSDavid Somayajulu break; 309afaf5a2dSDavid Somayajulu } 310afaf5a2dSDavid Somayajulu 311afaf5a2dSDavid Somayajulu 312afaf5a2dSDavid Somayajulu /* Advance request queue pointer */ 313afaf5a2dSDavid Somayajulu ha->request_in++; 314afaf5a2dSDavid Somayajulu if (ha->request_in == REQUEST_QUEUE_DEPTH) { 315afaf5a2dSDavid Somayajulu ha->request_in = 0; 316afaf5a2dSDavid Somayajulu ha->request_ptr = ha->request_ring; 317afaf5a2dSDavid Somayajulu } else 318afaf5a2dSDavid Somayajulu ha->request_ptr++; 319afaf5a2dSDavid Somayajulu 320afaf5a2dSDavid Somayajulu 321afaf5a2dSDavid Somayajulu qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); 322afaf5a2dSDavid Somayajulu wmb(); 323afaf5a2dSDavid Somayajulu 324afaf5a2dSDavid Somayajulu /* 325afaf5a2dSDavid Somayajulu * Check to see if adapter is online before placing request on 326afaf5a2dSDavid Somayajulu * request queue. If a reset occurs and a request is in the queue, 327afaf5a2dSDavid Somayajulu * the firmware will still attempt to process the request, retrieving 328afaf5a2dSDavid Somayajulu * garbage for pointers. 329afaf5a2dSDavid Somayajulu */ 330afaf5a2dSDavid Somayajulu if (!test_bit(AF_ONLINE, &ha->flags)) { 331afaf5a2dSDavid Somayajulu DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " 332afaf5a2dSDavid Somayajulu "Do not issue command.\n", 333afaf5a2dSDavid Somayajulu ha->host_no, __func__)); 334afaf5a2dSDavid Somayajulu goto queuing_error; 335afaf5a2dSDavid Somayajulu } 336afaf5a2dSDavid Somayajulu 337afaf5a2dSDavid Somayajulu srb->cmd->host_scribble = (unsigned char *)srb; 338afaf5a2dSDavid Somayajulu 339afaf5a2dSDavid Somayajulu /* update counters */ 340afaf5a2dSDavid Somayajulu srb->state = SRB_ACTIVE_STATE; 341afaf5a2dSDavid Somayajulu srb->flags |= SRB_DMA_VALID; 342afaf5a2dSDavid Somayajulu 343afaf5a2dSDavid Somayajulu /* Track IOCB used */ 344afaf5a2dSDavid Somayajulu ha->iocb_cnt += req_cnt; 345afaf5a2dSDavid Somayajulu srb->iocb_cnt = req_cnt; 346afaf5a2dSDavid Somayajulu ha->req_q_count -= req_cnt; 347afaf5a2dSDavid Somayajulu 348afaf5a2dSDavid Somayajulu /* Debug print statements */ 349afaf5a2dSDavid Somayajulu writel(ha->request_in, &ha->reg->req_q_in); 350afaf5a2dSDavid Somayajulu readl(&ha->reg->req_q_in); 351afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 352afaf5a2dSDavid Somayajulu 353afaf5a2dSDavid Somayajulu return QLA_SUCCESS; 354afaf5a2dSDavid Somayajulu 355afaf5a2dSDavid Somayajulu queuing_error: 356afaf5a2dSDavid Somayajulu 357afaf5a2dSDavid Somayajulu if (cmd->use_sg && tot_dsds) { 358afaf5a2dSDavid Somayajulu sg = (struct scatterlist *) cmd->request_buffer; 359afaf5a2dSDavid Somayajulu pci_unmap_sg(ha->pdev, sg, cmd->use_sg, 360afaf5a2dSDavid Somayajulu cmd->sc_data_direction); 361afaf5a2dSDavid Somayajulu } else if (tot_dsds) 362afaf5a2dSDavid Somayajulu pci_unmap_single(ha->pdev, srb->dma_handle, 363afaf5a2dSDavid Somayajulu cmd->request_bufflen, cmd->sc_data_direction); 364afaf5a2dSDavid Somayajulu spin_unlock_irqrestore(&ha->hardware_lock, flags); 365afaf5a2dSDavid Somayajulu 366afaf5a2dSDavid Somayajulu return QLA_ERROR; 367afaf5a2dSDavid Somayajulu } 368afaf5a2dSDavid Somayajulu 369