📄 qla_fo.c
字号:
rval = qla2x00_fo_get_lun_data(&cmd_struct, &buff.lun_data, mode); if (rval != 0) out_size = 0; break; case FO_CC_SET_LUN_DATA: DEBUG4(printk("calling qla2x00_fo_set_lun_data\n");) DEBUG4(printk(" ((EXT_IOCTL*)arg)->RequestAdr (%p):\n", (((EXT_IOCTL*)arg)->RequestAdr));) rval = qla2x00_fo_set_lun_data(&cmd_struct, &buff.lun_data, mode); break; case FO_CC_GET_TARGET_DATA: DEBUG4(printk("calling qla2x00_fo_get_target_data\n");) DEBUG4(printk(" ((EXT_IOCTL*)arg)->RequestAdr (%p):\n", (((EXT_IOCTL*)arg)->RequestAdr));) rval = qla2x00_fo_get_target_data(&cmd_struct, &buff.target_data, mode); if (rval != 0) { out_size = 0; } break; case FO_CC_SET_TARGET_DATA: DEBUG4(printk("calling qla2x00_fo_set_target_data\n");) DEBUG4(printk(" ((EXT_IOCTL*)arg)->RequestAdr (%p):\n", (((EXT_IOCTL*)arg)->RequestAdr));) rval = qla2x00_fo_set_target_data(&cmd_struct, &buff.target_data, mode); break; } if ((cmd_struct.ResponseLen = out_size) != 0) { copy_to_user(&(((EXT_IOCTL*)arg)->ResponseAdr), &buff, out_size); } /* Set Status and DetailStatus fields in application EXT_IOCTL */ (((EXT_IOCTL*)arg)->Status) = cmd_struct.Status; (((EXT_IOCTL*)arg)->DetailStatus) = cmd_struct.DetailStatus; (((EXT_IOCTL*)arg)->ResponseLen) = cmd_struct.ResponseLen; if (rval != 0) { /*EMPTY*/ DEBUG4(printk("qla2x00_fo_ioctl: **** FAILED ****\n");) } else { /*EMPTY*/ DEBUG4(printk("qla2x00_fo_ioctl: exiting normally\n");) } return rval;}/* * qla2x00_fo_count_retries * Increment the retry counter for the command. * Set or reset the SRB_RETRY flag. * * Input: * sp = Pointer to command. * * Returns: * TRUE -- retry * FALSE -- don't retry * * Context: * Kernel context. */static BOOLqla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp){ BOOL retry = TRUE; os_lun_t *lq; os_tgt_t *tq; if (++sp->fo_retry_cnt > qla_fo_params.MaxRetriesPerIo) { /* no more failovers for this request */ retry = FALSE; sp->fo_retry_cnt = 0; printk(KERN_INFO "qla2x00: no more failovers for request - " "pid= %ld\n", sp->cmd->serial_number); } else { /* * We haven't exceeded the max retries for this request, check * max retries this path */ if ((sp->fo_retry_cnt % qla_fo_params.MaxRetriesPerPath) == 0) { DEBUG(printk(" qla2x00_fo_count_retries: FAILOVER - " "queuing ha=%ld, sp=%p, pid =%ld, " "fo retry= %d \n", ha->host_no, sp, sp->cmd->serial_number, sp->fo_retry_cnt);) /* * Note: we don't want it to timeout, so it is * recycling on the retry queue and the fialover queue. */ lq = sp->lun_queue; tq = sp->tgt_queue; set_bit(LUN_MPIO_BUSY, &lq->q_flag); /* * ??? We can get a path error on any ha, but always * queue failover on originating ha. This will allow us * to syncronized the requests for a given lun. */ sp->f_start=jiffies;/*ra 10/29/01*/ /* Now queue it on to be failover */ sp->ha = ha; add_to_failover_queue(ha,sp); } } return retry ;}/* * qla2x00_fo_check * This function is called from the done routine to see if * the SRB requires a failover. * * This function examines the available os returned status and * if meets condition, the command(srb) is placed ont the failover * queue for processing. * * Input: * sp = Pointer to the SCSI Request Block * * Output: * sp->flags SRB_RETRY bit id command is to * be retried otherwise bit is reset. * * Returns: * None. * * Context: * Kernel/Interrupt context. */BOOLqla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp){ BOOL retry = FALSE; int host_status;#if DEBUG_QLA2100 STATIC char *reason[] = { "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR" };#endif /* we failover on selction timeouts only */ host_status = CMD_RESULT(sp->cmd) >>16; if( host_status == DID_NO_CONNECT) { if( qla2x00_fo_count_retries(ha,sp) ) { /* Force a retry on this request, it will * cause the LINUX timer to get reset, while we * we are processing the failover. */ CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16; retry = TRUE; } DEBUG(printk("qla2x00_fo_check: pid= %ld sp %p " "retry count=%d, retry flag = %d, " "host status (%s)\n\r", sp->cmd->serial_number, sp, sp->fo_retry_cnt, retry, reason[host_status]);) } return retry;}/* * qla2x00_fo_path_change * This function is called from configuration mgr to notify * of a path change. * * Input: * type = Failover notify type, FO_NOTIFY_LUN_RESET or FO_NOTIFY_LOGOUT * newlunp = Pointer to the fc_lun struct for current path. * oldlunp = Pointer to fc_lun struct for previous path. * * Returns: * * Context: * Kernel context. */uint32_tqla2x00_fo_path_change(uint32_t type, fc_lun_t *newlunp, fc_lun_t *oldlunp){ uint32_t ret = QLA2X00_SUCCESS; newlunp->max_path_retries = 0; return ret;}/* * qla2x00_fo_get_params * Process an ioctl request to get system wide failover parameters. * * Input: * pp = Pointer to FO_PARAMS structure. * * Returns: * EXT_STATUS code. * * Context: * Kernel context. */static uint32_tqla2x00_fo_get_params(PFO_PARAMS pp){ pp->MaxPathsPerDevice = qla_fo_params.MaxPathsPerDevice; pp->MaxRetriesPerPath = qla_fo_params.MaxRetriesPerPath; pp->MaxRetriesPerIo = qla_fo_params.MaxRetriesPerIo; pp->Flags = qla_fo_params.Flags; pp->FailoverNotifyType = qla_fo_params.FailoverNotifyType; pp->FailoverNotifyCdbLength = qla_fo_params.FailoverNotifyCdbLength; memset(pp->FailoverNotifyCdb, 0, sizeof(pp->FailoverNotifyCdb)); memcpy(pp->FailoverNotifyCdb, &qla_fo_params.FailoverNotifyCdb[0], sizeof(pp->FailoverNotifyCdb)); return EXT_STATUS_OK;}/* * qla2x00_fo_set_params * Process an ioctl request to set system wide failover parameters. * * Input: * pp = Pointer to FO_PARAMS structure. * * Returns: * EXT_STATUS code. * * Context: * Kernel context. */static uint32_tqla2x00_fo_set_params(PFO_PARAMS pp){ /* Check values for defined MIN and MAX */ if ((pp->MaxPathsPerDevice > SDM_DEF_MAX_PATHS_PER_DEVICE) || (pp->MaxRetriesPerPath < FO_MAX_RETRIES_PER_PATH_MIN) || (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_PATH_MAX) || (pp->MaxRetriesPerIo < FO_MAX_RETRIES_PER_IO_MIN) || (pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_IO_MAX)) return EXT_STATUS_INVALID_PARAM; /* Update the global structure. */ qla_fo_params.MaxPathsPerDevice = pp->MaxPathsPerDevice; qla_fo_params.MaxRetriesPerPath = pp->MaxRetriesPerPath; qla_fo_params.MaxRetriesPerIo = pp->MaxRetriesPerIo; qla_fo_params.Flags = pp->Flags; qla_fo_params.FailoverNotifyType = pp->FailoverNotifyType; qla_fo_params.FailoverNotifyCdbLength = pp->FailoverNotifyCdbLength; if (pp->FailoverNotifyType & FO_NOTIFY_TYPE_CDB) { if (pp->FailoverNotifyCdbLength > sizeof(qla_fo_params.FailoverNotifyCdb)) return EXT_STATUS_INVALID_PARAM; memcpy(qla_fo_params.FailoverNotifyCdb, pp->FailoverNotifyCdb, sizeof(qla_fo_params.FailoverNotifyCdb)); } return EXT_STATUS_OK;}/* * qla2x00_fo_init_params * Gets driver configuration file failover properties to initalize * the global failover parameters structure. * * Input: * ha = adapter block pointer. * * Context: * Kernel context. */voidqla2x00_fo_init_params(scsi_qla_host_t *ha){ /* For parameters that are not completely implemented yet, */ memset(&qla_fo_params, 0, sizeof(qla_fo_params)); if(MaxPathsPerDevice) { qla_fo_params.MaxPathsPerDevice = MaxPathsPerDevice; } else qla_fo_params.MaxPathsPerDevice =FO_MAX_PATHS_PER_DEVICE_DEF ; if(MaxRetriesPerPath) { qla_fo_params.MaxRetriesPerPath = MaxRetriesPerPath; } else qla_fo_params.MaxRetriesPerPath =FO_MAX_RETRIES_PER_PATH_DEF; if(MaxRetriesPerIo) { qla_fo_params.MaxRetriesPerIo =MaxRetriesPerIo; } else qla_fo_params.MaxRetriesPerIo =FO_MAX_RETRIES_PER_IO_DEF; qla_fo_params.Flags = 0; qla_fo_params.FailoverNotifyType = FO_NOTIFY_TYPE_NONE;}/* * qla2x00_send_fo_notification * Sends failover notification if needed. Change the fc_lun pointer * in the old path lun queue. * * Input: * old_lp = Pointer to old fc_lun. * new_lp = Pointer to new fc_lun. * * Returns: * Local function status code. * * Context: * Kernel context. */uint32_tqla2x00_send_fo_notification(fc_lun_t *old_lp, fc_lun_t *new_lp){ scsi_qla_host_t *old_ha = old_lp->fcport->ha; int rval = QLA2X00_SUCCESS; inq_cmd_rsp_t *pkt; uint16_t loop_id, lun; dma_addr_t phys_address; ENTER("qla2x00_send_fo_notification"); loop_id = old_lp->fcport->loop_id; lun = old_lp->lun; if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LUN_RESET) { rval = qla2x00_lun_reset(old_ha, loop_id, lun); if (rval == QLA2X00_SUCCESS) { DEBUG4(printk("qla2x00_send_fo_notification: LUN " "reset succeded\n");) } else { DEBUG4(printk("qla2x00_send_fo_notification: LUN " "reset failed\n");) } } if ( (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET) || (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LOGOUT_OR_CDB) ) { rval = qla2x00_fabric_logout(old_ha, loop_id); if (rval == QLA2X00_SUCCESS) { DEBUG4(printk("qla2x00_send_fo_failover_notify: " "logout succeded\n");) } else { DEBUG4(printk("qla2x00_send_fo_failover_notify: " "logout failed\n");) } } if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB) { pkt = pci_alloc_consistent(old_ha->pdev, sizeof(inq_cmd_rsp_t), &phys_address); if (pkt == NULL) { DEBUG4(printk("qla2x00_send_fo_failover_notify: " "memory allocation failed\n");) return(QLA2X00_FUNCTION_FAILED); } memset(pkt,0, sizeof(inq_cmd_rsp_t)); /* Fix Me-COMMAND_A64_TYPE ??? */ pkt->p.cmd.entry_type = COMMAND_TYPE; pkt->p.cmd.entry_count = 1; pkt->p.cmd.lun = lun; pkt->p.cmd.target = (uint8_t)loop_id; pkt->p.cmd.control_flags = CF_SIMPLE_TAG; memcpy(qla_fo_params.FailoverNotifyCdb, pkt->p.cmd.scsi_cdb, qla_fo_params.FailoverNotifyCdbLength); /* FIXME This setup needs to be verified with Dennis. */ pkt->p.cmd.dseg_count = 1; pkt->p.cmd.byte_count = 0; LITTLE_ENDIAN_32(pkt->p.cmd.byte_count); pkt->p.cmd.dseg_0_address = (uint32_t) (phys_address + sizeof (sts_entry_t)); LITTLE_ENDIAN_32(pkt->p.cmd.dseg_0_address); pkt->p.cmd.dseg_0_length = 0; LITTLE_ENDIAN_32(pkt->p.cmd.dseg_0_length); rval = qla2x00_issue_iocb(old_ha, pkt, phys_address, sizeof (inq_cmd_rsp_t)); if (rval != QLA2X00_SUCCESS || pkt->p.rsp.comp_status != CS_COMPLETE || pkt->p.rsp.scsi_status & SS_CHECK_CONDITION || pkt->inq[0] == 0x7f) { DEBUG4(printk("qla2x00_fo_notification: send CDB " "failed: comp_status = %x" "scsi_status = %x inq[0] = %x\n", pkt->p.rsp.comp_status, pkt->p.rsp.scsi_status, pkt->inq[0]);) } pci_free_consistent(old_ha->pdev, sizeof(inq_cmd_rsp_t), pkt, phys_address); } return rval;}/* * qla2100_fo_enabled * Reads and validates the failover enabled property. * * Input: * ha = adapter state pointer. * instance = HBA number. * * Returns: * TRUE when failover is authorized else FALSE * * Context: * Kernel context. */BOOLqla2x00_fo_enabled(scsi_qla_host_t *ha, int instance){ BOOL enable = FALSE; if (ha->flags.failover_enabled) enable = TRUE; return enable;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -