blob: 03fb20cc8548e198b7e4a50dbcae5bc289067a55 [file] [log] [blame]
/*
* qla_target.c SCSI LLD infrastructure for Cavium 22xx/23xx/24xx/25xx
*
* based on qla2x00t.c code:
*
* Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
* Copyright (C) 2004 - 2005 Leonid Stoljar
* Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
* Copyright (C) 2006 - 2010 ID7 Ltd.
*
* Forward port and refactoring to modern qla2xxx and target/configfs
*
* Copyright (C) 2010-2013 Nicholas A. Bellinger <nab@kernel.org>
*
* 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, version 2
* of the License.
*
* 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.
*/
/* NOTE: this file is mean to hold any symbol/routine that's SCST
* specific where upstream community would not accept. Upstream
* would view these symbols as dead code.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include "qla_def.h"
#include "scst_qla2xxx.h"
size_t qlt_add_vtarget(u64 port_name, u64 node_name, u64 parent_host)
{
struct Scsi_Host *shost = NULL;
struct qla_tgt *tgt;
scsi_qla_host_t *vha = NULL;
struct fc_vport_identifiers vid;
uint8_t parent_wwn[WWN_SIZE];
memset(&vid, 0, sizeof(vid));
u64_to_wwn(parent_host, parent_wwn);
mutex_lock(&qla_tgt_mutex);
list_for_each_entry(tgt, &qla_tgt_glist, tgt_list_entry) {
vha = tgt->vha;
if (!memcmp(parent_wwn, vha->port_name, WWN_SIZE)) {
shost = vha->host;
break;
}
}
mutex_unlock(&qla_tgt_mutex);
if (!vha || !shost)
return -ENODEV;
vid.port_name = port_name;
vid.node_name = node_name;
vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
vid.vport_type = FC_PORTTYPE_NPIV;
/* vid.symbolic_name is already zero/NULL's */
vid.disable = false; /* always enabled */
/* We only allow support on Channel 0 !!! */
if (!fc_vport_create(shost, 0, &vid))
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(qlt_add_vtarget);
size_t qlt_del_vtarget(u64 port_name)
{
struct qla_tgt *tgt, *t;
scsi_qla_host_t *vha = NULL;
struct Scsi_Host *shost;
struct fc_host_attrs *fc_host;
struct fc_vport *vport;
unsigned long flags;
int match = 0;
pr_info("%s: %llx", __func__, port_name);
mutex_lock(&qla_tgt_mutex);
list_for_each_entry_safe(tgt, t, &qla_tgt_glist, tgt_list_entry) {
vha = tgt->vha;
shost = vha->host;
fc_host = shost_to_fc_host(shost);
spin_lock_irqsave(shost->host_lock, flags);
/* We only allow support on Channel 0 !!! */
list_for_each_entry(vport, &fc_host->vports, peers) {
if ((vport->channel == 0) &&
(vport->port_name == port_name)) {
match = 1;
dev_info(&vha->hw->pdev->dev,
"%s: port_name %llx\n",
__func__, port_name);
break;
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
if (match)
break;
}
mutex_unlock(&qla_tgt_mutex);
if (!match)
return -ENODEV;
return fc_vport_terminate(vport);
}
EXPORT_SYMBOL(qlt_del_vtarget);