|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Copyright (c) 2008, Intel Corporation.
|
|
Packit Service |
35c908 |
*
|
|
Packit Service |
35c908 |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit Service |
35c908 |
* under the terms and conditions of the GNU Lesser General Public License,
|
|
Packit Service |
35c908 |
* version 2.1, as published by the Free Software Foundation.
|
|
Packit Service |
35c908 |
*
|
|
Packit Service |
35c908 |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit Service |
35c908 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit Service |
35c908 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
Packit Service |
35c908 |
* for more details.
|
|
Packit Service |
35c908 |
*
|
|
Packit Service |
35c908 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
35c908 |
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
35c908 |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
35c908 |
*
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
#include "utils.h"
|
|
Packit Service |
35c908 |
#include "api_lib.h"
|
|
Packit Service |
35c908 |
#include "adapt_impl.h"
|
|
Packit Service |
35c908 |
#include "bind_impl.h"
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Binding capabilities we understand.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
#define BINDING_CAPABILITIES (HBA_CAN_BIND_TO_D_ID | \
|
|
Packit Service |
35c908 |
HBA_CAN_BIND_TO_WWPN | \
|
|
Packit Service |
35c908 |
HBA_CAN_BIND_TO_WWNN)
|
|
Packit Service |
35c908 |
#define SYSFS_BIND "tgtid_bind_type"
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Name-value strings for kernel bindings.
|
|
Packit Service |
35c908 |
* The first word of the strings must exactly match those in
|
|
Packit Service |
35c908 |
* Linux's drivers/scsi/scsi_transport_fc
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
static struct sa_nameval binding_types_table[] = {
|
|
Packit Service |
35c908 |
{ "none", 0 },
|
|
Packit Service |
35c908 |
{ "wwpn (World Wide Port Name)", HBA_CAN_BIND_TO_WWPN },
|
|
Packit Service |
35c908 |
{ "wwnn (World Wide Node Name)", HBA_CAN_BIND_TO_WWNN },
|
|
Packit Service |
35c908 |
{ "port_id (FC Address)", HBA_CAN_BIND_TO_D_ID },
|
|
Packit Service |
35c908 |
{ NULL, 0 }
|
|
Packit Service |
35c908 |
};
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Context for LUN binding reader.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
struct binding_context {
|
|
Packit Service |
35c908 |
HBA_HANDLE oc_handle;
|
|
Packit Service |
35c908 |
int oc_kern_hba; /* kernel HBA number */
|
|
Packit Service |
35c908 |
int oc_port;
|
|
Packit Service |
35c908 |
int oc_target;
|
|
Packit Service |
35c908 |
int oc_lun;
|
|
Packit Service |
35c908 |
u_int32_t oc_count;
|
|
Packit Service |
35c908 |
u_int32_t oc_limit;
|
|
Packit Service |
35c908 |
u_int32_t oc_ver;
|
|
Packit Service |
35c908 |
void *oc_entries;
|
|
Packit Service |
35c908 |
HBA_STATUS oc_status;
|
|
Packit Service |
35c908 |
char oc_sg[32]; /* SCSI-generic dev name */
|
|
Packit Service |
35c908 |
HBA_SCSIID *oc_scp; /* place for OS device name */
|
|
Packit Service |
35c908 |
struct port_info *oc_rport; /* target remote port, if known */
|
|
Packit Service |
35c908 |
char oc_path[256]; /* parent dir save area */
|
|
Packit Service |
35c908 |
};
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Get binding capability.
|
|
Packit Service |
35c908 |
* We currently don't have a way to get this from the driver.
|
|
Packit Service |
35c908 |
* Instead, we hardcode what we know about Linux's capabilities.
|
|
Packit Service |
35c908 |
* We don't care which HBA is specified, except to return the correct error.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
HBA_STATUS
|
|
Packit Service |
35c908 |
get_binding_capability(HBA_HANDLE handle, HBA_WWN wwn, HBA_BIND_CAPABILITY *cp)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct port_info *pp;
|
|
Packit Service |
35c908 |
int count = 0;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
pp = adapter_get_port_by_wwn(handle, wwn, &count);
|
|
Packit Service |
35c908 |
if (count > 1)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_AMBIGUOUS_WWN;
|
|
Packit Service |
35c908 |
else if (pp == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_ILLEGAL_WWN;
|
|
Packit Service |
35c908 |
*cp = BINDING_CAPABILITIES;
|
|
Packit Service |
35c908 |
return HBA_STATUS_OK;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Get binding support.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
HBA_STATUS
|
|
Packit Service |
35c908 |
get_binding_support(HBA_HANDLE handle, HBA_WWN wwn, HBA_BIND_CAPABILITY *cp)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct port_info *pp;
|
|
Packit Service |
35c908 |
char dir[50];
|
|
Packit Service |
35c908 |
char bind[50];
|
|
Packit Service |
35c908 |
int count = 0;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
pp = adapter_get_port_by_wwn(handle, wwn, &count);
|
|
Packit Service |
35c908 |
if (count > 1)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_AMBIGUOUS_WWN;
|
|
Packit Service |
35c908 |
else if (pp == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_ILLEGAL_WWN;
|
|
Packit Service |
35c908 |
snprintf(dir, sizeof(dir), SYSFS_HOST_DIR "/host%u", pp->ap_kern_hba);
|
|
Packit Service |
35c908 |
if (sa_sys_read_line(dir, SYSFS_BIND, bind, sizeof(bind)) == 0)
|
|
Packit Service |
35c908 |
sa_enum_encode(binding_types_table, bind, cp);
|
|
Packit Service |
35c908 |
return HBA_STATUS_OK;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Set binding support.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
HBA_STATUS
|
|
Packit Service |
35c908 |
set_binding_support(HBA_HANDLE handle, HBA_WWN wwn, HBA_BIND_CAPABILITY flags)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct port_info *pp;
|
|
Packit Service |
35c908 |
int count = 0;
|
|
Packit Service |
35c908 |
char dir[50];
|
|
Packit Service |
35c908 |
char buf[50];
|
|
Packit Service |
35c908 |
const char *bind;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
pp = adapter_get_port_by_wwn(handle, wwn, &count);
|
|
Packit Service |
35c908 |
if (count > 1)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_AMBIGUOUS_WWN;
|
|
Packit Service |
35c908 |
if (pp == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_ILLEGAL_WWN;
|
|
Packit Service |
35c908 |
if ((flags & BINDING_CAPABILITIES) != flags)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_NOT_SUPPORTED;
|
|
Packit Service |
35c908 |
bind = sa_enum_decode(buf, sizeof(buf), binding_types_table, flags);
|
|
Packit Service |
35c908 |
snprintf(dir, sizeof(dir), SYSFS_HOST_DIR "/host%u", pp->ap_kern_hba);
|
|
Packit Service |
35c908 |
if (strstr(bind, "Unknown") != NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_NOT_SUPPORTED;
|
|
Packit Service |
35c908 |
if (sa_sys_write_line(dir, SYSFS_BIND, bind) == 0)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_INCAPABLE;
|
|
Packit Service |
35c908 |
return HBA_STATUS_OK;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
static int
|
|
Packit Service |
35c908 |
get_deprecated_device_name(struct dirent *dp, void *arg)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context *cp = arg;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
if (strstr(cp->oc_path, "block"))
|
|
Packit Service |
35c908 |
snprintf(cp->oc_scp->OSDeviceName,
|
|
Packit Service |
35c908 |
sizeof(cp->oc_scp->OSDeviceName),
|
|
Packit Service |
35c908 |
"/dev/%s", dp->d_name);
|
|
Packit Service |
35c908 |
if (strstr(cp->oc_path, "scsi_generic"))
|
|
Packit Service |
35c908 |
snprintf(cp->oc_sg, sizeof(cp->oc_sg),
|
|
Packit Service |
35c908 |
"/dev/%s", dp->d_name);
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
static int
|
|
Packit Service |
35c908 |
get_binding_os_names(struct dirent *dp, void *arg)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context *cp = arg;
|
|
Packit Service |
35c908 |
char *name = dp->d_name;
|
|
Packit Service |
35c908 |
char *sep;
|
|
Packit Service |
35c908 |
char buf[sizeof(cp->oc_scp->OSDeviceName)];
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
sep = strchr(name, ':');
|
|
Packit Service |
35c908 |
if (dp->d_type == DT_LNK && sep != NULL) {
|
|
Packit Service |
35c908 |
*sep = '\0'; /* replace colon */
|
|
Packit Service |
35c908 |
if (strcmp(name, "block") == 0) {
|
|
Packit Service |
35c908 |
snprintf(cp->oc_scp->OSDeviceName,
|
|
Packit Service |
35c908 |
sizeof(cp->oc_scp->OSDeviceName),
|
|
Packit Service |
35c908 |
"/dev/%s", sep + 1);
|
|
Packit Service |
35c908 |
} else if (strcmp(name, "scsi_generic") == 0) {
|
|
Packit Service |
35c908 |
snprintf(cp->oc_sg,
|
|
Packit Service |
35c908 |
sizeof(cp->oc_sg),
|
|
Packit Service |
35c908 |
"/dev/%s", sep + 1);
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
*sep = ':'; /* not really needed */
|
|
Packit Service |
35c908 |
} else if (dp->d_type == DT_DIR && sep == NULL) {
|
|
Packit Service |
35c908 |
if ((!strcmp(name, "block")) ||
|
|
Packit Service |
35c908 |
(!strcmp(name, "scsi_generic"))) {
|
|
Packit Service |
35c908 |
/* save the original path */
|
|
Packit Service |
35c908 |
sa_strncpy_safe(buf, sizeof(buf),
|
|
Packit Service |
35c908 |
cp->oc_path, sizeof(cp->oc_path));
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
snprintf(cp->oc_path, sizeof(cp->oc_path),
|
|
Packit Service |
35c908 |
"%s/%s", buf, name);
|
|
Packit Service |
35c908 |
sa_dir_read(cp->oc_path,
|
|
Packit Service |
35c908 |
get_deprecated_device_name, cp);
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/* restore the original path */
|
|
Packit Service |
35c908 |
sa_strncpy_safe(cp->oc_path, sizeof(cp->oc_path),
|
|
Packit Service |
35c908 |
buf, sizeof(buf));
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
static int
|
|
Packit Service |
35c908 |
get_binding_target_mapping(struct dirent *dp, void *ctxt_arg)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context *cp = ctxt_arg;
|
|
Packit Service |
35c908 |
struct port_info *pp;
|
|
Packit Service |
35c908 |
HBA_FCPSCSIENTRY *sp;
|
|
Packit Service |
35c908 |
HBA_FCPSCSIENTRYV2 *s2p;
|
|
Packit Service |
35c908 |
HBA_SCSIID *scp = NULL;
|
|
Packit Service |
35c908 |
HBA_FCPID *fcp = NULL;
|
|
Packit Service |
35c908 |
HBA_LUID *luid = NULL;
|
|
Packit Service |
35c908 |
char name[50];
|
|
Packit Service |
35c908 |
u_int32_t hba = -1;
|
|
Packit Service |
35c908 |
u_int32_t port = -1;
|
|
Packit Service |
35c908 |
u_int32_t tgt = -1;
|
|
Packit Service |
35c908 |
u_int32_t lun = -1;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Parse directory entry name to see if it matches
|
|
Packit Service |
35c908 |
* <hba>:<port>:<target>:<lun>.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
if (sscanf(dp->d_name, "%u:%u:%u:%u", &hba, &port, &tgt, &lun) != 4)
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
if (hba != cp->oc_kern_hba ||
|
|
Packit Service |
35c908 |
(port != cp->oc_port && cp->oc_port != -1) ||
|
|
Packit Service |
35c908 |
(tgt != cp->oc_target && cp->oc_target != -1) ||
|
|
Packit Service |
35c908 |
(lun != cp->oc_lun && cp->oc_lun != -1)) {
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Name matches. Add to count and to mapping list if there's room.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
if (cp->oc_count < cp->oc_limit) {
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
switch (cp->oc_ver) {
|
|
Packit Service |
35c908 |
case 1:
|
|
Packit Service |
35c908 |
sp = &((HBA_FCPSCSIENTRY *)
|
|
Packit Service |
35c908 |
cp->oc_entries)[cp->oc_count];
|
|
Packit Service |
35c908 |
scp = &sp->ScsiId;
|
|
Packit Service |
35c908 |
fcp = &sp->FcpId;
|
|
Packit Service |
35c908 |
luid = NULL;
|
|
Packit Service |
35c908 |
break;
|
|
Packit Service |
35c908 |
case 2:
|
|
Packit Service |
35c908 |
s2p = &((HBA_FCPSCSIENTRYV2 *)
|
|
Packit Service |
35c908 |
cp->oc_entries)[cp->oc_count];
|
|
Packit Service |
35c908 |
scp = &s2p->ScsiId;
|
|
Packit Service |
35c908 |
fcp = &s2p->FcpId;
|
|
Packit Service |
35c908 |
luid = &s2p->LUID;
|
|
Packit Service |
35c908 |
break;
|
|
Packit Service |
35c908 |
default:
|
|
Packit Service |
35c908 |
fprintf(stderr, "*** Fatal! ***\n");
|
|
Packit Service |
35c908 |
break;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
pp = cp->oc_rport;
|
|
Packit Service |
35c908 |
if (pp == NULL)
|
|
Packit Service |
35c908 |
pp = adapter_get_rport_target(cp->oc_handle,
|
|
Packit Service |
35c908 |
port, tgt);
|
|
Packit Service |
35c908 |
if (pp != NULL) {
|
|
Packit Service |
35c908 |
fcp->FcId = pp->ap_attr.PortFcId;
|
|
Packit Service |
35c908 |
fcp->NodeWWN = pp->ap_attr.NodeWWN;
|
|
Packit Service |
35c908 |
fcp->PortWWN = pp->ap_attr.PortWWN;
|
|
Packit Service |
35c908 |
fcp->FcpLun = (HBA_UINT64) lun;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Find OS device name by searching for symlink block:<device>
|
|
Packit Service |
35c908 |
* and SG name by searching for scsi_generic:<name>
|
|
Packit Service |
35c908 |
* in device subdirectory.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
snprintf(name, sizeof(name),
|
|
Packit Service |
35c908 |
SYSFS_LUN_DIR "/%s/device", dp->d_name);
|
|
Packit Service |
35c908 |
cp->oc_sg[0] = '\0';
|
|
Packit Service |
35c908 |
cp->oc_scp = scp;
|
|
Packit Service |
35c908 |
scp->OSDeviceName[0] = '\0';
|
|
Packit Service |
35c908 |
/* save a copy of the dir name */
|
|
Packit Service |
35c908 |
sa_strncpy_safe(cp->oc_path, sizeof(cp->oc_path),
|
|
Packit Service |
35c908 |
name, sizeof(name));
|
|
Packit Service |
35c908 |
sa_dir_read(name, get_binding_os_names, cp);
|
|
Packit Service |
35c908 |
scp->ScsiBusNumber = hba;
|
|
Packit Service |
35c908 |
scp->ScsiTargetNumber = tgt;
|
|
Packit Service |
35c908 |
scp->ScsiOSLun = lun;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* find the LUN ID information by using scsi_generic I/O.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
if (luid != NULL && cp->oc_sg[0] != '\0')
|
|
Packit Service |
35c908 |
sg_get_dev_id(cp->oc_sg, luid->buffer,
|
|
Packit Service |
35c908 |
sizeof(luid->buffer));
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
cp->oc_count++;
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Get FCP target mapping.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
HBA_STATUS
|
|
Packit Service |
35c908 |
get_binding_target_mapping_v1(HBA_HANDLE handle, HBA_FCPTARGETMAPPING *map)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context ctxt;
|
|
Packit Service |
35c908 |
struct adapter_info *ap;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
ap = adapter_open_handle(handle);
|
|
Packit Service |
35c908 |
if (ap == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_INVALID_HANDLE;
|
|
Packit Service |
35c908 |
memset(&ctxt, 0, sizeof(ctxt));
|
|
Packit Service |
35c908 |
ctxt.oc_handle = handle;
|
|
Packit Service |
35c908 |
ctxt.oc_kern_hba = ap->ad_kern_index;
|
|
Packit Service |
35c908 |
ctxt.oc_port = -1;
|
|
Packit Service |
35c908 |
ctxt.oc_target = -1;
|
|
Packit Service |
35c908 |
ctxt.oc_lun = -1;
|
|
Packit Service |
35c908 |
ctxt.oc_limit = map->NumberOfEntries;
|
|
Packit Service |
35c908 |
ctxt.oc_ver = 1;
|
|
Packit Service |
35c908 |
ctxt.oc_entries = map->entry;
|
|
Packit Service |
35c908 |
ctxt.oc_status = HBA_STATUS_OK;
|
|
Packit Service |
35c908 |
memset(map->entry, 0, sizeof(map->entry[0]) * ctxt.oc_limit);
|
|
Packit Service |
35c908 |
sa_dir_read(SYSFS_LUN_DIR, get_binding_target_mapping, &ctxt);
|
|
Packit Service |
35c908 |
map->NumberOfEntries = ctxt.oc_count;
|
|
Packit Service |
35c908 |
if (ctxt.oc_status == HBA_STATUS_OK && ctxt.oc_count > ctxt.oc_limit)
|
|
Packit Service |
35c908 |
ctxt.oc_status = HBA_STATUS_ERROR_MORE_DATA;
|
|
Packit Service |
35c908 |
return ctxt.oc_status;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Get FCP target mapping.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
HBA_STATUS
|
|
Packit Service |
35c908 |
get_binding_target_mapping_v2(HBA_HANDLE handle, HBA_WWN wwn,
|
|
Packit Service |
35c908 |
HBA_FCPTARGETMAPPINGV2 *map)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context ctxt;
|
|
Packit Service |
35c908 |
struct adapter_info *ap;
|
|
Packit Service |
35c908 |
struct port_info *pp;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
pp = adapter_get_port_by_wwn(handle, wwn, NULL);
|
|
Packit Service |
35c908 |
if (pp == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_INVALID_HANDLE;
|
|
Packit Service |
35c908 |
ap = pp->ap_adapt;
|
|
Packit Service |
35c908 |
if (ap == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_INVALID_HANDLE;
|
|
Packit Service |
35c908 |
memset(&ctxt, 0, sizeof(ctxt));
|
|
Packit Service |
35c908 |
ctxt.oc_handle = handle;
|
|
Packit Service |
35c908 |
ctxt.oc_kern_hba = ap->ad_kern_index;
|
|
Packit Service |
35c908 |
ctxt.oc_port = pp->ap_index;
|
|
Packit Service |
35c908 |
ctxt.oc_target = -1;
|
|
Packit Service |
35c908 |
ctxt.oc_lun = -1;
|
|
Packit Service |
35c908 |
ctxt.oc_limit = map->NumberOfEntries;
|
|
Packit Service |
35c908 |
ctxt.oc_ver = 2;
|
|
Packit Service |
35c908 |
ctxt.oc_entries = map->entry;
|
|
Packit Service |
35c908 |
ctxt.oc_status = HBA_STATUS_OK;
|
|
Packit Service |
35c908 |
memset(map->entry, 0, sizeof(map->entry[0]) * ctxt.oc_limit);
|
|
Packit Service |
35c908 |
sa_dir_read(SYSFS_LUN_DIR, get_binding_target_mapping, &ctxt);
|
|
Packit Service |
35c908 |
map->NumberOfEntries = ctxt.oc_count;
|
|
Packit Service |
35c908 |
if (ctxt.oc_status == HBA_STATUS_OK && ctxt.oc_count > ctxt.oc_limit)
|
|
Packit Service |
35c908 |
ctxt.oc_status = HBA_STATUS_ERROR_MORE_DATA;
|
|
Packit Service |
35c908 |
return ctxt.oc_status;
|
|
Packit Service |
35c908 |
}
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* Get LUN scsi-generic device name.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
int
|
|
Packit Service |
35c908 |
get_binding_sg_name(struct port_info *lp, HBA_WWN disc_wwpn,
|
|
Packit Service |
35c908 |
HBA_UINT64 fc_lun, char *buf, size_t len)
|
|
Packit Service |
35c908 |
{
|
|
Packit Service |
35c908 |
struct binding_context ctxt;
|
|
Packit Service |
35c908 |
struct port_info *rp;
|
|
Packit Service |
35c908 |
HBA_FCPSCSIENTRYV2 entry;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
/*
|
|
Packit Service |
35c908 |
* find discovered (remote) port.
|
|
Packit Service |
35c908 |
*/
|
|
Packit Service |
35c908 |
rp = adapter_get_rport_by_wwn(lp, disc_wwpn);
|
|
Packit Service |
35c908 |
if (rp == NULL)
|
|
Packit Service |
35c908 |
return HBA_STATUS_ERROR_ILLEGAL_WWN;
|
|
Packit Service |
35c908 |
|
|
Packit Service |
35c908 |
memset(&ctxt, 0, sizeof(ctxt));
|
|
Packit Service |
35c908 |
memset(&entry, 0, sizeof(entry));
|
|
Packit Service |
35c908 |
ctxt.oc_rport = rp;
|
|
Packit Service |
35c908 |
ctxt.oc_kern_hba = rp->ap_kern_hba;
|
|
Packit Service |
35c908 |
ctxt.oc_port = rp->ap_index;
|
|
Packit Service |
35c908 |
ctxt.oc_target = rp->ap_scsi_target;
|
|
Packit Service |
35c908 |
if (ctxt.oc_target == -1)
|
|
Packit Service |
35c908 |
return ENOENT;
|
|
Packit Service |
35c908 |
ctxt.oc_lun = (int) fc_lun;
|
|
Packit Service |
35c908 |
ctxt.oc_limit = 1;
|
|
Packit Service |
35c908 |
ctxt.oc_ver = 1;
|
|
Packit Service |
35c908 |
ctxt.oc_entries = &entry;
|
|
Packit Service |
35c908 |
sa_dir_read(SYSFS_LUN_DIR, get_binding_target_mapping, &ctxt);
|
|
Packit Service |
35c908 |
if (ctxt.oc_count != 1)
|
|
Packit Service |
35c908 |
return ENOENT;
|
|
Packit Service |
35c908 |
sa_strncpy_safe(buf, len, ctxt.oc_sg, sizeof(ctxt.oc_sg));
|
|
Packit Service |
35c908 |
return 0;
|
|
Packit Service |
35c908 |
}
|