forked from Minki/linux
[SCSI] bfa: Add BSG interface to support ELS, CT and vendor commands.
- Added BSG interface support to BFA driver - Adds support to send ELS/CT FC passthru commands and few vendor specific BSG requests. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
75332a70a8
commit
b85daafe46
@ -1,6 +1,6 @@
|
||||
obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
|
||||
|
||||
bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
|
||||
bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfad_bsg.o
|
||||
bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
|
||||
bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
|
||||
bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
|
||||
|
@ -130,6 +130,7 @@ enum bfa_status {
|
||||
BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists,
|
||||
* contact support */
|
||||
BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
|
||||
BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
|
||||
BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */
|
||||
BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */
|
||||
BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */
|
||||
@ -138,11 +139,13 @@ enum bfa_status {
|
||||
BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed setting */
|
||||
BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */
|
||||
BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */
|
||||
BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */
|
||||
BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */
|
||||
BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */
|
||||
BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists
|
||||
* contact support */
|
||||
BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */
|
||||
BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
|
||||
BFA_STATUS_DIAG_BUSY = 71, /* diag busy */
|
||||
BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
|
||||
BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
|
||||
|
@ -1369,6 +1369,45 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the list of local logical ports present in the given VF.
|
||||
*
|
||||
* @param[in] vf vf for which logical ports are returned
|
||||
* @param[out] lpwwn returned logical port wwn list
|
||||
* @param[in,out] nlports in:size of lpwwn list;
|
||||
* out:total elements present,
|
||||
* actual elements returned is limited by the size
|
||||
*/
|
||||
void
|
||||
bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
|
||||
{
|
||||
struct list_head *qe;
|
||||
struct bfa_fcs_vport_s *vport;
|
||||
int i = 0;
|
||||
struct bfa_fcs_s *fcs;
|
||||
|
||||
if (vf == NULL || lpwwn == NULL || *nlports == 0)
|
||||
return;
|
||||
|
||||
fcs = vf->fcs;
|
||||
|
||||
bfa_trc(fcs, vf->vf_id);
|
||||
bfa_trc(fcs, (uint32_t) *nlports);
|
||||
|
||||
lpwwn[i++] = vf->bport.port_cfg.pwwn;
|
||||
|
||||
list_for_each(qe, &vf->vport_q) {
|
||||
if (i >= *nlports)
|
||||
break;
|
||||
|
||||
vport = (struct bfa_fcs_vport_s *) qe;
|
||||
lpwwn[i++] = vport->lport.port_cfg.pwwn;
|
||||
}
|
||||
|
||||
bfa_trc(fcs, i);
|
||||
*nlports = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* BFA FCS PPORT ( physical port)
|
||||
*/
|
||||
|
@ -731,6 +731,7 @@ void bfa_fcs_exit(struct bfa_fcs_s *fcs);
|
||||
* bfa fcs vf public functions
|
||||
*/
|
||||
bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
|
||||
void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
|
||||
|
||||
/*
|
||||
* fabric protected interface functions
|
||||
|
@ -583,6 +583,8 @@ struct fc_function_template bfad_im_fc_function_template = {
|
||||
.vport_create = bfad_im_vport_create,
|
||||
.vport_delete = bfad_im_vport_delete,
|
||||
.vport_disable = bfad_im_vport_disable,
|
||||
.bsg_request = bfad_im_bsg_request,
|
||||
.bsg_timeout = bfad_im_bsg_timeout,
|
||||
};
|
||||
|
||||
struct fc_function_template bfad_im_vport_fc_function_template = {
|
||||
|
768
drivers/scsi/bfa/bfad_bsg.c
Normal file
768
drivers/scsi/bfa/bfad_bsg.c
Normal file
@ -0,0 +1,768 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
|
||||
* All rights reserved
|
||||
* www.brocade.com
|
||||
*
|
||||
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (GPL) Version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include "bfad_drv.h"
|
||||
#include "bfad_im.h"
|
||||
#include "bfad_bsg.h"
|
||||
|
||||
BFA_TRC_FILE(LDRV, BSG);
|
||||
|
||||
/* bfad_im_bsg_get_kobject - increment the bfa refcnt */
|
||||
static void
|
||||
bfad_im_bsg_get_kobject(struct fc_bsg_job *job)
|
||||
{
|
||||
struct Scsi_Host *shost = job->shost;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
__module_get(shost->dma_dev->driver->owner);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
/* bfad_im_bsg_put_kobject - decrement the bfa refcnt */
|
||||
static void
|
||||
bfad_im_bsg_put_kobject(struct fc_bsg_job *job)
|
||||
{
|
||||
struct Scsi_Host *shost = job->shost;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
module_put(shost->dma_dev->driver->owner);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
int i;
|
||||
struct bfa_bsg_ioc_info_s *iocmd = (struct bfa_bsg_ioc_info_s *)cmd;
|
||||
struct bfad_im_port_s *im_port;
|
||||
struct bfa_port_attr_s pattr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcport_get_attr(&bfad->bfa, &pattr);
|
||||
iocmd->nwwn = pattr.nwwn;
|
||||
iocmd->pwwn = pattr.pwwn;
|
||||
iocmd->ioc_type = bfa_get_type(&bfad->bfa);
|
||||
iocmd->mac = bfa_get_mac(&bfad->bfa);
|
||||
iocmd->factory_mac = bfa_get_mfg_mac(&bfad->bfa);
|
||||
bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum);
|
||||
iocmd->factorynwwn = pattr.factorynwwn;
|
||||
iocmd->factorypwwn = pattr.factorypwwn;
|
||||
im_port = bfad->pport.im_port;
|
||||
iocmd->host = im_port->shost->host_no;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
strcpy(iocmd->name, bfad->adapter_name);
|
||||
strcpy(iocmd->port_name, bfad->port_name);
|
||||
strcpy(iocmd->hwpath, bfad->pci_name);
|
||||
|
||||
/* set adapter hw path */
|
||||
strcpy(iocmd->adapter_hwpath, bfad->pci_name);
|
||||
i = strlen(iocmd->adapter_hwpath) - 1;
|
||||
while (iocmd->adapter_hwpath[i] != '.')
|
||||
i--;
|
||||
iocmd->adapter_hwpath[i] = '\0';
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
struct bfa_bsg_ioc_attr_s *iocmd = (struct bfa_bsg_ioc_attr_s *)cmd;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_ioc_get_attr(&bfad->bfa.ioc, &iocmd->ioc_attr);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
/* fill in driver attr info */
|
||||
strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME);
|
||||
strncpy(iocmd->ioc_attr.driver_attr.driver_ver,
|
||||
BFAD_DRIVER_VERSION, BFA_VERSION_LEN);
|
||||
strcpy(iocmd->ioc_attr.driver_attr.fw_ver,
|
||||
iocmd->ioc_attr.adapter_attr.fw_ver);
|
||||
strcpy(iocmd->ioc_attr.driver_attr.bios_ver,
|
||||
iocmd->ioc_attr.adapter_attr.optrom_ver);
|
||||
|
||||
/* copy chip rev info first otherwise it will be overwritten */
|
||||
memcpy(bfad->pci_attr.chip_rev, iocmd->ioc_attr.pci_attr.chip_rev,
|
||||
sizeof(bfad->pci_attr.chip_rev));
|
||||
memcpy(&iocmd->ioc_attr.pci_attr, &bfad->pci_attr,
|
||||
sizeof(struct bfa_ioc_pci_attr_s));
|
||||
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
struct bfa_bsg_port_attr_s *iocmd = (struct bfa_bsg_port_attr_s *)cmd;
|
||||
struct bfa_lport_attr_s port_attr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcport_get_attr(&bfad->bfa, &iocmd->attr);
|
||||
bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
if (iocmd->attr.topology != BFA_PORT_TOPOLOGY_NONE)
|
||||
iocmd->attr.pid = port_attr.pid;
|
||||
else
|
||||
iocmd->attr.pid = 0;
|
||||
|
||||
iocmd->attr.port_type = port_attr.port_type;
|
||||
iocmd->attr.loopback = port_attr.loopback;
|
||||
iocmd->attr.authfail = port_attr.authfail;
|
||||
strncpy(iocmd->attr.port_symname.symname,
|
||||
port_attr.port_cfg.sym_name.symname,
|
||||
sizeof(port_attr.port_cfg.sym_name.symname));
|
||||
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
struct bfa_fcs_lport_s *fcs_port;
|
||||
struct bfa_bsg_lport_attr_s *iocmd = (struct bfa_bsg_lport_attr_s *)cmd;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
|
||||
iocmd->vf_id, iocmd->pwwn);
|
||||
if (fcs_port == NULL) {
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bfa_fcs_lport_get_attr(fcs_port, &iocmd->port_attr);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_rport_get_addr(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
struct bfa_bsg_rport_scsi_addr_s *iocmd =
|
||||
(struct bfa_bsg_rport_scsi_addr_s *)cmd;
|
||||
struct bfa_fcs_lport_s *fcs_port;
|
||||
struct bfa_fcs_itnim_s *fcs_itnim;
|
||||
struct bfad_itnim_s *drv_itnim;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
|
||||
iocmd->vf_id, iocmd->pwwn);
|
||||
if (fcs_port == NULL) {
|
||||
bfa_trc(bfad, 0);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fcs_itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
|
||||
if (fcs_itnim == NULL) {
|
||||
bfa_trc(bfad, 0);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drv_itnim = fcs_itnim->itnim_drv;
|
||||
|
||||
if (drv_itnim && drv_itnim->im_port)
|
||||
iocmd->host = drv_itnim->im_port->shost->host_no;
|
||||
else {
|
||||
bfa_trc(bfad, 0);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iocmd->target = drv_itnim->scsi_tgt_id;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
iocmd->bus = 0;
|
||||
iocmd->lun = 0;
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
|
||||
unsigned int payload_len)
|
||||
{
|
||||
struct bfa_bsg_fabric_get_lports_s *iocmd =
|
||||
(struct bfa_bsg_fabric_get_lports_s *)cmd;
|
||||
bfa_fcs_vf_t *fcs_vf;
|
||||
uint32_t nports = iocmd->nports;
|
||||
unsigned long flags;
|
||||
void *iocmd_bufptr;
|
||||
|
||||
if (nports == 0) {
|
||||
iocmd->status = BFA_STATUS_EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bfad_chk_iocmd_sz(payload_len,
|
||||
sizeof(struct bfa_bsg_fabric_get_lports_s),
|
||||
sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) {
|
||||
iocmd->status = BFA_STATUS_VERSION_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iocmd_bufptr = (char *)iocmd +
|
||||
sizeof(struct bfa_bsg_fabric_get_lports_s);
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
|
||||
if (fcs_vf == NULL) {
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_VFID;
|
||||
goto out;
|
||||
}
|
||||
bfa_fcs_vf_get_ports(fcs_vf, (wwn_t *)iocmd_bufptr, &nports);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
iocmd->nports = nports;
|
||||
iocmd->status = BFA_STATUS_OK;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_itnim_get_attr(struct bfad_s *bfad, void *cmd)
|
||||
{
|
||||
struct bfa_bsg_itnim_attr_s *iocmd = (struct bfa_bsg_itnim_attr_s *)cmd;
|
||||
struct bfa_fcs_lport_s *fcs_port;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
|
||||
iocmd->vf_id, iocmd->lpwwn);
|
||||
if (!fcs_port)
|
||||
iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
|
||||
else
|
||||
iocmd->status = bfa_fcs_itnim_attr_get(fcs_port,
|
||||
iocmd->rpwwn, &iocmd->attr);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
|
||||
unsigned int payload_len)
|
||||
{
|
||||
int rc = EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
case IOCMD_IOC_GET_INFO:
|
||||
rc = bfad_iocmd_ioc_get_info(bfad, iocmd);
|
||||
break;
|
||||
case IOCMD_IOC_GET_ATTR:
|
||||
rc = bfad_iocmd_ioc_get_attr(bfad, iocmd);
|
||||
break;
|
||||
case IOCMD_PORT_GET_ATTR:
|
||||
rc = bfad_iocmd_port_get_attr(bfad, iocmd);
|
||||
break;
|
||||
case IOCMD_LPORT_GET_ATTR:
|
||||
rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
|
||||
break;
|
||||
case IOCMD_RPORT_GET_ADDR:
|
||||
rc = bfad_iocmd_rport_get_addr(bfad, iocmd);
|
||||
break;
|
||||
case IOCMD_FABRIC_GET_LPORTS:
|
||||
rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len);
|
||||
break;
|
||||
case IOCMD_ITNIM_GET_ATTR:
|
||||
rc = bfad_iocmd_itnim_get_attr(bfad, iocmd);
|
||||
break;
|
||||
default:
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -rc;
|
||||
}
|
||||
|
||||
static int
|
||||
bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
|
||||
{
|
||||
uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) job->shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
void *payload_kbuf;
|
||||
int rc = -EINVAL;
|
||||
|
||||
/* Allocate a temp buffer to hold the passed in user space command */
|
||||
payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
|
||||
if (!payload_kbuf) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy the sg_list passed in to a linear buffer: holds the cmnd data */
|
||||
sg_copy_to_buffer(job->request_payload.sg_list,
|
||||
job->request_payload.sg_cnt, payload_kbuf,
|
||||
job->request_payload.payload_len);
|
||||
|
||||
/* Invoke IOCMD handler - to handle all the vendor command requests */
|
||||
rc = bfad_iocmd_handler(bfad, vendor_cmd, payload_kbuf,
|
||||
job->request_payload.payload_len);
|
||||
if (rc != BFA_STATUS_OK)
|
||||
goto error;
|
||||
|
||||
/* Copy the response data to the job->reply_payload sg_list */
|
||||
sg_copy_from_buffer(job->reply_payload.sg_list,
|
||||
job->reply_payload.sg_cnt,
|
||||
payload_kbuf,
|
||||
job->reply_payload.payload_len);
|
||||
|
||||
/* free the command buffer */
|
||||
kfree(payload_kbuf);
|
||||
|
||||
/* Fill the BSG job reply data */
|
||||
job->reply_len = job->reply_payload.payload_len;
|
||||
job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
|
||||
job->reply->result = rc;
|
||||
|
||||
job->job_done(job);
|
||||
return rc;
|
||||
error:
|
||||
/* free the command buffer */
|
||||
kfree(payload_kbuf);
|
||||
out:
|
||||
job->reply->result = rc;
|
||||
job->reply_len = sizeof(uint32_t);
|
||||
job->reply->reply_payload_rcv_len = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* FC passthru call backs */
|
||||
u64
|
||||
bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid)
|
||||
{
|
||||
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
|
||||
struct bfa_sge_s *sge;
|
||||
u64 addr;
|
||||
|
||||
sge = drv_fcxp->req_sge + sgeid;
|
||||
addr = (u64)(size_t) sge->sg_addr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32
|
||||
bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid)
|
||||
{
|
||||
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
|
||||
struct bfa_sge_s *sge;
|
||||
|
||||
sge = drv_fcxp->req_sge + sgeid;
|
||||
return sge->sg_len;
|
||||
}
|
||||
|
||||
u64
|
||||
bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid)
|
||||
{
|
||||
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
|
||||
struct bfa_sge_s *sge;
|
||||
u64 addr;
|
||||
|
||||
sge = drv_fcxp->rsp_sge + sgeid;
|
||||
addr = (u64)(size_t) sge->sg_addr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32
|
||||
bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid)
|
||||
{
|
||||
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
|
||||
struct bfa_sge_s *sge;
|
||||
|
||||
sge = drv_fcxp->rsp_sge + sgeid;
|
||||
return sge->sg_len;
|
||||
}
|
||||
|
||||
void
|
||||
bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
|
||||
bfa_status_t req_status, u32 rsp_len, u32 resid_len,
|
||||
struct fchs_s *rsp_fchs)
|
||||
{
|
||||
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
|
||||
|
||||
drv_fcxp->req_status = req_status;
|
||||
drv_fcxp->rsp_len = rsp_len;
|
||||
|
||||
/* bfa_fcxp will be automatically freed by BFA */
|
||||
drv_fcxp->bfa_fcxp = NULL;
|
||||
complete(&drv_fcxp->comp);
|
||||
}
|
||||
|
||||
struct bfad_buf_info *
|
||||
bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
|
||||
uint32_t payload_len, uint32_t *num_sgles)
|
||||
{
|
||||
struct bfad_buf_info *buf_base, *buf_info;
|
||||
struct bfa_sge_s *sg_table;
|
||||
int sge_num = 1;
|
||||
|
||||
buf_base = kzalloc((sizeof(struct bfad_buf_info) +
|
||||
sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL);
|
||||
if (!buf_base)
|
||||
return NULL;
|
||||
|
||||
sg_table = (struct bfa_sge_s *) (((uint8_t *)buf_base) +
|
||||
(sizeof(struct bfad_buf_info) * sge_num));
|
||||
|
||||
/* Allocate dma coherent memory */
|
||||
buf_info = buf_base;
|
||||
buf_info->size = payload_len;
|
||||
buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
|
||||
&buf_info->phys, GFP_KERNEL);
|
||||
if (!buf_info->virt)
|
||||
goto out_free_mem;
|
||||
|
||||
/* copy the linear bsg buffer to buf_info */
|
||||
memset(buf_info->virt, 0, buf_info->size);
|
||||
memcpy(buf_info->virt, payload_kbuf, buf_info->size);
|
||||
|
||||
/*
|
||||
* Setup SG table
|
||||
*/
|
||||
sg_table->sg_len = buf_info->size;
|
||||
sg_table->sg_addr = (void *)(size_t) buf_info->phys;
|
||||
|
||||
*num_sgles = sge_num;
|
||||
|
||||
return buf_base;
|
||||
|
||||
out_free_mem:
|
||||
kfree(buf_base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
|
||||
uint32_t num_sgles)
|
||||
{
|
||||
int i;
|
||||
struct bfad_buf_info *buf_info = buf_base;
|
||||
|
||||
if (buf_base) {
|
||||
for (i = 0; i < num_sgles; buf_info++, i++) {
|
||||
if (buf_info->virt != NULL)
|
||||
dma_free_coherent(&bfad->pcidev->dev,
|
||||
buf_info->size, buf_info->virt,
|
||||
buf_info->phys);
|
||||
}
|
||||
kfree(buf_base);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
|
||||
bfa_bsg_fcpt_t *bsg_fcpt)
|
||||
{
|
||||
struct bfa_fcxp_s *hal_fcxp;
|
||||
struct bfad_s *bfad = drv_fcxp->port->bfad;
|
||||
unsigned long flags;
|
||||
uint8_t lp_tag;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
|
||||
/* Allocate bfa_fcxp structure */
|
||||
hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
|
||||
drv_fcxp->num_req_sgles,
|
||||
drv_fcxp->num_rsp_sgles,
|
||||
bfad_fcxp_get_req_sgaddr_cb,
|
||||
bfad_fcxp_get_req_sglen_cb,
|
||||
bfad_fcxp_get_rsp_sgaddr_cb,
|
||||
bfad_fcxp_get_rsp_sglen_cb);
|
||||
if (!hal_fcxp) {
|
||||
bfa_trc(bfad, 0);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
return BFA_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
drv_fcxp->bfa_fcxp = hal_fcxp;
|
||||
|
||||
lp_tag = bfa_lps_get_tag_from_pid(&bfad->bfa, bsg_fcpt->fchs.s_id);
|
||||
|
||||
bfa_fcxp_send(hal_fcxp, drv_fcxp->bfa_rport, bsg_fcpt->vf_id, lp_tag,
|
||||
bsg_fcpt->cts, bsg_fcpt->cos,
|
||||
job->request_payload.payload_len,
|
||||
&bsg_fcpt->fchs, bfad_send_fcpt_cb, bfad,
|
||||
job->reply_payload.payload_len, bsg_fcpt->tsecs);
|
||||
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
|
||||
{
|
||||
struct bfa_bsg_data *bsg_data;
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) job->shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
bfa_bsg_fcpt_t *bsg_fcpt;
|
||||
struct bfad_fcxp *drv_fcxp;
|
||||
struct bfa_fcs_lport_s *fcs_port;
|
||||
struct bfa_fcs_rport_s *fcs_rport;
|
||||
uint32_t command_type = job->request->msgcode;
|
||||
unsigned long flags;
|
||||
struct bfad_buf_info *rsp_buf_info;
|
||||
void *req_kbuf = NULL, *rsp_kbuf = NULL;
|
||||
int rc = -EINVAL;
|
||||
|
||||
job->reply_len = sizeof(uint32_t); /* Atleast uint32_t reply_len */
|
||||
job->reply->reply_payload_rcv_len = 0;
|
||||
|
||||
/* Get the payload passed in from userspace */
|
||||
bsg_data = (struct bfa_bsg_data *) (((char *)job->request) +
|
||||
sizeof(struct fc_bsg_request));
|
||||
if (bsg_data == NULL)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Allocate buffer for bsg_fcpt and do a copy_from_user op for payload
|
||||
* buffer of size bsg_data->payload_len
|
||||
*/
|
||||
bsg_fcpt = (struct bfa_bsg_fcpt_s *)
|
||||
kzalloc(bsg_data->payload_len, GFP_KERNEL);
|
||||
if (!bsg_fcpt)
|
||||
goto out;
|
||||
|
||||
if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
|
||||
bsg_data->payload_len)) {
|
||||
kfree(bsg_fcpt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
drv_fcxp = kzalloc(sizeof(struct bfad_fcxp), GFP_KERNEL);
|
||||
if (drv_fcxp == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, bsg_fcpt->vf_id,
|
||||
bsg_fcpt->lpwwn);
|
||||
if (fcs_port == NULL) {
|
||||
bsg_fcpt->status = BFA_STATUS_UNKNOWN_LWWN;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
/* Check if the port is online before sending FC Passthru cmd */
|
||||
if (!bfa_fcs_lport_is_online(fcs_port)) {
|
||||
bsg_fcpt->status = BFA_STATUS_PORT_OFFLINE;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
drv_fcxp->port = fcs_port->bfad_port;
|
||||
|
||||
if (drv_fcxp->port->bfad == 0)
|
||||
drv_fcxp->port->bfad = bfad;
|
||||
|
||||
/* Fetch the bfa_rport - if nexus needed */
|
||||
if (command_type == FC_BSG_HST_ELS_NOLOGIN ||
|
||||
command_type == FC_BSG_HST_CT) {
|
||||
/* BSG HST commands: no nexus needed */
|
||||
drv_fcxp->bfa_rport = NULL;
|
||||
|
||||
} else if (command_type == FC_BSG_RPT_ELS ||
|
||||
command_type == FC_BSG_RPT_CT) {
|
||||
/* BSG RPT commands: nexus needed */
|
||||
fcs_rport = bfa_fcs_lport_get_rport_by_pwwn(fcs_port,
|
||||
bsg_fcpt->dpwwn);
|
||||
if (fcs_rport == NULL) {
|
||||
bsg_fcpt->status = BFA_STATUS_UNKNOWN_RWWN;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
drv_fcxp->bfa_rport = fcs_rport->bfa_rport;
|
||||
|
||||
} else { /* Unknown BSG msgcode; return -EINVAL */
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
/* allocate memory for req / rsp buffers */
|
||||
req_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
|
||||
if (!req_kbuf) {
|
||||
printk(KERN_INFO "bfa %s: fcpt request buffer alloc failed\n",
|
||||
bfad->pci_name);
|
||||
rc = -ENOMEM;
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
rsp_kbuf = kzalloc(job->reply_payload.payload_len, GFP_KERNEL);
|
||||
if (!rsp_kbuf) {
|
||||
printk(KERN_INFO "bfa %s: fcpt response buffer alloc failed\n",
|
||||
bfad->pci_name);
|
||||
rc = -ENOMEM;
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
/* map req sg - copy the sg_list passed in to the linear buffer */
|
||||
sg_copy_to_buffer(job->request_payload.sg_list,
|
||||
job->request_payload.sg_cnt, req_kbuf,
|
||||
job->request_payload.payload_len);
|
||||
|
||||
drv_fcxp->reqbuf_info = bfad_fcxp_map_sg(bfad, req_kbuf,
|
||||
job->request_payload.payload_len,
|
||||
&drv_fcxp->num_req_sgles);
|
||||
if (!drv_fcxp->reqbuf_info) {
|
||||
printk(KERN_INFO "bfa %s: fcpt request fcxp_map_sg failed\n",
|
||||
bfad->pci_name);
|
||||
rc = -ENOMEM;
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
drv_fcxp->req_sge = (struct bfa_sge_s *)
|
||||
(((uint8_t *)drv_fcxp->reqbuf_info) +
|
||||
(sizeof(struct bfad_buf_info) *
|
||||
drv_fcxp->num_req_sgles));
|
||||
|
||||
/* map rsp sg */
|
||||
drv_fcxp->rspbuf_info = bfad_fcxp_map_sg(bfad, rsp_kbuf,
|
||||
job->reply_payload.payload_len,
|
||||
&drv_fcxp->num_rsp_sgles);
|
||||
if (!drv_fcxp->rspbuf_info) {
|
||||
printk(KERN_INFO "bfa %s: fcpt response fcxp_map_sg failed\n",
|
||||
bfad->pci_name);
|
||||
rc = -ENOMEM;
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
rsp_buf_info = (struct bfad_buf_info *)drv_fcxp->rspbuf_info;
|
||||
drv_fcxp->rsp_sge = (struct bfa_sge_s *)
|
||||
(((uint8_t *)drv_fcxp->rspbuf_info) +
|
||||
(sizeof(struct bfad_buf_info) *
|
||||
drv_fcxp->num_rsp_sgles));
|
||||
|
||||
/* fcxp send */
|
||||
init_completion(&drv_fcxp->comp);
|
||||
rc = bfad_fcxp_bsg_send(job, drv_fcxp, bsg_fcpt);
|
||||
if (rc == BFA_STATUS_OK) {
|
||||
wait_for_completion(&drv_fcxp->comp);
|
||||
bsg_fcpt->status = drv_fcxp->req_status;
|
||||
} else {
|
||||
bsg_fcpt->status = rc;
|
||||
goto out_free_mem;
|
||||
}
|
||||
|
||||
/* fill the job->reply data */
|
||||
if (drv_fcxp->req_status == BFA_STATUS_OK) {
|
||||
job->reply_len = drv_fcxp->rsp_len;
|
||||
job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
|
||||
job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
|
||||
} else {
|
||||
job->reply->reply_payload_rcv_len =
|
||||
sizeof(struct fc_bsg_ctels_reply);
|
||||
job->reply_len = sizeof(uint32_t);
|
||||
job->reply->reply_data.ctels_reply.status =
|
||||
FC_CTELS_STATUS_REJECT;
|
||||
}
|
||||
|
||||
/* Copy the response data to the reply_payload sg list */
|
||||
sg_copy_from_buffer(job->reply_payload.sg_list,
|
||||
job->reply_payload.sg_cnt,
|
||||
(uint8_t *)rsp_buf_info->virt,
|
||||
job->reply_payload.payload_len);
|
||||
|
||||
out_free_mem:
|
||||
bfad_fcxp_free_mem(bfad, drv_fcxp->rspbuf_info,
|
||||
drv_fcxp->num_rsp_sgles);
|
||||
bfad_fcxp_free_mem(bfad, drv_fcxp->reqbuf_info,
|
||||
drv_fcxp->num_req_sgles);
|
||||
kfree(req_kbuf);
|
||||
kfree(rsp_kbuf);
|
||||
|
||||
/* Need a copy to user op */
|
||||
if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
|
||||
bsg_data->payload_len))
|
||||
rc = -EIO;
|
||||
|
||||
kfree(bsg_fcpt);
|
||||
kfree(drv_fcxp);
|
||||
out:
|
||||
job->reply->result = rc;
|
||||
|
||||
if (rc == BFA_STATUS_OK)
|
||||
job->job_done(job);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
bfad_im_bsg_request(struct fc_bsg_job *job)
|
||||
{
|
||||
uint32_t rc = BFA_STATUS_OK;
|
||||
|
||||
/* Increment the bfa module refcnt - if bsg request is in service */
|
||||
bfad_im_bsg_get_kobject(job);
|
||||
|
||||
switch (job->request->msgcode) {
|
||||
case FC_BSG_HST_VENDOR:
|
||||
/* Process BSG HST Vendor requests */
|
||||
rc = bfad_im_bsg_vendor_request(job);
|
||||
break;
|
||||
case FC_BSG_HST_ELS_NOLOGIN:
|
||||
case FC_BSG_RPT_ELS:
|
||||
case FC_BSG_HST_CT:
|
||||
case FC_BSG_RPT_CT:
|
||||
/* Process BSG ELS/CT commands */
|
||||
rc = bfad_im_bsg_els_ct_request(job);
|
||||
break;
|
||||
default:
|
||||
job->reply->result = rc = -EINVAL;
|
||||
job->reply->reply_payload_rcv_len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Decrement the bfa module refcnt - on completion of bsg request */
|
||||
bfad_im_bsg_put_kobject(job);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
bfad_im_bsg_timeout(struct fc_bsg_job *job)
|
||||
{
|
||||
/* Don't complete the BSG job request - return -EAGAIN
|
||||
* to reset bsg job timeout : for ELS/CT pass thru we
|
||||
* already have timer to track the request.
|
||||
*/
|
||||
return -EAGAIN;
|
||||
}
|
135
drivers/scsi/bfa/bfad_bsg.h
Normal file
135
drivers/scsi/bfa/bfad_bsg.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
|
||||
* All rights reserved
|
||||
* www.brocade.com
|
||||
*
|
||||
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (GPL) Version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef BFAD_BSG_H
|
||||
#define BFAD_BSG_H
|
||||
|
||||
#include "bfa_defs.h"
|
||||
#include "bfa_defs_fcs.h"
|
||||
|
||||
/* Definitions of vendor unique structures and command codes passed in
|
||||
* using FC_BSG_HST_VENDOR message code.
|
||||
*/
|
||||
enum {
|
||||
IOCMD_IOC_GET_ATTR = 0x1,
|
||||
IOCMD_IOC_GET_INFO,
|
||||
IOCMD_PORT_GET_ATTR,
|
||||
IOCMD_LPORT_GET_ATTR,
|
||||
IOCMD_RPORT_GET_ADDR,
|
||||
IOCMD_FABRIC_GET_LPORTS,
|
||||
IOCMD_ITNIM_GET_ATTR,
|
||||
};
|
||||
|
||||
struct bfa_bsg_ioc_info_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 rsvd;
|
||||
char serialnum[64];
|
||||
char hwpath[BFA_STRING_32];
|
||||
char adapter_hwpath[BFA_STRING_32];
|
||||
char guid[BFA_ADAPTER_SYM_NAME_LEN*2];
|
||||
char name[BFA_ADAPTER_SYM_NAME_LEN];
|
||||
char port_name[BFA_ADAPTER_SYM_NAME_LEN];
|
||||
char eth_name[BFA_ADAPTER_SYM_NAME_LEN];
|
||||
wwn_t pwwn;
|
||||
wwn_t nwwn;
|
||||
wwn_t factorypwwn;
|
||||
wwn_t factorynwwn;
|
||||
mac_t mac;
|
||||
mac_t factory_mac; /* Factory mac address */
|
||||
mac_t current_mac; /* Currently assigned mac address */
|
||||
enum bfa_ioc_type_e ioc_type;
|
||||
u16 pvid; /* Port vlan id */
|
||||
u16 rsvd1;
|
||||
u32 host;
|
||||
u32 bandwidth; /* For PF support */
|
||||
u32 rsvd2;
|
||||
};
|
||||
|
||||
struct bfa_bsg_ioc_attr_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 rsvd;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
};
|
||||
|
||||
struct bfa_bsg_port_attr_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 rsvd;
|
||||
struct bfa_port_attr_s attr;
|
||||
};
|
||||
|
||||
struct bfa_bsg_lport_attr_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 vf_id;
|
||||
wwn_t pwwn;
|
||||
struct bfa_lport_attr_s port_attr;
|
||||
};
|
||||
|
||||
struct bfa_bsg_rport_scsi_addr_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 vf_id;
|
||||
wwn_t pwwn;
|
||||
wwn_t rpwwn;
|
||||
u32 host;
|
||||
u32 bus;
|
||||
u32 target;
|
||||
u32 lun;
|
||||
};
|
||||
|
||||
struct bfa_bsg_fabric_get_lports_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 vf_id;
|
||||
u64 buf_ptr;
|
||||
u32 nports;
|
||||
u32 rsvd;
|
||||
};
|
||||
|
||||
struct bfa_bsg_itnim_attr_s {
|
||||
bfa_status_t status;
|
||||
u16 bfad_num;
|
||||
u16 vf_id;
|
||||
wwn_t lpwwn;
|
||||
wwn_t rpwwn;
|
||||
struct bfa_itnim_attr_s attr;
|
||||
};
|
||||
|
||||
struct bfa_bsg_fcpt_s {
|
||||
bfa_status_t status;
|
||||
u16 vf_id;
|
||||
wwn_t lpwwn;
|
||||
wwn_t dpwwn;
|
||||
u32 tsecs;
|
||||
int cts;
|
||||
enum fc_cos cos;
|
||||
struct fchs_s fchs;
|
||||
};
|
||||
#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s
|
||||
|
||||
struct bfa_bsg_data {
|
||||
int payload_len;
|
||||
void *payload;
|
||||
};
|
||||
|
||||
#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz) \
|
||||
(((__payload_len) != ((__hdrsz) + (__bufsz))) ? \
|
||||
BFA_STATUS_FAILED : BFA_STATUS_OK)
|
||||
|
||||
#endif /* BFAD_BSG_H */
|
@ -43,6 +43,7 @@
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_bsg_fc.h>
|
||||
|
||||
#include "bfa_modules.h"
|
||||
#include "bfa_fcs.h"
|
||||
@ -110,6 +111,7 @@ struct bfad_msix_s {
|
||||
enum {
|
||||
BFA_TRC_LDRV_BFAD = 1,
|
||||
BFA_TRC_LDRV_IM = 2,
|
||||
BFA_TRC_LDRV_BSG = 3,
|
||||
};
|
||||
|
||||
enum bfad_port_pvb_type {
|
||||
|
@ -778,6 +778,7 @@ struct scsi_host_template bfad_im_scsi_host_template = {
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = bfad_im_host_attrs,
|
||||
.max_sectors = 0xFFFF,
|
||||
.vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
|
||||
};
|
||||
|
||||
struct scsi_host_template bfad_im_vport_template = {
|
||||
|
@ -141,4 +141,7 @@ extern struct device_attribute *bfad_im_vport_attrs[];
|
||||
|
||||
irqreturn_t bfad_intx(int irq, void *dev_id);
|
||||
|
||||
int bfad_im_bsg_request(struct fc_bsg_job *job);
|
||||
int bfad_im_bsg_timeout(struct fc_bsg_job *job);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user