/** * qla4xxx_send_marker_iocb - issues marker iocb to HBA * @ha: Pointer to host adapter structure. * @ddb_entry: Pointer to device database entry * @lun: SCSI LUN * @mrkr_mod: marker identifier * * This routine issues a marker IOCB.
**/ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod)
{ struct qla4_marker_entry *marker_entry; unsignedlong flags = 0;
uint8_t status = QLA_SUCCESS;
/* Acquire hardware specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Get pointer to the queue entry for the marker */ if (qla4xxx_get_req_pkt(ha, (struct queue_entry **) &marker_entry) !=
QLA_SUCCESS) {
status = QLA_ERROR; goto exit_send_marker;
}
/* Put the marker in the request queue */
marker_entry->hdr.entryType = ET_MARKER;
marker_entry->hdr.entryCount = 1;
marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
marker_entry->modifier = cpu_to_le16(mrkr_mod);
int_to_scsilun(lun, &marker_entry->lun);
wmb();
/* Tell ISP it's got a new I/O request */
ha->isp_ops->queue_iocb(ha);
/** * qla4_82xx_queue_iocb - Tell ISP it's got new request(s) * @ha: pointer to host adapter structure. * * This routine notifies the ISP that one or more new request * queue entries have been placed on the request queue.
**/ void qla4_82xx_queue_iocb(struct scsi_qla_host *ha)
{
uint32_t dbval = 0;
/** * qla4_82xx_complete_iocb - Tell ISP we're done with response(s) * @ha: pointer to host adapter structure. * * This routine notifies the ISP that one or more response/completion * queue entries have been processed by the driver. * This also clears the interrupt.
**/ void qla4_82xx_complete_iocb(struct scsi_qla_host *ha)
{
writel(ha->response_out, &ha->qla4_82xx_reg->rsp_q_out);
readl(&ha->qla4_82xx_reg->rsp_q_out);
}
/** * qla4xxx_queue_iocb - Tell ISP it's got new request(s) * @ha: pointer to host adapter structure. * * This routine is notifies the ISP that one or more new request * queue entries have been placed on the request queue.
**/ void qla4xxx_queue_iocb(struct scsi_qla_host *ha)
{
writel(ha->request_in, &ha->reg->req_q_in);
readl(&ha->reg->req_q_in);
}
/** * qla4xxx_complete_iocb - Tell ISP we're done with response(s) * @ha: pointer to host adapter structure. * * This routine is notifies the ISP that one or more response/completion * queue entries have been processed by the driver. * This also clears the interrupt.
**/ void qla4xxx_complete_iocb(struct scsi_qla_host *ha)
{
writel(ha->response_out, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
}
/** * qla4xxx_send_command_to_isp - issues command to HBA * @ha: pointer to host adapter structure. * @srb: pointer to SCSI Request Block to be sent to ISP * * This routine is called by qla4xxx_queuecommand to build an ISP * command and pass it to the ISP for execution.
**/ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
{ struct scsi_cmnd *cmd = srb->cmd; struct ddb_entry *ddb_entry; struct command_t3_entry *cmd_entry; int nseg;
uint16_t tot_dsds;
uint16_t req_cnt; unsignedlong flags;
uint32_t index;
/* Get real lun and adapter */
ddb_entry = srb->ddb;
tot_dsds = 0;
/* Acquire hardware specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
index = scsi_cmd_to_rq(cmd)->tag;
/* * Check to see if adapter is online before placing request on * request queue. If a reset occurs and a request is in the queue, * the firmware will still attempt to process the request, retrieving * garbage for pointers.
*/ if (!test_bit(AF_ONLINE, &ha->flags)) {
DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " "Do not issue command.\n",
ha->host_no, __func__)); goto queuing_error;
}
/* Calculate the number of request entries needed. */
nseg = scsi_dma_map(cmd); if (nseg < 0) goto queuing_error;
tot_dsds = nseg;
req_cnt = qla4xxx_calc_request_entries(tot_dsds); if (!qla4xxx_space_in_req_ring(ha, req_cnt)) goto queuing_error;
/* total iocbs active */ if ((ha->iocb_cnt + req_cnt) >= ha->iocb_hiwat) goto queuing_error;
/* Set data transfer direction control flags * NOTE: Look at data_direction bits iff there is data to be * transferred, as the data direction bit is sometimed filled
* in when there is no data to be transferred */
cmd_entry->control_flags = CF_NO_DATA; if (scsi_bufflen(cmd)) { if (cmd->sc_data_direction == DMA_TO_DEVICE)
cmd_entry->control_flags = CF_WRITE; elseif (cmd->sc_data_direction == DMA_FROM_DEVICE)
cmd_entry->control_flags = CF_READ;
spin_lock_irqsave(&ha->hardware_lock, flags);
task_data->iocb_req_cnt = 1; /* Put the IOCB on the request queue */ if (!qla4xxx_space_in_req_ring(ha, task_data->iocb_req_cnt)) goto queuing_error;
/* Acquire hardware specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Get pointer to the queue entry for the marker */
rval = qla4xxx_get_req_pkt(ha, (struct queue_entry **) &(mrb->mbox)); if (rval != QLA_SUCCESS) goto exit_mbox_iocb;
index = ha->mrb_index; /* get valid mrb index*/ for (i = 0; i < MAX_MRB; i++) {
index++; if (index == MAX_MRB)
index = 1; if (ha->active_mrb_array[index] == NULL) {
ha->mrb_index = index; break;
}
}
mrb = qla4xxx_get_new_mrb(ha); if (!mrb) {
DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: fail to get new mrb\n",
__func__));
rval = QLA_ERROR; goto exit_ping;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.