📄 qla_fo.c
字号:
/********************************************************************************* QLOGIC LINUX SOFTWARE** QLogic ISP2x00 device driver for Linux 2.4.x* Copyright (C) 2002 Qlogic Corporation* (www.qlogic.com)** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License as published by the* Free Software Foundation; either version 2, or (at your option) any* later version.** This program is distributed in the hope that it will be useful, but* WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* General Public License for more details.******************************************************************************** Failover include file******************************************************************************/#include "qla2x00.h"#include "qla_gbl.h"#include "exioct.h"#include "qlfo.h"#include "qla_fo.h"#include "qlfolimits.h"/* * Global variables */SysFoParams_t qla_fo_params;/* * Local routines */#if !defined(linux)static int qla2x00_sdm_setup(EXT_IOCTL *cmd_stp, void *arg, int mode);#endifstatic uint32_t qla2x00_fo_get_params(PFO_PARAMS pp);static uint32_t qla2x00_fo_set_params(PFO_PARAMS pp);static BOOL qla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp);static int qla2x00_fo_get_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode);static int qla2x00_fo_set_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode);static uint32_t qla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset);static int qla2x00_fo_set_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode);static int qla2x00_fo_get_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode);/* * qla2x00_get_hba * Searches the hba structure chain for the requested instance * aquires the mutex and returns a pointer to the hba structure. * * Input: * inst = adapter instance number. * * Returns: * Return value is a pointer to the adapter structure or * NULL if instance not found. * * Context: * Kernel context. */scsi_qla_host_t *qla2x00_get_hba(int instance){ scsi_qla_host_t * hbap; hbap = (scsi_qla_host_t *) qla2x00_hostlist; while (hbap != NULL) { if (hbap->instance == instance) { break; } hbap = (scsi_qla_host_t *)hbap->next; } return hbap;}/* * qla2x00_fo_stats * Searches the hba structure chan for the requested instance * aquires the mutex and returns a pointer to the hba structure. * * Input: * stat_p = Pointer to FO_HBA_STAT union. * reset = Flag, TRUE = reset statistics. * FALSE = return statistics values. * * Returns: * 0 = success * * Context: * Kernel context. */static uint32_tqla2x00_fo_stats(FO_HBA_STAT *stat_p, BOOL reset){ int32_t inst, idx; uint32_t rval = 0; scsi_qla_host_t *hbap; inst = stat_p->input.HbaInstance; stat_p->info.HbaCount = 0; hbap = (scsi_qla_host_t *) qla2x00_hostlist; while (hbap != NULL) { if (inst == FO_ADAPTER_ALL) { stat_p->info.HbaCount++; idx = hbap->instance; } else if (hbap->instance == inst) { stat_p->info.HbaCount = 1; idx = inst; } if (reset == TRUE) { hbap->IosRequested = 0; hbap->BytesRequested = 0; hbap->IosExecuted = 0; hbap->BytesExecuted = 0; } else {#if 0 stat_p->info.StatEntry[idx].IosRequested = hbap->IosRequested; stat_p->info.StatEntry[idx].BytesRequested = hbap->BytesRequested; stat_p->info.StatEntry[idx].IosExecuted = hbap->IosExecuted; stat_p->info.StatEntry[idx].BytesExecuted = hbap->BytesExecuted;#endif } if (inst != FO_ADAPTER_ALL) break; else hbap = (scsi_qla_host_t *)hbap->next; } return rval;}/* * qla2x00_fo_get_lun_data * Get lun data from all devices attached to a HBA (FO_GET_LUN_DATA). * Gets lun mask if failover not enabled. * * Input: * ha = pointer to adapter * bp = pointer to buffer * * Return; * 0 on success or errno. * * Context: * Kernel context. */static intqla2x00_fo_get_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode){ scsi_qla_host_t *ha; fc_port_t *fcport; int ret = 0; mp_host_t *host = NULL; mp_device_t *dp; mp_path_t *path; mp_path_list_t *pathlist; os_tgt_t *ostgt; uint8_t path_id; uint16_t dev_no; uint16_t cnt; uint16_t lun; FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; FO_LUN_DATA_LIST *u_list, *list; ha = qla2x00_get_hba((int)bp->HbaInstance); DEBUG3(printk("qla_fo_get_lun_data: hba %p, buff %p.\n", ha, bp);) DEBUG4(printk("qla_fo_get_lun_data: hba %p, buff %p " "bp->HbaInstance(%x).\n", ha, bp, (int)bp->HbaInstance)); if (ha->flags.failover_enabled) if ((host = qla2x00_cfg_find_host(ha)) == NULL) { DEBUG2(printk("qla2x00_get_lun_data: no HOST for " "ha %p.\n", ha);) return 1; } if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), GFP_ATOMIC, 12)) == NULL) { printk("qla_fo_get_lun_data: failed to allocate " "memory of size (%d)\n", (int)sizeof(FO_LUN_DATA_LIST)); return 1; } entry = &list->DataEntry[0]; u_list = (FO_LUN_DATA_LIST *)pext->ResponseAdr; u_entry = &u_list->DataEntry[0]; /* find the correct fcport list */ if (!ha->flags.failover_enabled) fcport = ha->fcport; else fcport = host->fcport; /* Check thru this adapter's fcport list */ for ( ; (fcport); fcport = fcport->next) { memcpy(entry->NodeName, fcport->node_name, EXT_DEF_WWN_NAME_SIZE); memcpy(entry->PortName, fcport->port_name, EXT_DEF_WWN_NAME_SIZE); if (!ha->flags.failover_enabled) { /* * Failover disabled. Just return LUN mask info * in lun data entry of this port. */ entry->TargetId = 0; for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { if (!(ostgt = ha->otgt[cnt])) { continue; } if (ostgt->vis_port == fcport) { entry->TargetId = cnt; break; } } if (cnt == MAX_FIBRE_DEVICES) { /* Not found? For now just go to next port. */#if defined(QL_DEBUG_LEVEL_2) uint8_t *tmp_name;#if USE_PORTNAME tmp_name = fcport->port_name;#else tmp_name = fcport->node_name;#endif printk("fo_get_lun_data(%ld): ERROR " "port %02x%02x%02x%02x%02x%02x%02x%02x " "not configured.\n", ha->host_no, tmp_name[0], tmp_name[1], tmp_name[2], tmp_name[3], tmp_name[4], tmp_name[5], tmp_name[6], tmp_name[7]);#endif /* DEBUG */ continue; } for (lun = 0; lun < MAX_LUNS; lun++) { /* set MSB if masked */ if (EXT_IS_LUN_BIT_SET(&(fcport->lun_mask), lun)) { entry->Data[lun] = 0; } else { entry->Data[lun] = LUN_DATA_ENABLED; } } DEBUG3(printk("qla2x00_fo_get_lun_data: got lun_mask " "for tgt %d\n", cnt);) DEBUG3(qla2x00_dump_buffer((char *)&(fcport->lun_mask), sizeof(fcport->lun_mask));) list->EntryCount++; copy_to_user(u_entry, entry, sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); u_entry++; /* Go to next port */ continue; } /* * Failover is enabled. Go through the mp_devs list and return * lun data in configured path. */ for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { dp = host->mp_devs[dev_no]; if (dp == NULL) continue; /* Lookup entry name */ if (!qla2x00_is_portname_in_device(dp, entry->PortName)) continue; if ((pathlist = dp->path_list) == NULL) continue; path = pathlist->last; for (path_id = 0; path_id < pathlist->path_cnt; path_id++, path = path->next) { if (path->host != host) continue; if (!qla2x00_is_portname_equal(path->portname, entry->PortName)) continue; for (lun = 0; lun < MAX_LUNS; lun++) { entry->Data[lun] = path->lun_data.data[lun]; } entry->TargetId = dp->dev_id; entry->Dev_No = path->id; list->EntryCount++; copy_to_user(u_entry, entry, sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); u_entry++; DEBUG2(printk("qla_fo: (output) get_lun_data - " "u_entry(%p) - lun entry[%d] " ":\n", u_entry,list->EntryCount - 1);) DEBUG2(qla2x00_dump_buffer((void *)entry, 64);) /* * We found the right path for this port. * Continue with next port. */ break; } /* Continue with next port. */ break; } } DEBUG4(printk("qla_fo: get_lun_data - entry count = [%d]\n", list->EntryCount);) /* copy number of entries */ copy_to_user(&u_list->EntryCount, &list->EntryCount, sizeof(list->EntryCount)); pext->ResponseLen = FO_LUN_DATA_LIST_MAX_SIZE; KMEM_FREE(list, sizeof(FO_LUN_DATA_LIST)); return ret;}/* * qla2x00_fo_set_lun_data * Set lun data for the specified device on the attached hba * (FO_SET_LUN_DATA). * Sets lun mask if failover not enabled. * * Input: * bp = pointer to buffer * * Return; * 0 on success or errno. * * Context: * Kernel context. */static intqla2x00_fo_set_lun_data(EXT_IOCTL *pext, FO_LUN_DATA_INPUT *bp, int mode){ scsi_qla_host_t *ha; fc_port_t *fcport; int i; int ret = 0; mp_host_t *host = NULL; mp_device_t *dp; mp_path_t *path; mp_path_list_t *pathlist; os_tgt_t *ostgt; uint8_t path_id; uint16_t dev_no; uint16_t lun; FO_LUN_DATA_LIST *u_list, *list; FO_EXTERNAL_LUN_DATA_ENTRY *u_entry, *entry; typedef struct _tagStruct { FO_LUN_DATA_INPUT foLunDataInput; FO_LUN_DATA_LIST foLunDataList; } com_struc; com_struc *com_iter; ha = qla2x00_get_hba((int)bp->HbaInstance); DEBUG9(printk("qla_fo_set_lun_data: hba %p, buff %p.\n", ha, bp);) if (ha->flags.failover_enabled) if ((host = qla2x00_cfg_find_host(ha)) == NULL) { DEBUG2(printk("qla2x00_fo_set_lun_data: no HOST for " "ha %p.\n", ha);) return 1; } if ((list = (FO_LUN_DATA_LIST *)kmem_zalloc(sizeof(FO_LUN_DATA_LIST), GFP_ATOMIC, 13)) == NULL) { DEBUG2_3(printk("qla_fo_set_lun_data: failed to allocate " "memory of size (%d)\n", (int)sizeof(FO_LUN_DATA_LIST));) return 1; } entry = &list->DataEntry[0]; /* get lun data list from user */ com_iter = (com_struc *)pext->RequestAdr; u_list = &(com_iter->foLunDataList); u_entry = &u_list->DataEntry[0]; copy_from_user(list, u_list, sizeof(FO_LUN_DATA_LIST)); DEBUG2(printk("qla_fo_set_lun_data: pext->RequestAdr(%p) u_list (%p) " "sizeof(FO_LUN_DATA_INPUT) =(%d) and 64 bytes...\n", pext->RequestAdr, u_list, (int)sizeof(FO_LUN_DATA_INPUT));) DEBUG2(qla2x00_dump_buffer((void *)u_list, 64);) for (i = 0; i < list->EntryCount; i++, u_entry++) { copy_from_user(entry, u_entry, sizeof(FO_EXTERNAL_LUN_DATA_ENTRY)); if (!ha->flags.failover_enabled) { /* * Failover disabled. Just find the port and set * LUN mask values in lun_mask field of this port. */ if (entry->TargetId >= MAX_FIBRE_DEVICES) /* ERROR */ continue; if (!(ostgt = ha->otgt[entry->TargetId])) /* ERROR */ continue; if (!(fcport = ostgt->vis_port)) /* ERROR */ continue; for (lun = 0; lun < MAX_LUNS; lun++) { /* set MSB if masked */ if (entry->Data[lun] | LUN_DATA_ENABLED) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -