mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 15:20:58 +07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (34 commits) [SCSI] qla2xxx: Fix NULL ptr deref bug in fail path during queue create [SCSI] st: fix possible memory use after free after MTSETBLK ioctl [SCSI] be2iscsi: Moving to pci_pools v3 [SCSI] libiscsi: iscsi_session_setup to allow for private space [SCSI] be2iscsi: add 10Gbps iSCSI - BladeEngine 2 driver [SCSI] zfcp: Fix hang when offlining device with offline chpid [SCSI] zfcp: Fix lockdep warning when offlining device with offline chpid [SCSI] zfcp: Fix oops during shutdown of offline device [SCSI] zfcp: Fix initial device and cfdc for delayed adapter allocation [SCSI] zfcp: correctly initialize unchained requests [SCSI] mpt2sas: Bump version 02.100.03.00 [SCSI] mpt2sas: Support dev remove when phy status is MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT [SCSI] mpt2sas: Timeout occurred within the HANDSHAKE logic while waiting on firmware to ACK. [SCSI] mpt2sas: Call init_completion on a per request basis. [SCSI] mpt2sas: Target Reset will be issued from Interrupt context. [SCSI] mpt2sas: Added SCSIIO, Internal and high priority memory pools to support multiple TM [SCSI] mpt2sas: Copyright change to 2009. [SCSI] mpt2sas: Added mpi2_history.txt for MPI2 headers. [SCSI] mpt2sas: Update driver to MPI2 REV K headers. [SCSI] bfa: Brocade BFA FC SCSI driver ...
This commit is contained in:
commit
69585dd69e
@ -3,6 +3,25 @@ HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop)
|
||||
Controller Register Map
|
||||
-------------------------
|
||||
|
||||
For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2:
|
||||
|
||||
BAR0 offset Register
|
||||
0x11C5C Link Interface IRQ Set
|
||||
0x11C60 Link Interface IRQ Clear
|
||||
|
||||
BAR2 offset Register
|
||||
0x10 Inbound Message Register 0
|
||||
0x14 Inbound Message Register 1
|
||||
0x18 Outbound Message Register 0
|
||||
0x1C Outbound Message Register 1
|
||||
0x20 Inbound Doorbell Register
|
||||
0x24 Inbound Interrupt Status Register
|
||||
0x28 Inbound Interrupt Mask Register
|
||||
0x30 Outbound Interrupt Status Register
|
||||
0x34 Outbound Interrupt Mask Register
|
||||
0x40 Inbound Queue Port
|
||||
0x44 Outbound Queue Port
|
||||
|
||||
For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0:
|
||||
|
||||
BAR0 offset Register
|
||||
@ -93,7 +112,7 @@ The driver exposes following sysfs attributes:
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
|
||||
Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -1231,6 +1231,13 @@ L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/tg3.*
|
||||
|
||||
BROCADE BFA FC SCSI DRIVER
|
||||
P: Jing Huang
|
||||
M: huangj@brocade.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/scsi/bfa/
|
||||
|
||||
BSG (block layer generic sg v4 driver)
|
||||
M: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
@ -4646,6 +4653,14 @@ F: drivers/ata/
|
||||
F: include/linux/ata.h
|
||||
F: include/linux/libata.h
|
||||
|
||||
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
|
||||
P: Jayamohan Kallickal
|
||||
M: jayamohank@serverengines.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
W: http://www.serverengines.com
|
||||
S: Supported
|
||||
F: drivers/scsi/be2iscsi/
|
||||
|
||||
SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
|
||||
M: Sathya Perla <sathyap@serverengines.com>
|
||||
M: Subbu Seetharaman <subbus@serverengines.com>
|
||||
|
@ -426,7 +426,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
|
||||
* because we preallocate so many resources
|
||||
*/
|
||||
cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
|
||||
ISCSI_DEF_XMIT_CMDS_MAX,
|
||||
ISCSI_DEF_XMIT_CMDS_MAX, 0,
|
||||
sizeof(struct iscsi_iser_task),
|
||||
initial_cmdsn, 0);
|
||||
if (!cls_session)
|
||||
|
@ -80,28 +80,35 @@ int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
|
||||
|
||||
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
||||
{
|
||||
struct ccw_device *ccwdev;
|
||||
struct zfcp_adapter *adapter;
|
||||
struct zfcp_port *port;
|
||||
struct zfcp_unit *unit;
|
||||
|
||||
mutex_lock(&zfcp_data.config_mutex);
|
||||
read_lock_irq(&zfcp_data.config_lock);
|
||||
adapter = zfcp_get_adapter_by_busid(busid);
|
||||
if (adapter)
|
||||
zfcp_adapter_get(adapter);
|
||||
read_unlock_irq(&zfcp_data.config_lock);
|
||||
ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
||||
if (!ccwdev)
|
||||
return;
|
||||
|
||||
if (ccw_device_set_online(ccwdev))
|
||||
goto out_ccwdev;
|
||||
|
||||
mutex_lock(&zfcp_data.config_mutex);
|
||||
adapter = dev_get_drvdata(&ccwdev->dev);
|
||||
if (!adapter)
|
||||
goto out_adapter;
|
||||
port = zfcp_port_enqueue(adapter, wwpn, 0, 0);
|
||||
if (IS_ERR(port))
|
||||
goto out_unlock;
|
||||
zfcp_adapter_get(adapter);
|
||||
|
||||
port = zfcp_get_port_by_wwpn(adapter, wwpn);
|
||||
if (!port)
|
||||
goto out_port;
|
||||
|
||||
zfcp_port_get(port);
|
||||
unit = zfcp_unit_enqueue(port, lun);
|
||||
if (IS_ERR(unit))
|
||||
goto out_unit;
|
||||
mutex_unlock(&zfcp_data.config_mutex);
|
||||
ccw_device_set_online(adapter->ccw_device);
|
||||
|
||||
zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
|
||||
zfcp_erp_wait(adapter);
|
||||
flush_work(&unit->scsi_work);
|
||||
|
||||
@ -111,8 +118,10 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
||||
zfcp_port_put(port);
|
||||
out_port:
|
||||
zfcp_adapter_put(adapter);
|
||||
out_adapter:
|
||||
out_unlock:
|
||||
mutex_unlock(&zfcp_data.config_mutex);
|
||||
out_ccwdev:
|
||||
put_device(&ccwdev->dev);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -593,10 +602,8 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
cancel_work_sync(&adapter->scan_work);
|
||||
cancel_work_sync(&adapter->stat_work);
|
||||
zfcp_fc_wka_ports_force_offline(adapter->gs);
|
||||
zfcp_adapter_scsi_unregister(adapter);
|
||||
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
|
||||
&zfcp_sysfs_adapter_attrs);
|
||||
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
|
||||
|
@ -102,6 +102,14 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
||||
if (!adapter)
|
||||
goto out;
|
||||
mutex_unlock(&zfcp_data.config_mutex);
|
||||
|
||||
cancel_work_sync(&adapter->scan_work);
|
||||
|
||||
mutex_lock(&zfcp_data.config_mutex);
|
||||
|
||||
/* this also removes the scsi devices, so call it first */
|
||||
zfcp_adapter_scsi_unregister(adapter);
|
||||
|
||||
write_lock_irq(&zfcp_data.config_lock);
|
||||
list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
|
||||
@ -117,11 +125,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
||||
write_unlock_irq(&zfcp_data.config_lock);
|
||||
|
||||
list_for_each_entry_safe(port, p, &port_remove_lh, list) {
|
||||
list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
|
||||
if (unit->device)
|
||||
scsi_remove_device(unit->device);
|
||||
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
|
||||
zfcp_unit_dequeue(unit);
|
||||
}
|
||||
zfcp_port_dequeue(port);
|
||||
}
|
||||
wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
|
||||
@ -192,13 +197,9 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
|
||||
|
||||
mutex_lock(&zfcp_data.config_mutex);
|
||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
||||
if (!adapter)
|
||||
goto out;
|
||||
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
|
||||
zfcp_erp_wait(adapter);
|
||||
mutex_unlock(&zfcp_data.config_mutex);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -253,13 +254,17 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
|
||||
|
||||
mutex_lock(&zfcp_data.config_mutex);
|
||||
adapter = dev_get_drvdata(&cdev->dev);
|
||||
if (!adapter)
|
||||
goto out;
|
||||
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
|
||||
zfcp_erp_wait(adapter);
|
||||
zfcp_erp_thread_kill(adapter);
|
||||
out:
|
||||
mutex_unlock(&zfcp_data.config_mutex);
|
||||
}
|
||||
|
||||
static struct ccw_driver zfcp_ccw_driver = {
|
||||
struct ccw_driver zfcp_ccw_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "zfcp",
|
||||
.ids = zfcp_ccw_device_id,
|
||||
@ -284,20 +289,3 @@ int __init zfcp_ccw_register(void)
|
||||
{
|
||||
return ccw_driver_register(&zfcp_ccw_driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_get_adapter_by_busid - find zfcp_adapter struct
|
||||
* @busid: bus id string of zfcp adapter to find
|
||||
*/
|
||||
struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
|
||||
{
|
||||
struct ccw_device *ccw_device;
|
||||
struct zfcp_adapter *adapter = NULL;
|
||||
|
||||
ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
||||
if (ccw_device) {
|
||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
||||
put_device(&ccw_device->dev);
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
|
@ -86,8 +86,23 @@ static int zfcp_cfdc_copy_to_user(void __user *user_buffer,
|
||||
static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
|
||||
{
|
||||
char busid[9];
|
||||
struct ccw_device *ccwdev;
|
||||
struct zfcp_adapter *adapter = NULL;
|
||||
|
||||
snprintf(busid, sizeof(busid), "0.0.%04x", devno);
|
||||
return zfcp_get_adapter_by_busid(busid);
|
||||
ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
||||
if (!ccwdev)
|
||||
goto out;
|
||||
|
||||
adapter = dev_get_drvdata(&ccwdev->dev);
|
||||
if (!adapter)
|
||||
goto out_put;
|
||||
|
||||
zfcp_adapter_get(adapter);
|
||||
out_put:
|
||||
put_device(&ccwdev->dev);
|
||||
out:
|
||||
return adapter;
|
||||
}
|
||||
|
||||
static int zfcp_cfdc_set_fsf(struct zfcp_fsf_cfdc *fsf_cfdc, int command)
|
||||
|
@ -28,7 +28,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
|
||||
/* zfcp_ccw.c */
|
||||
extern int zfcp_ccw_register(void);
|
||||
extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
|
||||
extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
|
||||
extern struct ccw_driver zfcp_ccw_driver;
|
||||
|
||||
/* zfcp_cfdc.c */
|
||||
extern struct miscdevice zfcp_cfdc_misc;
|
||||
|
@ -1058,11 +1058,25 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
|
||||
bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
|
||||
SBAL_FLAGS0_TYPE_WRITE_READ,
|
||||
sg_resp, max_sbals);
|
||||
req->qtcb->bottom.support.resp_buf_length = bytes;
|
||||
if (bytes <= 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
|
||||
struct scatterlist *sg_req,
|
||||
struct scatterlist *sg_resp,
|
||||
int max_sbals)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* common settings for ct/gs and els requests */
|
||||
req->qtcb->bottom.support.resp_buf_length = bytes;
|
||||
req->qtcb->bottom.support.service_class = FSF_CLASS_3;
|
||||
req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
|
||||
zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
|
||||
@ -1094,8 +1108,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
|
||||
FSF_MAX_SBALS_PER_REQ);
|
||||
ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
|
||||
FSF_MAX_SBALS_PER_REQ);
|
||||
if (ret)
|
||||
goto failed_send;
|
||||
|
||||
@ -1192,7 +1206,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
|
||||
}
|
||||
|
||||
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
|
||||
ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
|
||||
ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, 2);
|
||||
|
||||
if (ret)
|
||||
goto failed_send;
|
||||
|
@ -366,6 +366,7 @@ config ISCSI_TCP
|
||||
|
||||
source "drivers/scsi/cxgb3i/Kconfig"
|
||||
source "drivers/scsi/bnx2i/Kconfig"
|
||||
source "drivers/scsi/be2iscsi/Kconfig"
|
||||
|
||||
config SGIWD93_SCSI
|
||||
tristate "SGI WD93C93 SCSI Driver"
|
||||
@ -1827,6 +1828,16 @@ config SCSI_SRP
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called libsrp.
|
||||
|
||||
config SCSI_BFA_FC
|
||||
tristate "Brocade BFA Fibre Channel Support"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_FC_ATTRS
|
||||
help
|
||||
This bfa driver supports all Brocade PCIe FC/FCOE host adapters.
|
||||
|
||||
To compile this driver as a module, choose M here. The module will
|
||||
be called bfa.
|
||||
|
||||
endif # SCSI_LOWLEVEL
|
||||
|
||||
source "drivers/scsi/pcmcia/Kconfig"
|
||||
|
@ -86,6 +86,7 @@ obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
|
||||
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
|
||||
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx/
|
||||
obj-$(CONFIG_SCSI_LPFC) += lpfc/
|
||||
obj-$(CONFIG_SCSI_BFA_FC) += bfa/
|
||||
obj-$(CONFIG_SCSI_PAS16) += pas16.o
|
||||
obj-$(CONFIG_SCSI_T128) += t128.o
|
||||
obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o
|
||||
@ -130,6 +131,7 @@ obj-$(CONFIG_SCSI_MVSAS) += mvsas/
|
||||
obj-$(CONFIG_PS3_ROM) += ps3rom.o
|
||||
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
|
||||
obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
|
||||
obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
|
||||
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
|
||||
|
||||
obj-$(CONFIG_ARM) += arm/
|
||||
|
8
drivers/scsi/be2iscsi/Kconfig
Normal file
8
drivers/scsi/be2iscsi/Kconfig
Normal file
@ -0,0 +1,8 @@
|
||||
config BE2ISCSI
|
||||
tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_ISCSI_ATTRS
|
||||
|
||||
help
|
||||
This driver implements the iSCSI functionality for ServerEngines'
|
||||
10Gbps Storage adapter - BladeEngine 2.
|
8
drivers/scsi/be2iscsi/Makefile
Normal file
8
drivers/scsi/be2iscsi/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
|
||||
#
|
||||
#
|
||||
|
||||
obj-$(CONFIG_BE2ISCSI) += be2iscsi.o
|
||||
|
||||
be2iscsi-y := be_iscsi.o be_main.o be_mgmt.o be_cmds.o
|
183
drivers/scsi/be2iscsi/be.h
Normal file
183
drivers/scsi/be2iscsi/be.h
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*/
|
||||
|
||||
#ifndef BEISCSI_H
|
||||
#define BEISCSI_H
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define FW_VER_LEN 32
|
||||
|
||||
struct be_dma_mem {
|
||||
void *va;
|
||||
dma_addr_t dma;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct be_queue_info {
|
||||
struct be_dma_mem dma_mem;
|
||||
u16 len;
|
||||
u16 entry_size; /* Size of an element in the queue */
|
||||
u16 id;
|
||||
u16 tail, head;
|
||||
bool created;
|
||||
atomic_t used; /* Number of valid elements in the queue */
|
||||
};
|
||||
|
||||
static inline u32 MODULO(u16 val, u16 limit)
|
||||
{
|
||||
WARN_ON(limit & (limit - 1));
|
||||
return val & (limit - 1);
|
||||
}
|
||||
|
||||
static inline void index_inc(u16 *index, u16 limit)
|
||||
{
|
||||
*index = MODULO((*index + 1), limit);
|
||||
}
|
||||
|
||||
static inline void *queue_head_node(struct be_queue_info *q)
|
||||
{
|
||||
return q->dma_mem.va + q->head * q->entry_size;
|
||||
}
|
||||
|
||||
static inline void *queue_tail_node(struct be_queue_info *q)
|
||||
{
|
||||
return q->dma_mem.va + q->tail * q->entry_size;
|
||||
}
|
||||
|
||||
static inline void queue_head_inc(struct be_queue_info *q)
|
||||
{
|
||||
index_inc(&q->head, q->len);
|
||||
}
|
||||
|
||||
static inline void queue_tail_inc(struct be_queue_info *q)
|
||||
{
|
||||
index_inc(&q->tail, q->len);
|
||||
}
|
||||
|
||||
/*ISCSI */
|
||||
|
||||
struct be_eq_obj {
|
||||
struct be_queue_info q;
|
||||
char desc[32];
|
||||
|
||||
/* Adaptive interrupt coalescing (AIC) info */
|
||||
bool enable_aic;
|
||||
u16 min_eqd; /* in usecs */
|
||||
u16 max_eqd; /* in usecs */
|
||||
u16 cur_eqd; /* in usecs */
|
||||
};
|
||||
|
||||
struct be_mcc_obj {
|
||||
struct be_queue_info *q;
|
||||
struct be_queue_info *cq;
|
||||
};
|
||||
|
||||
struct be_ctrl_info {
|
||||
u8 __iomem *csr;
|
||||
u8 __iomem *db; /* Door Bell */
|
||||
u8 __iomem *pcicfg; /* PCI config space */
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* Mbox used for cmd request/response */
|
||||
spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
|
||||
struct be_dma_mem mbox_mem;
|
||||
/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
|
||||
* is stored for freeing purpose */
|
||||
struct be_dma_mem mbox_mem_alloced;
|
||||
|
||||
/* MCC Rings */
|
||||
struct be_mcc_obj mcc_obj;
|
||||
spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
|
||||
spinlock_t mcc_cq_lock;
|
||||
|
||||
/* MCC Async callback */
|
||||
void (*async_cb) (void *adapter, bool link_up);
|
||||
void *adapter_ctxt;
|
||||
};
|
||||
|
||||
#include "be_cmds.h"
|
||||
|
||||
#define PAGE_SHIFT_4K 12
|
||||
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
|
||||
|
||||
/* Returns number of pages spanned by the data starting at the given addr */
|
||||
#define PAGES_4K_SPANNED(_address, size) \
|
||||
((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
|
||||
(size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
|
||||
|
||||
/* Byte offset into the page corresponding to given address */
|
||||
#define OFFSET_IN_PAGE(addr) \
|
||||
((size_t)(addr) & (PAGE_SIZE_4K-1))
|
||||
|
||||
/* Returns bit offset within a DWORD of a bitfield */
|
||||
#define AMAP_BIT_OFFSET(_struct, field) \
|
||||
(((size_t)&(((_struct *)0)->field))%32)
|
||||
|
||||
/* Returns the bit mask of the field that is NOT shifted into location. */
|
||||
static inline u32 amap_mask(u32 bitsize)
|
||||
{
|
||||
return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1);
|
||||
}
|
||||
|
||||
static inline void amap_set(void *ptr, u32 dw_offset, u32 mask,
|
||||
u32 offset, u32 value)
|
||||
{
|
||||
u32 *dw = (u32 *) ptr + dw_offset;
|
||||
*dw &= ~(mask << offset);
|
||||
*dw |= (mask & value) << offset;
|
||||
}
|
||||
|
||||
#define AMAP_SET_BITS(_struct, field, ptr, val) \
|
||||
amap_set(ptr, \
|
||||
offsetof(_struct, field)/32, \
|
||||
amap_mask(sizeof(((_struct *)0)->field)), \
|
||||
AMAP_BIT_OFFSET(_struct, field), \
|
||||
val)
|
||||
|
||||
static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
|
||||
{
|
||||
u32 *dw = ptr;
|
||||
return mask & (*(dw + dw_offset) >> offset);
|
||||
}
|
||||
|
||||
#define AMAP_GET_BITS(_struct, field, ptr) \
|
||||
amap_get(ptr, \
|
||||
offsetof(_struct, field)/32, \
|
||||
amap_mask(sizeof(((_struct *)0)->field)), \
|
||||
AMAP_BIT_OFFSET(_struct, field))
|
||||
|
||||
#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len)
|
||||
#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len)
|
||||
static inline void swap_dws(void *wrb, int len)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN
|
||||
u32 *dw = wrb;
|
||||
WARN_ON(len % 4);
|
||||
do {
|
||||
*dw = cpu_to_le32(*dw);
|
||||
dw++;
|
||||
len -= 4;
|
||||
} while (len);
|
||||
#endif /* __BIG_ENDIAN */
|
||||
}
|
||||
|
||||
extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
|
||||
u16 num_popped);
|
||||
|
||||
#endif /* BEISCSI_H */
|
523
drivers/scsi/be2iscsi/be_cmds.c
Normal file
523
drivers/scsi/be2iscsi/be_cmds.c
Normal file
@ -0,0 +1,523 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*/
|
||||
|
||||
#include "be.h"
|
||||
#include "be_mgmt.h"
|
||||
#include "be_main.h"
|
||||
|
||||
static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
|
||||
{
|
||||
if (compl->flags != 0) {
|
||||
compl->flags = le32_to_cpu(compl->flags);
|
||||
WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
|
||||
{
|
||||
compl->flags = 0;
|
||||
}
|
||||
|
||||
static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
|
||||
struct be_mcc_compl *compl)
|
||||
{
|
||||
u16 compl_status, extd_status;
|
||||
|
||||
be_dws_le_to_cpu(compl, 4);
|
||||
|
||||
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
|
||||
CQE_STATUS_COMPL_MASK;
|
||||
if (compl_status != MCC_STATUS_SUCCESS) {
|
||||
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
|
||||
CQE_STATUS_EXTD_MASK;
|
||||
dev_err(&ctrl->pdev->dev,
|
||||
"error in cmd completion: status(compl/extd)=%d/%d\n",
|
||||
compl_status, extd_status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool is_link_state_evt(u32 trailer)
|
||||
{
|
||||
return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
|
||||
ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE);
|
||||
}
|
||||
|
||||
void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
|
||||
u16 num_popped)
|
||||
{
|
||||
u32 val = 0;
|
||||
val |= qid & DB_CQ_RING_ID_MASK;
|
||||
if (arm)
|
||||
val |= 1 << DB_CQ_REARM_SHIFT;
|
||||
val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
|
||||
iowrite32(val, ctrl->db + DB_CQ_OFFSET);
|
||||
}
|
||||
|
||||
static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
|
||||
{
|
||||
#define long_delay 2000
|
||||
void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
|
||||
int cnt = 0, wait = 5; /* in usecs */
|
||||
u32 ready;
|
||||
|
||||
do {
|
||||
ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
|
||||
if (ready)
|
||||
break;
|
||||
|
||||
if (cnt > 6000000) {
|
||||
dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cnt > 50) {
|
||||
wait = long_delay;
|
||||
mdelay(long_delay / 1000);
|
||||
} else
|
||||
udelay(wait);
|
||||
cnt += wait;
|
||||
} while (true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int be_mbox_notify(struct be_ctrl_info *ctrl)
|
||||
{
|
||||
int status;
|
||||
u32 val = 0;
|
||||
void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
|
||||
struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
|
||||
struct be_mcc_mailbox *mbox = mbox_mem->va;
|
||||
struct be_mcc_compl *compl = &mbox->compl;
|
||||
|
||||
val &= ~MPU_MAILBOX_DB_RDY_MASK;
|
||||
val |= MPU_MAILBOX_DB_HI_MASK;
|
||||
val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
|
||||
iowrite32(val, db);
|
||||
|
||||
status = be_mbox_db_ready_wait(ctrl);
|
||||
if (status != 0) {
|
||||
SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 1\n");
|
||||
return status;
|
||||
}
|
||||
val = 0;
|
||||
val &= ~MPU_MAILBOX_DB_RDY_MASK;
|
||||
val &= ~MPU_MAILBOX_DB_HI_MASK;
|
||||
val |= (u32) (mbox_mem->dma >> 4) << 2;
|
||||
iowrite32(val, db);
|
||||
|
||||
status = be_mbox_db_ready_wait(ctrl);
|
||||
if (status != 0) {
|
||||
SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 2\n");
|
||||
return status;
|
||||
}
|
||||
if (be_mcc_compl_is_new(compl)) {
|
||||
status = be_mcc_compl_process(ctrl, &mbox->compl);
|
||||
be_mcc_compl_use(compl);
|
||||
if (status) {
|
||||
SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process \n");
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
|
||||
bool embedded, u8 sge_cnt)
|
||||
{
|
||||
if (embedded)
|
||||
wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
|
||||
else
|
||||
wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
|
||||
MCC_WRB_SGE_CNT_SHIFT;
|
||||
wrb->payload_length = payload_len;
|
||||
be_dws_cpu_to_le(wrb, 8);
|
||||
}
|
||||
|
||||
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
|
||||
u8 subsystem, u8 opcode, int cmd_len)
|
||||
{
|
||||
req_hdr->opcode = opcode;
|
||||
req_hdr->subsystem = subsystem;
|
||||
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
|
||||
}
|
||||
|
||||
static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
|
||||
struct be_dma_mem *mem)
|
||||
{
|
||||
int i, buf_pages;
|
||||
u64 dma = (u64) mem->dma;
|
||||
|
||||
buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
|
||||
for (i = 0; i < buf_pages; i++) {
|
||||
pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
|
||||
pages[i].hi = cpu_to_le32(upper_32_bits(dma));
|
||||
dma += PAGE_SIZE_4K;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 eq_delay_to_mult(u32 usec_delay)
|
||||
{
|
||||
#define MAX_INTR_RATE 651042
|
||||
const u32 round = 10;
|
||||
u32 multiplier;
|
||||
|
||||
if (usec_delay == 0)
|
||||
multiplier = 0;
|
||||
else {
|
||||
u32 interrupt_rate = 1000000 / usec_delay;
|
||||
if (interrupt_rate == 0)
|
||||
multiplier = 1023;
|
||||
else {
|
||||
multiplier = (MAX_INTR_RATE - interrupt_rate) * round;
|
||||
multiplier /= interrupt_rate;
|
||||
multiplier = (multiplier + round / 2) / round;
|
||||
multiplier = min(multiplier, (u32) 1023);
|
||||
}
|
||||
}
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
|
||||
{
|
||||
return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
|
||||
}
|
||||
|
||||
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *eq, int eq_delay)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_cmd_req_eq_create *req = embedded_payload(wrb);
|
||||
struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
|
||||
struct be_dma_mem *q_mem = &eq->dma_mem;
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_EQ_CREATE, sizeof(*req));
|
||||
|
||||
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
|
||||
|
||||
AMAP_SET_BITS(struct amap_eq_context, func, req->context,
|
||||
PCI_FUNC(ctrl->pdev->devfn));
|
||||
AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
|
||||
AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
|
||||
AMAP_SET_BITS(struct amap_eq_context, count, req->context,
|
||||
__ilog2_u32(eq->len / 256));
|
||||
AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context,
|
||||
eq_delay_to_mult(eq_delay));
|
||||
be_dws_cpu_to_le(req->context, sizeof(req->context));
|
||||
|
||||
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
eq->id = le16_to_cpu(resp->eq_id);
|
||||
eq->created = true;
|
||||
}
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
int status;
|
||||
u8 *endian_check;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
endian_check = (u8 *) wrb;
|
||||
*endian_check++ = 0xFF;
|
||||
*endian_check++ = 0x12;
|
||||
*endian_check++ = 0x34;
|
||||
*endian_check++ = 0xFF;
|
||||
*endian_check++ = 0xFF;
|
||||
*endian_check++ = 0x56;
|
||||
*endian_check++ = 0x78;
|
||||
*endian_check++ = 0xFF;
|
||||
be_dws_cpu_to_le(wrb, sizeof(*wrb));
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status)
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed \n");
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *cq, struct be_queue_info *eq,
|
||||
bool sol_evts, bool no_delay, int coalesce_wm)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_cmd_req_cq_create *req = embedded_payload(wrb);
|
||||
struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
|
||||
struct be_dma_mem *q_mem = &cq->dma_mem;
|
||||
void *ctxt = &req->context;
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_CQ_CREATE, sizeof(*req));
|
||||
|
||||
if (!q_mem->va)
|
||||
SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n");
|
||||
|
||||
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
|
||||
|
||||
AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
|
||||
AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
|
||||
AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
|
||||
__ilog2_u32(cq->len / 256));
|
||||
AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
|
||||
AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
|
||||
AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
|
||||
AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
|
||||
AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
|
||||
AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
|
||||
PCI_FUNC(ctrl->pdev->devfn));
|
||||
be_dws_cpu_to_le(ctxt, sizeof(req->context));
|
||||
|
||||
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
cq->id = le16_to_cpu(resp->cq_id);
|
||||
cq->created = true;
|
||||
} else
|
||||
SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x \n",
|
||||
status);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static u32 be_encoded_q_len(int q_len)
|
||||
{
|
||||
u32 len_encoded = fls(q_len); /* log2(len) + 1 */
|
||||
if (len_encoded == 16)
|
||||
len_encoded = 0;
|
||||
return len_encoded;
|
||||
}
|
||||
int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
|
||||
int queue_type)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
|
||||
u8 subsys = 0, opcode = 0;
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
switch (queue_type) {
|
||||
case QTYPE_EQ:
|
||||
subsys = CMD_SUBSYSTEM_COMMON;
|
||||
opcode = OPCODE_COMMON_EQ_DESTROY;
|
||||
break;
|
||||
case QTYPE_CQ:
|
||||
subsys = CMD_SUBSYSTEM_COMMON;
|
||||
opcode = OPCODE_COMMON_CQ_DESTROY;
|
||||
break;
|
||||
case QTYPE_WRBQ:
|
||||
subsys = CMD_SUBSYSTEM_ISCSI;
|
||||
opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY;
|
||||
break;
|
||||
case QTYPE_DPDUQ:
|
||||
subsys = CMD_SUBSYSTEM_ISCSI;
|
||||
opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY;
|
||||
break;
|
||||
case QTYPE_SGL:
|
||||
subsys = CMD_SUBSYSTEM_ISCSI;
|
||||
opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES;
|
||||
break;
|
||||
default:
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
|
||||
if (queue_type != QTYPE_SGL)
|
||||
req->id = cpu_to_le16(q->id);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb);
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
|
||||
sizeof(*req));
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb);
|
||||
|
||||
memcpy(mac_addr, resp->mac_address, ETH_ALEN);
|
||||
}
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *cq,
|
||||
struct be_queue_info *dq, int length,
|
||||
int entry_size)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_defq_create_req *req = embedded_payload(wrb);
|
||||
struct be_dma_mem *q_mem = &dq->dma_mem;
|
||||
void *ctxt = &req->context;
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
|
||||
|
||||
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0);
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt,
|
||||
1);
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt,
|
||||
PCI_FUNC(ctrl->pdev->devfn));
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt,
|
||||
be_encoded_q_len(length / sizeof(struct phys_addr)));
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size,
|
||||
ctxt, entry_size);
|
||||
AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt,
|
||||
cq->id);
|
||||
|
||||
be_dws_cpu_to_le(ctxt, sizeof(req->context));
|
||||
|
||||
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
struct be_defq_create_resp *resp = embedded_payload(wrb);
|
||||
|
||||
dq->id = le16_to_cpu(resp->id);
|
||||
dq->created = true;
|
||||
}
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
|
||||
struct be_queue_info *wrbq)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_wrbq_create_req *req = embedded_payload(wrb);
|
||||
struct be_wrbq_create_resp *resp = embedded_payload(wrb);
|
||||
int status;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req));
|
||||
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
|
||||
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status)
|
||||
wrbq->id = le16_to_cpu(resp->cid);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
|
||||
struct be_dma_mem *q_mem,
|
||||
u32 page_offset, u32 num_pages)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_post_sgl_pages_req *req = embedded_payload(wrb);
|
||||
int status;
|
||||
unsigned int curr_pages;
|
||||
u32 internal_page_offset = 0;
|
||||
u32 temp_num_pages = num_pages;
|
||||
|
||||
if (num_pages == 0xff)
|
||||
num_pages = 1;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
do {
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES,
|
||||
sizeof(*req));
|
||||
curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req,
|
||||
pages);
|
||||
req->num_pages = min(num_pages, curr_pages);
|
||||
req->page_offset = page_offset;
|
||||
be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem);
|
||||
q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE);
|
||||
internal_page_offset += req->num_pages;
|
||||
page_offset += req->num_pages;
|
||||
num_pages -= req->num_pages;
|
||||
|
||||
if (temp_num_pages == 0xff)
|
||||
req->num_pages = temp_num_pages;
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"FW CMD to map iscsi frags failed.\n");
|
||||
goto error;
|
||||
}
|
||||
} while (num_pages > 0);
|
||||
error:
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
if (status != 0)
|
||||
beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
|
||||
return status;
|
||||
}
|
877
drivers/scsi/be2iscsi/be_cmds.h
Normal file
877
drivers/scsi/be2iscsi/be_cmds.h
Normal file
@ -0,0 +1,877 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*/
|
||||
|
||||
#ifndef BEISCSI_CMDS_H
|
||||
#define BEISCSI_CMDS_H
|
||||
|
||||
/**
|
||||
* The driver sends configuration and managements command requests to the
|
||||
* firmware in the BE. These requests are communicated to the processor
|
||||
* using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
|
||||
* WRB inside a MAILBOX.
|
||||
* The commands are serviced by the ARM processor in the BladeEngine's MPU.
|
||||
*/
|
||||
struct be_sge {
|
||||
u32 pa_lo;
|
||||
u32 pa_hi;
|
||||
u32 len;
|
||||
};
|
||||
|
||||
#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */
|
||||
#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */
|
||||
struct be_mcc_wrb {
|
||||
u32 embedded; /* dword 0 */
|
||||
u32 payload_length; /* dword 1 */
|
||||
u32 tag0; /* dword 2 */
|
||||
u32 tag1; /* dword 3 */
|
||||
u32 rsvd; /* dword 4 */
|
||||
union {
|
||||
u8 embedded_payload[236]; /* used by embedded cmds */
|
||||
struct be_sge sgl[19]; /* used by non-embedded cmds */
|
||||
} payload;
|
||||
};
|
||||
|
||||
#define CQE_FLAGS_VALID_MASK (1 << 31)
|
||||
#define CQE_FLAGS_ASYNC_MASK (1 << 30)
|
||||
|
||||
/* Completion Status */
|
||||
#define MCC_STATUS_SUCCESS 0x0
|
||||
|
||||
#define CQE_STATUS_COMPL_MASK 0xFFFF
|
||||
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
|
||||
#define CQE_STATUS_EXTD_MASK 0xFFFF
|
||||
#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */
|
||||
|
||||
struct be_mcc_compl {
|
||||
u32 status; /* dword 0 */
|
||||
u32 tag0; /* dword 1 */
|
||||
u32 tag1; /* dword 2 */
|
||||
u32 flags; /* dword 3 */
|
||||
};
|
||||
|
||||
/********* Mailbox door bell *************/
|
||||
/**
|
||||
* Used for driver communication with the FW.
|
||||
* The software must write this register twice to post any command. First,
|
||||
* it writes the register with hi=1 and the upper bits of the physical address
|
||||
* for the MAILBOX structure. Software must poll the ready bit until this
|
||||
* is acknowledged. Then, sotware writes the register with hi=0 with the lower
|
||||
* bits in the address. It must poll the ready bit until the command is
|
||||
* complete. Upon completion, the MAILBOX will contain a valid completion
|
||||
* queue entry.
|
||||
*/
|
||||
#define MPU_MAILBOX_DB_OFFSET 0x160
|
||||
#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */
|
||||
#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */
|
||||
|
||||
/********** MPU semphore ******************/
|
||||
#define MPU_EP_SEMAPHORE_OFFSET 0xac
|
||||
#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
|
||||
#define EP_SEMAPHORE_POST_ERR_MASK 0x1
|
||||
#define EP_SEMAPHORE_POST_ERR_SHIFT 31
|
||||
|
||||
/********** MCC door bell ************/
|
||||
#define DB_MCCQ_OFFSET 0x140
|
||||
#define DB_MCCQ_RING_ID_MASK 0x7FF /* bits 0 - 10 */
|
||||
/* Number of entries posted */
|
||||
#define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */
|
||||
|
||||
/* MPU semphore POST stage values */
|
||||
#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */
|
||||
|
||||
/**
|
||||
* When the async bit of mcc_compl is set, the last 4 bytes of
|
||||
* mcc_compl is interpreted as follows:
|
||||
*/
|
||||
#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
|
||||
#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
|
||||
#define ASYNC_EVENT_CODE_LINK_STATE 0x1
|
||||
struct be_async_event_trailer {
|
||||
u32 code;
|
||||
};
|
||||
|
||||
enum {
|
||||
ASYNC_EVENT_LINK_DOWN = 0x0,
|
||||
ASYNC_EVENT_LINK_UP = 0x1
|
||||
};
|
||||
|
||||
/**
|
||||
* When the event code of an async trailer is link-state, the mcc_compl
|
||||
* must be interpreted as follows
|
||||
*/
|
||||
struct be_async_event_link_state {
|
||||
u8 physical_port;
|
||||
u8 port_link_status;
|
||||
u8 port_duplex;
|
||||
u8 port_speed;
|
||||
u8 port_fault;
|
||||
u8 rsvd0[7];
|
||||
struct be_async_event_trailer trailer;
|
||||
} __packed;
|
||||
|
||||
struct be_mcc_mailbox {
|
||||
struct be_mcc_wrb wrb;
|
||||
struct be_mcc_compl compl;
|
||||
};
|
||||
|
||||
/* Type of subsystems supported by FW */
|
||||
#define CMD_SUBSYSTEM_COMMON 0x1
|
||||
#define CMD_SUBSYSTEM_ISCSI 0x2
|
||||
#define CMD_SUBSYSTEM_ETH 0x3
|
||||
#define CMD_SUBSYSTEM_ISCSI_INI 0x6
|
||||
#define CMD_COMMON_TCP_UPLOAD 0x1
|
||||
|
||||
/**
|
||||
* List of common opcodes subsystem CMD_SUBSYSTEM_COMMON
|
||||
* These opcodes are unique for each subsystem defined above
|
||||
*/
|
||||
#define OPCODE_COMMON_CQ_CREATE 12
|
||||
#define OPCODE_COMMON_EQ_CREATE 13
|
||||
#define OPCODE_COMMON_MCC_CREATE 21
|
||||
#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32
|
||||
#define OPCODE_COMMON_GET_FW_VERSION 35
|
||||
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
|
||||
#define OPCODE_COMMON_FIRMWARE_CONFIG 42
|
||||
#define OPCODE_COMMON_MCC_DESTROY 53
|
||||
#define OPCODE_COMMON_CQ_DESTROY 54
|
||||
#define OPCODE_COMMON_EQ_DESTROY 55
|
||||
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
|
||||
#define OPCODE_COMMON_FUNCTION_RESET 61
|
||||
|
||||
/**
|
||||
* LIST of opcodes that are common between Initiator and Target
|
||||
* used by CMD_SUBSYSTEM_ISCSI
|
||||
* These opcodes are unique for each subsystem defined above
|
||||
*/
|
||||
#define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2
|
||||
#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7
|
||||
#define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61
|
||||
#define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64
|
||||
#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65
|
||||
#define OPCODE_COMMON_ISCSI_WRBQ_CREATE 66
|
||||
#define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67
|
||||
|
||||
struct be_cmd_req_hdr {
|
||||
u8 opcode; /* dword 0 */
|
||||
u8 subsystem; /* dword 0 */
|
||||
u8 port_number; /* dword 0 */
|
||||
u8 domain; /* dword 0 */
|
||||
u32 timeout; /* dword 1 */
|
||||
u32 request_length; /* dword 2 */
|
||||
u32 rsvd; /* dword 3 */
|
||||
};
|
||||
|
||||
struct be_cmd_resp_hdr {
|
||||
u32 info; /* dword 0 */
|
||||
u32 status; /* dword 1 */
|
||||
u32 response_length; /* dword 2 */
|
||||
u32 actual_resp_len; /* dword 3 */
|
||||
};
|
||||
|
||||
struct phys_addr {
|
||||
u32 lo;
|
||||
u32 hi;
|
||||
};
|
||||
|
||||
/**************************
|
||||
* BE Command definitions *
|
||||
**************************/
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte - used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_eq_context {
|
||||
u8 cidx[13]; /* dword 0 */
|
||||
u8 rsvd0[3]; /* dword 0 */
|
||||
u8 epidx[13]; /* dword 0 */
|
||||
u8 valid; /* dword 0 */
|
||||
u8 rsvd1; /* dword 0 */
|
||||
u8 size; /* dword 0 */
|
||||
u8 pidx[13]; /* dword 1 */
|
||||
u8 rsvd2[3]; /* dword 1 */
|
||||
u8 pd[10]; /* dword 1 */
|
||||
u8 count[3]; /* dword 1 */
|
||||
u8 solevent; /* dword 1 */
|
||||
u8 stalled; /* dword 1 */
|
||||
u8 armed; /* dword 1 */
|
||||
u8 rsvd3[4]; /* dword 2 */
|
||||
u8 func[8]; /* dword 2 */
|
||||
u8 rsvd4; /* dword 2 */
|
||||
u8 delaymult[10]; /* dword 2 */
|
||||
u8 rsvd5[2]; /* dword 2 */
|
||||
u8 phase[2]; /* dword 2 */
|
||||
u8 nodelay; /* dword 2 */
|
||||
u8 rsvd6[4]; /* dword 2 */
|
||||
u8 rsvd7[32]; /* dword 3 */
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_eq_create {
|
||||
struct be_cmd_req_hdr hdr; /* dw[4] */
|
||||
u16 num_pages; /* sword */
|
||||
u16 rsvd0; /* sword */
|
||||
u8 context[sizeof(struct amap_eq_context) / 8]; /* dw[4] */
|
||||
struct phys_addr pages[8];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_eq_create {
|
||||
struct be_cmd_resp_hdr resp_hdr;
|
||||
u16 eq_id; /* sword */
|
||||
u16 rsvd0; /* sword */
|
||||
} __packed;
|
||||
|
||||
struct mac_addr {
|
||||
u16 size_of_struct;
|
||||
u8 addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_mac_query {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u8 type;
|
||||
u8 permanent;
|
||||
u16 if_id;
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_mac_query {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
struct mac_addr mac;
|
||||
};
|
||||
|
||||
/******************** Create CQ ***************************/
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte - used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_cq_context {
|
||||
u8 cidx[11]; /* dword 0 */
|
||||
u8 rsvd0; /* dword 0 */
|
||||
u8 coalescwm[2]; /* dword 0 */
|
||||
u8 nodelay; /* dword 0 */
|
||||
u8 epidx[11]; /* dword 0 */
|
||||
u8 rsvd1; /* dword 0 */
|
||||
u8 count[2]; /* dword 0 */
|
||||
u8 valid; /* dword 0 */
|
||||
u8 solevent; /* dword 0 */
|
||||
u8 eventable; /* dword 0 */
|
||||
u8 pidx[11]; /* dword 1 */
|
||||
u8 rsvd2; /* dword 1 */
|
||||
u8 pd[10]; /* dword 1 */
|
||||
u8 eqid[8]; /* dword 1 */
|
||||
u8 stalled; /* dword 1 */
|
||||
u8 armed; /* dword 1 */
|
||||
u8 rsvd3[4]; /* dword 2 */
|
||||
u8 func[8]; /* dword 2 */
|
||||
u8 rsvd4[20]; /* dword 2 */
|
||||
u8 rsvd5[32]; /* dword 3 */
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_cq_create {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_pages;
|
||||
u16 rsvd0;
|
||||
u8 context[sizeof(struct amap_cq_context) / 8];
|
||||
struct phys_addr pages[4];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_cq_create {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u16 cq_id;
|
||||
u16 rsvd0;
|
||||
} __packed;
|
||||
|
||||
/******************** Create MCCQ ***************************/
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte - used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_mcc_context {
|
||||
u8 con_index[14];
|
||||
u8 rsvd0[2];
|
||||
u8 ring_size[4];
|
||||
u8 fetch_wrb;
|
||||
u8 fetch_r2t;
|
||||
u8 cq_id[10];
|
||||
u8 prod_index[14];
|
||||
u8 fid[8];
|
||||
u8 pdid[9];
|
||||
u8 valid;
|
||||
u8 rsvd1[32];
|
||||
u8 rsvd2[32];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_mcc_create {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_pages;
|
||||
u16 rsvd0;
|
||||
u8 context[sizeof(struct amap_mcc_context) / 8];
|
||||
struct phys_addr pages[8];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_mcc_create {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u16 id;
|
||||
u16 rsvd0;
|
||||
} __packed;
|
||||
|
||||
/******************** Q Destroy ***************************/
|
||||
/* Type of Queue to be destroyed */
|
||||
enum {
|
||||
QTYPE_EQ = 1,
|
||||
QTYPE_CQ,
|
||||
QTYPE_MCCQ,
|
||||
QTYPE_WRBQ,
|
||||
QTYPE_DPDUQ,
|
||||
QTYPE_SGL
|
||||
};
|
||||
|
||||
struct be_cmd_req_q_destroy {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 id;
|
||||
u16 bypass_flush; /* valid only for rx q destroy */
|
||||
} __packed;
|
||||
|
||||
struct macaddr {
|
||||
u8 byte[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct be_cmd_req_mcast_mac_config {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_mac;
|
||||
u8 promiscuous;
|
||||
u8 interface_id;
|
||||
struct macaddr mac[32];
|
||||
} __packed;
|
||||
|
||||
static inline void *embedded_payload(struct be_mcc_wrb *wrb)
|
||||
{
|
||||
return wrb->payload.embedded_payload;
|
||||
}
|
||||
|
||||
static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
|
||||
{
|
||||
return &wrb->payload.sgl[0];
|
||||
}
|
||||
|
||||
/******************** Modify EQ Delay *******************/
|
||||
struct be_cmd_req_modify_eq_delay {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 num_eq;
|
||||
struct {
|
||||
u32 eq_id;
|
||||
u32 phase;
|
||||
u32 delay_multiplier;
|
||||
} delay[8];
|
||||
} __packed;
|
||||
|
||||
/******************** Get MAC ADDR *******************/
|
||||
|
||||
#define ETH_ALEN 6
|
||||
|
||||
|
||||
struct be_cmd_req_get_mac_addr {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 nic_port_count;
|
||||
u32 speed;
|
||||
u32 max_speed;
|
||||
u32 link_state;
|
||||
u32 max_frame_size;
|
||||
u16 size_of_structure;
|
||||
u8 mac_address[ETH_ALEN];
|
||||
u32 rsvd[23];
|
||||
};
|
||||
|
||||
struct be_cmd_resp_get_mac_addr {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u32 nic_port_count;
|
||||
u32 speed;
|
||||
u32 max_speed;
|
||||
u32 link_state;
|
||||
u32 max_frame_size;
|
||||
u16 size_of_structure;
|
||||
u8 mac_address[6];
|
||||
u32 rsvd[23];
|
||||
};
|
||||
|
||||
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *eq, int eq_delay);
|
||||
|
||||
int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *cq, struct be_queue_info *eq,
|
||||
bool sol_evts, bool no_delay,
|
||||
int num_cqe_dma_coalesce);
|
||||
|
||||
int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
|
||||
int type);
|
||||
int be_poll_mcc(struct be_ctrl_info *ctrl);
|
||||
unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl);
|
||||
int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr);
|
||||
|
||||
/*ISCSI Functuions */
|
||||
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
|
||||
|
||||
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
|
||||
|
||||
int be_mbox_notify(struct be_ctrl_info *ctrl);
|
||||
|
||||
int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *cq,
|
||||
struct be_queue_info *dq, int length,
|
||||
int entry_size);
|
||||
|
||||
int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
|
||||
struct be_dma_mem *q_mem, u32 page_offset,
|
||||
u32 num_pages);
|
||||
|
||||
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
|
||||
struct be_queue_info *wrbq);
|
||||
|
||||
struct be_default_pdu_context {
|
||||
u32 dw[4];
|
||||
} __packed;
|
||||
|
||||
struct amap_be_default_pdu_context {
|
||||
u8 dbuf_cindex[13]; /* dword 0 */
|
||||
u8 rsvd0[3]; /* dword 0 */
|
||||
u8 ring_size[4]; /* dword 0 */
|
||||
u8 ring_state[4]; /* dword 0 */
|
||||
u8 rsvd1[8]; /* dword 0 */
|
||||
u8 dbuf_pindex[13]; /* dword 1 */
|
||||
u8 rsvd2; /* dword 1 */
|
||||
u8 pci_func_id[8]; /* dword 1 */
|
||||
u8 rx_pdid[9]; /* dword 1 */
|
||||
u8 rx_pdid_valid; /* dword 1 */
|
||||
u8 default_buffer_size[16]; /* dword 2 */
|
||||
u8 cq_id_recv[10]; /* dword 2 */
|
||||
u8 rx_pdid_not_valid; /* dword 2 */
|
||||
u8 rsvd3[5]; /* dword 2 */
|
||||
u8 rsvd4[32]; /* dword 3 */
|
||||
} __packed;
|
||||
|
||||
struct be_defq_create_req {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_pages;
|
||||
u8 ulp_num;
|
||||
u8 rsvd0;
|
||||
struct be_default_pdu_context context;
|
||||
struct phys_addr pages[8];
|
||||
} __packed;
|
||||
|
||||
struct be_defq_create_resp {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 id;
|
||||
u16 rsvd0;
|
||||
} __packed;
|
||||
|
||||
struct be_post_sgl_pages_req {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_pages;
|
||||
u16 page_offset;
|
||||
u32 rsvd0;
|
||||
struct phys_addr pages[26];
|
||||
u32 rsvd1;
|
||||
} __packed;
|
||||
|
||||
struct be_wrbq_create_req {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 num_pages;
|
||||
u8 ulp_num;
|
||||
u8 rsvd0;
|
||||
struct phys_addr pages[8];
|
||||
} __packed;
|
||||
|
||||
struct be_wrbq_create_resp {
|
||||
struct be_cmd_resp_hdr resp_hdr;
|
||||
u16 cid;
|
||||
u16 rsvd0;
|
||||
} __packed;
|
||||
|
||||
#define SOL_CID_MASK 0x0000FFC0
|
||||
#define SOL_CODE_MASK 0x0000003F
|
||||
#define SOL_WRB_INDEX_MASK 0x00FF0000
|
||||
#define SOL_CMD_WND_MASK 0xFF000000
|
||||
#define SOL_RES_CNT_MASK 0x7FFFFFFF
|
||||
#define SOL_EXP_CMD_SN_MASK 0xFFFFFFFF
|
||||
#define SOL_HW_STS_MASK 0x000000FF
|
||||
#define SOL_STS_MASK 0x0000FF00
|
||||
#define SOL_RESP_MASK 0x00FF0000
|
||||
#define SOL_FLAGS_MASK 0x7F000000
|
||||
#define SOL_S_MASK 0x80000000
|
||||
|
||||
struct sol_cqe {
|
||||
u32 dw[4];
|
||||
};
|
||||
|
||||
struct amap_sol_cqe {
|
||||
u8 hw_sts[8]; /* dword 0 */
|
||||
u8 i_sts[8]; /* dword 0 */
|
||||
u8 i_resp[8]; /* dword 0 */
|
||||
u8 i_flags[7]; /* dword 0 */
|
||||
u8 s; /* dword 0 */
|
||||
u8 i_exp_cmd_sn[32]; /* dword 1 */
|
||||
u8 code[6]; /* dword 2 */
|
||||
u8 cid[10]; /* dword 2 */
|
||||
u8 wrb_index[8]; /* dword 2 */
|
||||
u8 i_cmd_wnd[8]; /* dword 2 */
|
||||
u8 i_res_cnt[31]; /* dword 3 */
|
||||
u8 valid; /* dword 3 */
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* Post WRB Queue Doorbell Register used by the host Storage
|
||||
* stack to notify the
|
||||
* controller of a posted Work Request Block
|
||||
*/
|
||||
#define DB_WRB_POST_CID_MASK 0x3FF /* bits 0 - 9 */
|
||||
#define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */
|
||||
|
||||
#define DB_DEF_PDU_WRB_INDEX_SHIFT 16
|
||||
#define DB_DEF_PDU_NUM_POSTED_SHIFT 24
|
||||
|
||||
struct fragnum_bits_for_sgl_cra_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 num_bits;
|
||||
} __packed;
|
||||
|
||||
struct iscsi_cleanup_req {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 chute;
|
||||
u8 hdr_ring_id;
|
||||
u8 data_ring_id;
|
||||
|
||||
} __packed;
|
||||
|
||||
struct eq_delay {
|
||||
u32 eq_id;
|
||||
u32 phase;
|
||||
u32 delay_multiplier;
|
||||
} __packed;
|
||||
|
||||
struct be_eq_delay_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 num_eq;
|
||||
struct eq_delay delay[8];
|
||||
} __packed;
|
||||
|
||||
struct ip_address_format {
|
||||
u16 size_of_structure;
|
||||
u8 reserved;
|
||||
u8 ip_type;
|
||||
u8 ip_address[16];
|
||||
u32 rsvd0;
|
||||
} __packed;
|
||||
|
||||
struct tcp_connect_and_offload_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
struct ip_address_format ip_address;
|
||||
u16 tcp_port;
|
||||
u16 cid;
|
||||
u16 cq_id;
|
||||
u16 defq_id;
|
||||
struct phys_addr dataout_template_pa;
|
||||
u16 hdr_ring_id;
|
||||
u16 data_ring_id;
|
||||
u8 do_offload;
|
||||
u8 rsvd0[3];
|
||||
} __packed;
|
||||
|
||||
struct tcp_connect_and_offload_out {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u32 connection_handle;
|
||||
u16 cid;
|
||||
u16 rsvd0;
|
||||
|
||||
} __packed;
|
||||
|
||||
struct be_mcc_wrb_context {
|
||||
struct MCC_WRB *wrb;
|
||||
int *users_final_status;
|
||||
} __packed;
|
||||
|
||||
#define DB_DEF_PDU_RING_ID_MASK 0x3FF /* bits 0 - 9 */
|
||||
#define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 0 - 9 */
|
||||
#define DB_DEF_PDU_REARM_SHIFT 14
|
||||
#define DB_DEF_PDU_EVENT_SHIFT 15
|
||||
#define DB_DEF_PDU_CQPROC_SHIFT 16
|
||||
|
||||
struct dmsg_cqe {
|
||||
u32 dw[4];
|
||||
} __packed;
|
||||
|
||||
struct tcp_upload_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 id;
|
||||
u16 upload_type;
|
||||
u32 reset_seq;
|
||||
} __packed;
|
||||
|
||||
struct tcp_upload_params_out {
|
||||
u32 dw[32];
|
||||
} __packed;
|
||||
|
||||
union tcp_upload_params {
|
||||
struct tcp_upload_params_in request;
|
||||
struct tcp_upload_params_out response;
|
||||
} __packed;
|
||||
|
||||
struct be_ulp_fw_cfg {
|
||||
u32 ulp_mode;
|
||||
u32 etx_base;
|
||||
u32 etx_count;
|
||||
u32 sq_base;
|
||||
u32 sq_count;
|
||||
u32 rq_base;
|
||||
u32 rq_count;
|
||||
u32 dq_base;
|
||||
u32 dq_count;
|
||||
u32 lro_base;
|
||||
u32 lro_count;
|
||||
u32 icd_base;
|
||||
u32 icd_count;
|
||||
};
|
||||
|
||||
struct be_fw_cfg {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 be_config_number;
|
||||
u32 asic_revision;
|
||||
u32 phys_port;
|
||||
u32 function_mode;
|
||||
struct be_ulp_fw_cfg ulp[2];
|
||||
u32 function_caps;
|
||||
} __packed;
|
||||
|
||||
#define CMD_ISCSI_COMMAND_INVALIDATE 1
|
||||
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
|
||||
#define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70
|
||||
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
|
||||
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
|
||||
#define OPCODE_COMMON_ISCSI_CLEANUP 59
|
||||
#define OPCODE_COMMON_TCP_UPLOAD 56
|
||||
#define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
|
||||
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
|
||||
#define CMD_ISCSI_CONNECTION_INVALIDATE 1
|
||||
#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2
|
||||
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
|
||||
|
||||
#define INI_WR_CMD 1 /* Initiator write command */
|
||||
#define INI_TMF_CMD 2 /* Initiator TMF command */
|
||||
#define INI_NOPOUT_CMD 3 /* Initiator; Send a NOP-OUT */
|
||||
#define INI_RD_CMD 5 /* Initiator requesting to send
|
||||
* a read command
|
||||
*/
|
||||
#define TGT_CTX_UPDT_CMD 7 /* Target context update */
|
||||
#define TGT_STS_CMD 8 /* Target R2T and other BHS
|
||||
* where only the status number
|
||||
* need to be updated
|
||||
*/
|
||||
#define TGT_DATAIN_CMD 9 /* Target Data-Ins in response
|
||||
* to read command
|
||||
*/
|
||||
#define TGT_SOS_PDU 10 /* Target:standalone status
|
||||
* response
|
||||
*/
|
||||
#define TGT_DM_CMD 11 /* Indicates that the bhs
|
||||
* preparedby
|
||||
* driver should not be touched
|
||||
*/
|
||||
/* --- CMD_CHUTE_TYPE --- */
|
||||
#define CMD_CONNECTION_CHUTE_0 1
|
||||
#define CMD_CONNECTION_CHUTE_1 2
|
||||
#define CMD_CONNECTION_CHUTE_2 3
|
||||
|
||||
#define EQ_MAJOR_CODE_COMPLETION 0
|
||||
|
||||
#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0
|
||||
#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1
|
||||
|
||||
/* --- CONNECTION_UPLOAD_PARAMS --- */
|
||||
/* These parameters are used to define the type of upload desired. */
|
||||
#define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */
|
||||
#define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with
|
||||
* reset
|
||||
*/
|
||||
#define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without
|
||||
* reset
|
||||
*/
|
||||
#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset,
|
||||
* sequence number by driver */
|
||||
|
||||
/* Returns byte size of given field with a structure. */
|
||||
|
||||
/* Returns the number of items in the field array. */
|
||||
#define BE_NUMBER_OF_FIELD(_type_, _field_) \
|
||||
(FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
|
||||
|
||||
/**
|
||||
* Different types of iSCSI completions to host driver for both initiator
|
||||
* and taget mode
|
||||
* of operation.
|
||||
*/
|
||||
#define SOL_CMD_COMPLETE 1 /* Solicited command completed
|
||||
* normally
|
||||
*/
|
||||
#define SOL_CMD_KILLED_DATA_DIGEST_ERR 2 /* Solicited command got
|
||||
* invalidated internally due
|
||||
* to Data Digest error
|
||||
*/
|
||||
#define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3 /* Connection got invalidated
|
||||
* internally
|
||||
* due to a recieved PDU
|
||||
* size > DSL
|
||||
*/
|
||||
#define CXN_KILLED_BURST_LEN_MISMATCH 4 /* Connection got invalidated
|
||||
* internally due ti received
|
||||
* PDU sequence size >
|
||||
* FBL/MBL.
|
||||
*/
|
||||
#define CXN_KILLED_AHS_RCVD 5 /* Connection got invalidated
|
||||
* internally due to a recieved
|
||||
* PDU Hdr that has
|
||||
* AHS */
|
||||
#define CXN_KILLED_HDR_DIGEST_ERR 6 /* Connection got invalidated
|
||||
* internally due to Hdr Digest
|
||||
* error
|
||||
*/
|
||||
#define CXN_KILLED_UNKNOWN_HDR 7 /* Connection got invalidated
|
||||
* internally
|
||||
* due to a bad opcode in the
|
||||
* pdu hdr
|
||||
*/
|
||||
#define CXN_KILLED_STALE_ITT_TTT_RCVD 8 /* Connection got invalidated
|
||||
* internally due to a recieved
|
||||
* ITT/TTT that does not belong
|
||||
* to this Connection
|
||||
*/
|
||||
#define CXN_KILLED_INVALID_ITT_TTT_RCVD 9 /* Connection got invalidated
|
||||
* internally due to recieved
|
||||
* ITT/TTT value > Max
|
||||
* Supported ITTs/TTTs
|
||||
*/
|
||||
#define CXN_KILLED_RST_RCVD 10 /* Connection got invalidated
|
||||
* internally due to an
|
||||
* incoming TCP RST
|
||||
*/
|
||||
#define CXN_KILLED_TIMED_OUT 11 /* Connection got invalidated
|
||||
* internally due to timeout on
|
||||
* tcp segment 12 retransmit
|
||||
* attempts failed
|
||||
*/
|
||||
#define CXN_KILLED_RST_SENT 12 /* Connection got invalidated
|
||||
* internally due to TCP RST
|
||||
* sent by the Tx side
|
||||
*/
|
||||
#define CXN_KILLED_FIN_RCVD 13 /* Connection got invalidated
|
||||
* internally due to an
|
||||
* incoming TCP FIN.
|
||||
*/
|
||||
#define CXN_KILLED_BAD_UNSOL_PDU_RCVD 14 /* Connection got invalidated
|
||||
* internally due to bad
|
||||
* unsolicited PDU Unsolicited
|
||||
* PDUs are PDUs with
|
||||
* ITT=0xffffffff
|
||||
*/
|
||||
#define CXN_KILLED_BAD_WRB_INDEX_ERROR 15 /* Connection got invalidated
|
||||
* internally due to bad WRB
|
||||
* index.
|
||||
*/
|
||||
#define CXN_KILLED_OVER_RUN_RESIDUAL 16 /* Command got invalidated
|
||||
* internally due to recived
|
||||
* command has residual
|
||||
* over run bytes.
|
||||
*/
|
||||
#define CXN_KILLED_UNDER_RUN_RESIDUAL 17 /* Command got invalidated
|
||||
* internally due to recived
|
||||
* command has residual under
|
||||
* run bytes.
|
||||
*/
|
||||
#define CMD_KILLED_INVALID_STATSN_RCVD 18 /* Command got invalidated
|
||||
* internally due to a recieved
|
||||
* PDU has an invalid StatusSN
|
||||
*/
|
||||
#define CMD_KILLED_INVALID_R2T_RCVD 19 /* Command got invalidated
|
||||
* internally due to a recieved
|
||||
* an R2T with some invalid
|
||||
* fields in it
|
||||
*/
|
||||
#define CMD_CXN_KILLED_LUN_INVALID 20 /* Command got invalidated
|
||||
* internally due to received
|
||||
* PDU has an invalid LUN.
|
||||
*/
|
||||
#define CMD_CXN_KILLED_ICD_INVALID 21 /* Command got invalidated
|
||||
* internally due to the
|
||||
* corresponding ICD not in a
|
||||
* valid state
|
||||
*/
|
||||
#define CMD_CXN_KILLED_ITT_INVALID 22 /* Command got invalidated due
|
||||
* to received PDU has an
|
||||
* invalid ITT.
|
||||
*/
|
||||
#define CMD_CXN_KILLED_SEQ_OUTOFORDER 23 /* Command got invalidated due
|
||||
* to received sequence buffer
|
||||
* offset is out of order.
|
||||
*/
|
||||
#define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24 /* Command got invalidated
|
||||
* internally due to a
|
||||
* recieved PDU has an invalid
|
||||
* DataSN
|
||||
*/
|
||||
#define CXN_INVALIDATE_NOTIFY 25 /* Connection invalidation
|
||||
* completion notify.
|
||||
*/
|
||||
#define CXN_INVALIDATE_INDEX_NOTIFY 26 /* Connection invalidation
|
||||
* completion
|
||||
* with data PDU index.
|
||||
*/
|
||||
#define CMD_INVALIDATED_NOTIFY 27 /* Command invalidation
|
||||
* completionnotifify.
|
||||
*/
|
||||
#define UNSOL_HDR_NOTIFY 28 /* Unsolicited header notify.*/
|
||||
#define UNSOL_DATA_NOTIFY 29 /* Unsolicited data notify.*/
|
||||
#define UNSOL_DATA_DIGEST_ERROR_NOTIFY 30 /* Unsolicited data digest
|
||||
* error notify.
|
||||
*/
|
||||
#define DRIVERMSG_NOTIFY 31 /* TCP acknowledge based
|
||||
* notification.
|
||||
*/
|
||||
#define CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN 32 /* Connection got invalidated
|
||||
* internally due to command
|
||||
* and data are not on same
|
||||
* connection.
|
||||
*/
|
||||
#define SOL_CMD_KILLED_DIF_ERR 33 /* Solicited command got
|
||||
* invalidated internally due
|
||||
* to DIF error
|
||||
*/
|
||||
#define CXN_KILLED_SYN_RCVD 34 /* Connection got invalidated
|
||||
* internally due to incoming
|
||||
* TCP SYN
|
||||
*/
|
||||
#define CXN_KILLED_IMM_DATA_RCVD 35 /* Connection got invalidated
|
||||
* internally due to an
|
||||
* incoming Unsolicited PDU
|
||||
* that has immediate data on
|
||||
* the cxn
|
||||
*/
|
||||
|
||||
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
|
||||
bool embedded, u8 sge_cnt);
|
||||
|
||||
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
|
||||
u8 subsystem, u8 opcode, int cmd_len);
|
||||
|
||||
#endif /* !BEISCSI_CMDS_H */
|
638
drivers/scsi/be2iscsi/be_iscsi.c
Normal file
638
drivers/scsi/be2iscsi/be_iscsi.c
Normal file
@ -0,0 +1,638 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*
|
||||
*/
|
||||
|
||||
#include <scsi/libiscsi.h>
|
||||
#include <scsi/scsi_transport_iscsi.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "be_iscsi.h"
|
||||
|
||||
extern struct iscsi_transport beiscsi_iscsi_transport;
|
||||
|
||||
/**
|
||||
* beiscsi_session_create - creates a new iscsi session
|
||||
* @cmds_max: max commands supported
|
||||
* @qdepth: max queue depth supported
|
||||
* @initial_cmdsn: initial iscsi CMDSN
|
||||
*/
|
||||
struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
|
||||
u16 cmds_max,
|
||||
u16 qdepth,
|
||||
u32 initial_cmdsn)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_cls_session *cls_session;
|
||||
struct beiscsi_hba *phba;
|
||||
struct iscsi_session *sess;
|
||||
struct beiscsi_session *beiscsi_sess;
|
||||
struct beiscsi_io_task *io_task;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n");
|
||||
|
||||
if (!ep) {
|
||||
SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n");
|
||||
return NULL;
|
||||
}
|
||||
beiscsi_ep = ep->dd_data;
|
||||
phba = beiscsi_ep->phba;
|
||||
shost = phba->shost;
|
||||
if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
|
||||
shost_printk(KERN_ERR, shost, "Cannot handle %d cmds."
|
||||
"Max cmds per session supported is %d. Using %d. "
|
||||
"\n", cmds_max,
|
||||
beiscsi_ep->phba->params.wrbs_per_cxn,
|
||||
beiscsi_ep->phba->params.wrbs_per_cxn);
|
||||
cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
|
||||
}
|
||||
|
||||
cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
|
||||
shost, cmds_max,
|
||||
sizeof(*beiscsi_sess),
|
||||
sizeof(*io_task),
|
||||
initial_cmdsn, ISCSI_MAX_TARGET);
|
||||
if (!cls_session)
|
||||
return NULL;
|
||||
sess = cls_session->dd_data;
|
||||
beiscsi_sess = sess->dd_data;
|
||||
beiscsi_sess->bhs_pool = pci_pool_create("beiscsi_bhs_pool",
|
||||
phba->pcidev,
|
||||
sizeof(struct be_cmd_bhs),
|
||||
64, 0);
|
||||
if (!beiscsi_sess->bhs_pool)
|
||||
goto destroy_sess;
|
||||
|
||||
return cls_session;
|
||||
destroy_sess:
|
||||
iscsi_session_teardown(cls_session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_session_destroy - destroys iscsi session
|
||||
* @cls_session: pointer to iscsi cls session
|
||||
*
|
||||
* Destroys iSCSI session instance and releases
|
||||
* resources allocated for it.
|
||||
*/
|
||||
void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
|
||||
{
|
||||
struct iscsi_session *sess = cls_session->dd_data;
|
||||
struct beiscsi_session *beiscsi_sess = sess->dd_data;
|
||||
|
||||
pci_pool_destroy(beiscsi_sess->bhs_pool);
|
||||
iscsi_session_teardown(cls_session);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_create - create an instance of iscsi connection
|
||||
* @cls_session: ptr to iscsi_cls_session
|
||||
* @cid: iscsi cid
|
||||
*/
|
||||
struct iscsi_cls_conn *
|
||||
beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
|
||||
{
|
||||
struct beiscsi_hba *phba;
|
||||
struct Scsi_Host *shost;
|
||||
struct iscsi_cls_conn *cls_conn;
|
||||
struct beiscsi_conn *beiscsi_conn;
|
||||
struct iscsi_conn *conn;
|
||||
struct iscsi_session *sess;
|
||||
struct beiscsi_session *beiscsi_sess;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid"
|
||||
"from iscsi layer=%d\n", cid);
|
||||
shost = iscsi_session_to_shost(cls_session);
|
||||
phba = iscsi_host_priv(shost);
|
||||
|
||||
cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
|
||||
if (!cls_conn)
|
||||
return NULL;
|
||||
|
||||
conn = cls_conn->dd_data;
|
||||
beiscsi_conn = conn->dd_data;
|
||||
beiscsi_conn->ep = NULL;
|
||||
beiscsi_conn->phba = phba;
|
||||
beiscsi_conn->conn = conn;
|
||||
sess = cls_session->dd_data;
|
||||
beiscsi_sess = sess->dd_data;
|
||||
beiscsi_conn->beiscsi_sess = beiscsi_sess;
|
||||
return cls_conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table
|
||||
* @beiscsi_conn: The pointer to beiscsi_conn structure
|
||||
* @phba: The phba instance
|
||||
* @cid: The cid to free
|
||||
*/
|
||||
static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
|
||||
struct beiscsi_conn *beiscsi_conn,
|
||||
unsigned int cid)
|
||||
{
|
||||
if (phba->conn_table[cid]) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"Connection table already occupied. Detected clash\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n",
|
||||
cid, beiscsi_conn);
|
||||
phba->conn_table[cid] = beiscsi_conn;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
|
||||
* @cls_session: pointer to iscsi cls session
|
||||
* @cls_conn: pointer to iscsi cls conn
|
||||
* @transport_fd: EP handle(64 bit)
|
||||
*
|
||||
* This function binds the TCP Conn with iSCSI Connection and Session.
|
||||
*/
|
||||
int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct iscsi_cls_conn *cls_conn,
|
||||
u64 transport_fd, int is_leading)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
|
||||
struct Scsi_Host *shost =
|
||||
(struct Scsi_Host *)iscsi_session_to_shost(cls_session);
|
||||
struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_endpoint *ep;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n");
|
||||
ep = iscsi_lookup_endpoint(transport_fd);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
beiscsi_ep = ep->dd_data;
|
||||
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
|
||||
return -EINVAL;
|
||||
|
||||
if (beiscsi_ep->phba != phba) {
|
||||
SE_DEBUG(DBG_LVL_8,
|
||||
"beiscsi_ep->hba=%p not equal to phba=%p \n",
|
||||
beiscsi_ep->phba, phba);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
|
||||
beiscsi_conn->ep = beiscsi_ep;
|
||||
beiscsi_ep->conn = beiscsi_conn;
|
||||
SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n",
|
||||
beiscsi_conn, conn, beiscsi_ep->ep_cid);
|
||||
return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_get_param - get the iscsi parameter
|
||||
* @cls_conn: pointer to iscsi cls conn
|
||||
* @param: parameter type identifier
|
||||
* @buf: buffer pointer
|
||||
*
|
||||
* returns iscsi parameter
|
||||
*/
|
||||
int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf)
|
||||
{
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
|
||||
int len = 0;
|
||||
|
||||
beiscsi_ep = beiscsi_conn->ep;
|
||||
if (!beiscsi_ep) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"In beiscsi_conn_get_param , no beiscsi_ep\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (param) {
|
||||
case ISCSI_PARAM_CONN_PORT:
|
||||
len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
|
||||
break;
|
||||
case ISCSI_PARAM_CONN_ADDRESS:
|
||||
if (beiscsi_ep->ip_type == BE2_IPV4)
|
||||
len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
|
||||
else
|
||||
len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
|
||||
break;
|
||||
default:
|
||||
return iscsi_conn_get_param(cls_conn, param, buf);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf, int buflen)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_session *session = conn->session;
|
||||
int ret;
|
||||
|
||||
ret = iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* If userspace tried to set the value to higher than we can
|
||||
* support override here.
|
||||
*/
|
||||
switch (param) {
|
||||
case ISCSI_PARAM_FIRST_BURST:
|
||||
if (session->first_burst > 8192)
|
||||
session->first_burst = 8192;
|
||||
break;
|
||||
case ISCSI_PARAM_MAX_RECV_DLENGTH:
|
||||
if (conn->max_recv_dlength > 65536)
|
||||
conn->max_recv_dlength = 65536;
|
||||
break;
|
||||
case ISCSI_PARAM_MAX_BURST:
|
||||
if (session->first_burst > 262144)
|
||||
session->first_burst = 262144;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_get_host_param - get the iscsi parameter
|
||||
* @shost: pointer to scsi_host structure
|
||||
* @param: parameter type identifier
|
||||
* @buf: buffer pointer
|
||||
*
|
||||
* returns host parameter
|
||||
*/
|
||||
int beiscsi_get_host_param(struct Scsi_Host *shost,
|
||||
enum iscsi_host_param param, char *buf)
|
||||
{
|
||||
struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
|
||||
int len = 0;
|
||||
|
||||
switch (param) {
|
||||
case ISCSI_HOST_PARAM_HWADDRESS:
|
||||
be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address);
|
||||
len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
|
||||
break;
|
||||
default:
|
||||
return iscsi_host_get_param(shost, param, buf);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_get_stats - get the iscsi stats
|
||||
* @cls_conn: pointer to iscsi cls conn
|
||||
* @stats: pointer to iscsi_stats structure
|
||||
*
|
||||
* returns iscsi stats
|
||||
*/
|
||||
void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
|
||||
struct iscsi_stats *stats)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n");
|
||||
stats->txdata_octets = conn->txdata_octets;
|
||||
stats->rxdata_octets = conn->rxdata_octets;
|
||||
stats->dataout_pdus = conn->dataout_pdus_cnt;
|
||||
stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
|
||||
stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
|
||||
stats->datain_pdus = conn->datain_pdus_cnt;
|
||||
stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
|
||||
stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
|
||||
stats->r2t_pdus = conn->r2t_pdus_cnt;
|
||||
stats->digest_err = 0;
|
||||
stats->timeout_err = 0;
|
||||
stats->custom_length = 0;
|
||||
strcpy(stats->custom[0].desc, "eh_abort_cnt");
|
||||
stats->custom[0].value = conn->eh_abort_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_set_params_for_offld - get the parameters for offload
|
||||
* @beiscsi_conn: pointer to beiscsi_conn
|
||||
* @params: pointer to offload_params structure
|
||||
*/
|
||||
static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
|
||||
struct beiscsi_offload_params *params)
|
||||
{
|
||||
struct iscsi_conn *conn = beiscsi_conn->conn;
|
||||
struct iscsi_session *session = conn->session;
|
||||
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
|
||||
params, session->max_burst);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params,
|
||||
max_send_data_segment_length, params,
|
||||
conn->max_xmit_dlength);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
|
||||
params, session->first_burst);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
|
||||
session->erl);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
|
||||
conn->datadgst_en);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
|
||||
conn->hdrdgst_en);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
|
||||
session->initial_r2t_en);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
|
||||
session->imm_data_en);
|
||||
AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
|
||||
(conn->exp_statsn - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_start - offload of session to chip
|
||||
* @cls_conn: pointer to beiscsi_conn
|
||||
*/
|
||||
int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct beiscsi_offload_params params;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
|
||||
memset(¶ms, 0, sizeof(struct beiscsi_offload_params));
|
||||
beiscsi_ep = beiscsi_conn->ep;
|
||||
if (!beiscsi_ep)
|
||||
SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
|
||||
|
||||
free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
|
||||
beiscsi_conn->login_in_progress = 0;
|
||||
beiscsi_set_params_for_offld(beiscsi_conn, ¶ms);
|
||||
beiscsi_offload_connection(beiscsi_conn, ¶ms);
|
||||
iscsi_conn_start(cls_conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_get_cid - Allocate a cid
|
||||
* @phba: The phba instance
|
||||
*/
|
||||
static int beiscsi_get_cid(struct beiscsi_hba *phba)
|
||||
{
|
||||
unsigned short cid = 0xFFFF;
|
||||
|
||||
if (!phba->avlbl_cids)
|
||||
return cid;
|
||||
|
||||
cid = phba->cid_array[phba->cid_alloc++];
|
||||
if (phba->cid_alloc == phba->params.cxns_per_ctrl)
|
||||
phba->cid_alloc = 0;
|
||||
phba->avlbl_cids--;
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_open_conn - Ask FW to open a TCP connection
|
||||
* @ep: endpoint to be used
|
||||
* @src_addr: The source IP address
|
||||
* @dst_addr: The Destination IP address
|
||||
*
|
||||
* Asks the FW to open a TCP connection
|
||||
*/
|
||||
static int beiscsi_open_conn(struct iscsi_endpoint *ep,
|
||||
struct sockaddr *src_addr,
|
||||
struct sockaddr *dst_addr, int non_blocking)
|
||||
{
|
||||
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
|
||||
struct beiscsi_hba *phba = beiscsi_ep->phba;
|
||||
int ret = -1;
|
||||
|
||||
beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
|
||||
if (beiscsi_ep->ep_cid == 0xFFFF) {
|
||||
SE_DEBUG(DBG_LVL_1, "No free cid available\n");
|
||||
return ret;
|
||||
}
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ",
|
||||
beiscsi_ep->ep_cid);
|
||||
phba->ep_array[beiscsi_ep->ep_cid] = ep;
|
||||
if (beiscsi_ep->ep_cid >
|
||||
(phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) {
|
||||
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
beiscsi_ep->cid_vld = 0;
|
||||
return mgmt_open_connection(phba, dst_addr, beiscsi_ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_put_cid - Free the cid
|
||||
* @phba: The phba for which the cid is being freed
|
||||
* @cid: The cid to free
|
||||
*/
|
||||
static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
|
||||
{
|
||||
phba->avlbl_cids++;
|
||||
phba->cid_array[phba->cid_free++] = cid;
|
||||
if (phba->cid_free == phba->params.cxns_per_ctrl)
|
||||
phba->cid_free = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_free_ep - free endpoint
|
||||
* @ep: pointer to iscsi endpoint structure
|
||||
*/
|
||||
static void beiscsi_free_ep(struct iscsi_endpoint *ep)
|
||||
{
|
||||
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
|
||||
struct beiscsi_hba *phba = beiscsi_ep->phba;
|
||||
|
||||
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
|
||||
beiscsi_ep->phba = NULL;
|
||||
iscsi_destroy_endpoint(ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_ep_connect - Ask chip to create TCP Conn
|
||||
* @scsi_host: Pointer to scsi_host structure
|
||||
* @dst_addr: The IP address of Target
|
||||
* @non_blocking: blocking or non-blocking call
|
||||
*
|
||||
* This routines first asks chip to create a connection and then allocates an EP
|
||||
*/
|
||||
struct iscsi_endpoint *
|
||||
beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
|
||||
int non_blocking)
|
||||
{
|
||||
struct beiscsi_hba *phba;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_endpoint *ep;
|
||||
int ret;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n");
|
||||
if (shost)
|
||||
phba = iscsi_host_priv(shost);
|
||||
else {
|
||||
ret = -ENXIO;
|
||||
SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
|
||||
if (!ep) {
|
||||
ret = -ENOMEM;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
beiscsi_ep = ep->dd_data;
|
||||
beiscsi_ep->phba = phba;
|
||||
|
||||
if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
|
||||
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_ep;
|
||||
}
|
||||
|
||||
return ep;
|
||||
|
||||
free_ep:
|
||||
beiscsi_free_ep(ep);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_ep_poll - Poll to see if connection is established
|
||||
* @ep: endpoint to be used
|
||||
* @timeout_ms: timeout specified in millisecs
|
||||
*
|
||||
* Poll to see if TCP connection established
|
||||
*/
|
||||
int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
|
||||
{
|
||||
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_poll\n");
|
||||
if (beiscsi_ep->cid_vld == 1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_close_conn - Upload the connection
|
||||
* @ep: The iscsi endpoint
|
||||
* @flag: The type of connection closure
|
||||
*/
|
||||
static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag)
|
||||
{
|
||||
int ret = 0;
|
||||
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
|
||||
struct beiscsi_hba *phba = beiscsi_ep->phba;
|
||||
|
||||
if (MGMT_STATUS_SUCCESS !=
|
||||
mgmt_upload_connection(phba, beiscsi_ep->ep_cid,
|
||||
CONNECTION_UPLOAD_GRACEFUL)) {
|
||||
SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
|
||||
beiscsi_ep->ep_cid);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_ep_disconnect - Tears down the TCP connection
|
||||
* @ep: endpoint to be used
|
||||
*
|
||||
* Tears down the TCP connection
|
||||
*/
|
||||
void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
|
||||
{
|
||||
struct beiscsi_conn *beiscsi_conn;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct beiscsi_hba *phba;
|
||||
int flag = 0;
|
||||
|
||||
beiscsi_ep = ep->dd_data;
|
||||
phba = beiscsi_ep->phba;
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n");
|
||||
|
||||
if (beiscsi_ep->conn) {
|
||||
beiscsi_conn = beiscsi_ep->conn;
|
||||
iscsi_suspend_queue(beiscsi_conn->conn);
|
||||
beiscsi_close_conn(ep, flag);
|
||||
}
|
||||
|
||||
beiscsi_free_ep(ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
|
||||
* @phba: The phba instance
|
||||
* @cid: The cid to free
|
||||
*/
|
||||
static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
|
||||
unsigned int cid)
|
||||
{
|
||||
if (phba->conn_table[cid])
|
||||
phba->conn_table[cid] = NULL;
|
||||
else {
|
||||
SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_conn_stop - Invalidate and stop the connection
|
||||
* @cls_conn: pointer to get iscsi_conn
|
||||
* @flag: The type of connection closure
|
||||
*/
|
||||
void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
unsigned int status;
|
||||
unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
|
||||
beiscsi_ep = beiscsi_conn->ep;
|
||||
if (!beiscsi_ep) {
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
|
||||
return;
|
||||
}
|
||||
status = mgmt_invalidate_connection(phba, beiscsi_ep,
|
||||
beiscsi_ep->ep_cid, 1,
|
||||
savecfg_flag);
|
||||
if (status != MGMT_STATUS_SUCCESS) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"mgmt_invalidate_connection Failed for cid=%d \n",
|
||||
beiscsi_ep->ep_cid);
|
||||
}
|
||||
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
|
||||
iscsi_conn_stop(cls_conn, flag);
|
||||
}
|
75
drivers/scsi/be2iscsi/be_iscsi.h
Normal file
75
drivers/scsi/be2iscsi/be_iscsi.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BE_ISCSI_
|
||||
#define _BE_ISCSI_
|
||||
|
||||
#include "be_main.h"
|
||||
#include "be_mgmt.h"
|
||||
|
||||
#define BE2_IPV4 0x1
|
||||
#define BE2_IPV6 0x10
|
||||
|
||||
void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
|
||||
struct beiscsi_offload_params *params);
|
||||
|
||||
void beiscsi_offload_iscsi(struct beiscsi_hba *phba, struct iscsi_conn *conn,
|
||||
struct beiscsi_conn *beiscsi_conn,
|
||||
unsigned int fw_handle);
|
||||
|
||||
struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
|
||||
uint16_t cmds_max,
|
||||
uint16_t qdepth,
|
||||
uint32_t initial_cmdsn);
|
||||
|
||||
void beiscsi_session_destroy(struct iscsi_cls_session *cls_session);
|
||||
|
||||
struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session
|
||||
*cls_session, uint32_t cid);
|
||||
|
||||
int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct iscsi_cls_conn *cls_conn,
|
||||
uint64_t transport_fd, int is_leading);
|
||||
|
||||
int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf);
|
||||
|
||||
int beiscsi_get_host_param(struct Scsi_Host *shost,
|
||||
enum iscsi_host_param param, char *buf);
|
||||
|
||||
int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf, int buflen);
|
||||
|
||||
int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn);
|
||||
|
||||
void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag);
|
||||
|
||||
struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost,
|
||||
struct sockaddr *dst_addr,
|
||||
int non_blocking);
|
||||
|
||||
int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
|
||||
|
||||
void beiscsi_ep_disconnect(struct iscsi_endpoint *ep);
|
||||
|
||||
void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
|
||||
struct iscsi_stats *stats);
|
||||
|
||||
#endif
|
3390
drivers/scsi/be2iscsi/be_main.c
Normal file
3390
drivers/scsi/be2iscsi/be_main.c
Normal file
File diff suppressed because it is too large
Load Diff
837
drivers/scsi/be2iscsi/be_main.h
Normal file
837
drivers/scsi/be2iscsi/be_main.h
Normal file
@ -0,0 +1,837 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BEISCSI_MAIN_
|
||||
#define _BEISCSI_MAIN_
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/blk-iopoll.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/iscsi_proto.h>
|
||||
#include <scsi/libiscsi.h>
|
||||
#include <scsi/scsi_transport_iscsi.h>
|
||||
|
||||
#include "be.h"
|
||||
|
||||
|
||||
|
||||
#define DRV_NAME "be2iscsi"
|
||||
#define BUILD_STR "2.0.527.0"
|
||||
|
||||
#define BE_NAME "ServerEngines BladeEngine2" \
|
||||
"Linux iSCSI Driver version" BUILD_STR
|
||||
#define DRV_DESC BE_NAME " " "Driver"
|
||||
|
||||
#define BE_VENDOR_ID 0x19A2
|
||||
#define BE_DEVICE_ID1 0x212
|
||||
#define OC_DEVICE_ID1 0x702
|
||||
#define OC_DEVICE_ID2 0x703
|
||||
|
||||
#define BE2_MAX_SESSIONS 64
|
||||
#define BE2_CMDS_PER_CXN 128
|
||||
#define BE2_LOGOUTS BE2_MAX_SESSIONS
|
||||
#define BE2_TMFS 16
|
||||
#define BE2_NOPOUT_REQ 16
|
||||
#define BE2_ASYNCPDUS BE2_MAX_SESSIONS
|
||||
#define BE2_MAX_ICDS 2048
|
||||
#define BE2_SGE 32
|
||||
#define BE2_DEFPDU_HDR_SZ 64
|
||||
#define BE2_DEFPDU_DATA_SZ 8192
|
||||
#define BE2_IO_DEPTH \
|
||||
(BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ))
|
||||
|
||||
#define BEISCSI_SGLIST_ELEMENTS BE2_SGE
|
||||
|
||||
#define BEISCSI_MAX_CMNDS 1024 /* Max IO's per Ctrlr sht->can_queue */
|
||||
#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */
|
||||
#define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */
|
||||
|
||||
#define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */
|
||||
#define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */
|
||||
#define BEISCSI_NUM_DEVICES_SUPPORTED 0x01
|
||||
#define BEISCSI_MAX_FRAGS_INIT 192
|
||||
#define BE_NUM_MSIX_ENTRIES 1
|
||||
#define MPU_EP_SEMAPHORE 0xac
|
||||
|
||||
#define BE_SENSE_INFO_SIZE 258
|
||||
#define BE_ISCSI_PDU_HEADER_SIZE 64
|
||||
#define BE_MIN_MEM_SIZE 16384
|
||||
|
||||
#define IIOC_SCSI_DATA 0x05 /* Write Operation */
|
||||
|
||||
#define DBG_LVL 0x00000001
|
||||
#define DBG_LVL_1 0x00000001
|
||||
#define DBG_LVL_2 0x00000002
|
||||
#define DBG_LVL_3 0x00000004
|
||||
#define DBG_LVL_4 0x00000008
|
||||
#define DBG_LVL_5 0x00000010
|
||||
#define DBG_LVL_6 0x00000020
|
||||
#define DBG_LVL_7 0x00000040
|
||||
#define DBG_LVL_8 0x00000080
|
||||
|
||||
#define SE_DEBUG(debug_mask, fmt, args...) \
|
||||
do { \
|
||||
if (debug_mask & DBG_LVL) { \
|
||||
printk(KERN_ERR "(%s():%d):", __func__, __LINE__);\
|
||||
printk(fmt, ##args); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/**
|
||||
* hardware needs the async PDU buffers to be posted in multiples of 8
|
||||
* So have atleast 8 of them by default
|
||||
*/
|
||||
|
||||
#define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx)
|
||||
|
||||
/********* Memory BAR register ************/
|
||||
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
|
||||
/**
|
||||
* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
|
||||
* Disable" may still globally block interrupts in addition to individual
|
||||
* interrupt masks; a mechanism for the device driver to block all interrupts
|
||||
* atomically without having to arbitrate for the PCI Interrupt Disable bit
|
||||
* with the OS.
|
||||
*/
|
||||
#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */
|
||||
|
||||
/********* ISR0 Register offset **********/
|
||||
#define CEV_ISR0_OFFSET 0xC18
|
||||
#define CEV_ISR_SIZE 4
|
||||
|
||||
/**
|
||||
* Macros for reading/writing a protection domain or CSR registers
|
||||
* in BladeEngine.
|
||||
*/
|
||||
|
||||
#define DB_TXULP0_OFFSET 0x40
|
||||
#define DB_RXULP0_OFFSET 0xA0
|
||||
/********* Event Q door bell *************/
|
||||
#define DB_EQ_OFFSET DB_CQ_OFFSET
|
||||
#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */
|
||||
/* Clear the interrupt for this eq */
|
||||
#define DB_EQ_CLR_SHIFT (9) /* bit 9 */
|
||||
/* Must be 1 */
|
||||
#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */
|
||||
/* Number of event entries processed */
|
||||
#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
|
||||
/* Rearm bit */
|
||||
#define DB_EQ_REARM_SHIFT (29) /* bit 29 */
|
||||
|
||||
/********* Compl Q door bell *************/
|
||||
#define DB_CQ_OFFSET 0x120
|
||||
#define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */
|
||||
/* Number of event entries processed */
|
||||
#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
|
||||
/* Rearm bit */
|
||||
#define DB_CQ_REARM_SHIFT (29) /* bit 29 */
|
||||
|
||||
#define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr)
|
||||
#define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\
|
||||
(GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id)
|
||||
#define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\
|
||||
(GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id)
|
||||
|
||||
#define PAGES_REQUIRED(x) \
|
||||
((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
|
||||
|
||||
enum be_mem_enum {
|
||||
HWI_MEM_ADDN_CONTEXT,
|
||||
HWI_MEM_CQ,
|
||||
HWI_MEM_EQ,
|
||||
HWI_MEM_WRB,
|
||||
HWI_MEM_WRBH,
|
||||
HWI_MEM_SGLH, /* 5 */
|
||||
HWI_MEM_SGE,
|
||||
HWI_MEM_ASYNC_HEADER_BUF,
|
||||
HWI_MEM_ASYNC_DATA_BUF,
|
||||
HWI_MEM_ASYNC_HEADER_RING,
|
||||
HWI_MEM_ASYNC_DATA_RING, /* 10 */
|
||||
HWI_MEM_ASYNC_HEADER_HANDLE,
|
||||
HWI_MEM_ASYNC_DATA_HANDLE,
|
||||
HWI_MEM_ASYNC_PDU_CONTEXT,
|
||||
ISCSI_MEM_GLOBAL_HEADER,
|
||||
SE_MEM_MAX /* 15 */
|
||||
};
|
||||
|
||||
struct be_bus_address32 {
|
||||
unsigned int address_lo;
|
||||
unsigned int address_hi;
|
||||
};
|
||||
|
||||
struct be_bus_address64 {
|
||||
unsigned long long address;
|
||||
};
|
||||
|
||||
struct be_bus_address {
|
||||
union {
|
||||
struct be_bus_address32 a32;
|
||||
struct be_bus_address64 a64;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct mem_array {
|
||||
struct be_bus_address bus_address; /* Bus address of location */
|
||||
void *virtual_address; /* virtual address to the location */
|
||||
unsigned int size; /* Size required by memory block */
|
||||
};
|
||||
|
||||
struct be_mem_descriptor {
|
||||
unsigned int index; /* Index of this memory parameter */
|
||||
unsigned int category; /* type indicates cached/non-cached */
|
||||
unsigned int num_elements; /* number of elements in this
|
||||
* descriptor
|
||||
*/
|
||||
unsigned int alignment_mask; /* Alignment mask for this block */
|
||||
unsigned int size_in_bytes; /* Size required by memory block */
|
||||
struct mem_array *mem_array;
|
||||
};
|
||||
|
||||
struct sgl_handle {
|
||||
unsigned int sgl_index;
|
||||
struct iscsi_sge *pfrag;
|
||||
};
|
||||
|
||||
struct hba_parameters {
|
||||
unsigned int ios_per_ctrl;
|
||||
unsigned int cxns_per_ctrl;
|
||||
unsigned int asyncpdus_per_ctrl;
|
||||
unsigned int icds_per_ctrl;
|
||||
unsigned int num_sge_per_io;
|
||||
unsigned int defpdu_hdr_sz;
|
||||
unsigned int defpdu_data_sz;
|
||||
unsigned int num_cq_entries;
|
||||
unsigned int num_eq_entries;
|
||||
unsigned int wrbs_per_cxn;
|
||||
unsigned int crashmode;
|
||||
unsigned int hba_num;
|
||||
|
||||
unsigned int mgmt_ws_sz;
|
||||
unsigned int hwi_ws_sz;
|
||||
|
||||
unsigned int eto;
|
||||
unsigned int ldto;
|
||||
|
||||
unsigned int dbg_flags;
|
||||
unsigned int num_cxn;
|
||||
|
||||
unsigned int eq_timer;
|
||||
/**
|
||||
* These are calculated from other params. They're here
|
||||
* for debug purposes
|
||||
*/
|
||||
unsigned int num_mcc_pages;
|
||||
unsigned int num_mcc_cq_pages;
|
||||
unsigned int num_cq_pages;
|
||||
unsigned int num_eq_pages;
|
||||
|
||||
unsigned int num_async_pdu_buf_pages;
|
||||
unsigned int num_async_pdu_buf_sgl_pages;
|
||||
unsigned int num_async_pdu_buf_cq_pages;
|
||||
|
||||
unsigned int num_async_pdu_hdr_pages;
|
||||
unsigned int num_async_pdu_hdr_sgl_pages;
|
||||
unsigned int num_async_pdu_hdr_cq_pages;
|
||||
|
||||
unsigned int num_sge;
|
||||
};
|
||||
|
||||
struct beiscsi_hba {
|
||||
struct hba_parameters params;
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
unsigned int mem_req[SE_MEM_MAX];
|
||||
/* PCI BAR mapped addresses */
|
||||
u8 __iomem *csr_va; /* CSR */
|
||||
u8 __iomem *db_va; /* Door Bell */
|
||||
u8 __iomem *pci_va; /* PCI Config */
|
||||
struct be_bus_address csr_pa; /* CSR */
|
||||
struct be_bus_address db_pa; /* CSR */
|
||||
struct be_bus_address pci_pa; /* CSR */
|
||||
/* PCI representation of our HBA */
|
||||
struct pci_dev *pcidev;
|
||||
unsigned int state;
|
||||
unsigned short asic_revision;
|
||||
struct blk_iopoll iopoll;
|
||||
struct be_mem_descriptor *init_mem;
|
||||
|
||||
unsigned short io_sgl_alloc_index;
|
||||
unsigned short io_sgl_free_index;
|
||||
unsigned short io_sgl_hndl_avbl;
|
||||
struct sgl_handle **io_sgl_hndl_base;
|
||||
|
||||
unsigned short eh_sgl_alloc_index;
|
||||
unsigned short eh_sgl_free_index;
|
||||
unsigned short eh_sgl_hndl_avbl;
|
||||
struct sgl_handle **eh_sgl_hndl_base;
|
||||
spinlock_t io_sgl_lock;
|
||||
spinlock_t mgmt_sgl_lock;
|
||||
spinlock_t isr_lock;
|
||||
unsigned int age;
|
||||
unsigned short avlbl_cids;
|
||||
unsigned short cid_alloc;
|
||||
unsigned short cid_free;
|
||||
struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2];
|
||||
struct list_head hba_queue;
|
||||
unsigned short *cid_array;
|
||||
struct iscsi_endpoint **ep_array;
|
||||
struct Scsi_Host *shost;
|
||||
struct {
|
||||
/**
|
||||
* group together since they are used most frequently
|
||||
* for cid to cri conversion
|
||||
*/
|
||||
unsigned int iscsi_cid_start;
|
||||
unsigned int phys_port;
|
||||
|
||||
unsigned int isr_offset;
|
||||
unsigned int iscsi_icd_start;
|
||||
unsigned int iscsi_cid_count;
|
||||
unsigned int iscsi_icd_count;
|
||||
unsigned int pci_function;
|
||||
|
||||
unsigned short cid_alloc;
|
||||
unsigned short cid_free;
|
||||
unsigned short avlbl_cids;
|
||||
spinlock_t cid_lock;
|
||||
} fw_config;
|
||||
|
||||
u8 mac_address[ETH_ALEN];
|
||||
unsigned short todo_cq;
|
||||
unsigned short todo_mcc_cq;
|
||||
char wq_name[20];
|
||||
struct workqueue_struct *wq; /* The actuak work queue */
|
||||
struct work_struct work_cqs; /* The work being queued */
|
||||
struct be_ctrl_info ctrl;
|
||||
};
|
||||
|
||||
struct beiscsi_session {
|
||||
struct pci_pool *bhs_pool;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct beiscsi_conn - iscsi connection structure
|
||||
*/
|
||||
struct beiscsi_conn {
|
||||
struct iscsi_conn *conn;
|
||||
struct beiscsi_hba *phba;
|
||||
u32 exp_statsn;
|
||||
u32 beiscsi_conn_cid;
|
||||
struct beiscsi_endpoint *ep;
|
||||
unsigned short login_in_progress;
|
||||
struct sgl_handle *plogin_sgl_handle;
|
||||
struct beiscsi_session *beiscsi_sess;
|
||||
};
|
||||
|
||||
/* This structure is used by the chip */
|
||||
struct pdu_data_out {
|
||||
u32 dw[12];
|
||||
};
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_pdu_data_out {
|
||||
u8 opcode[6]; /* opcode */
|
||||
u8 rsvd0[2]; /* should be 0 */
|
||||
u8 rsvd1[7];
|
||||
u8 final_bit; /* F bit */
|
||||
u8 rsvd2[16];
|
||||
u8 ahs_length[8]; /* no AHS */
|
||||
u8 data_len_hi[8];
|
||||
u8 data_len_lo[16]; /* DataSegmentLength */
|
||||
u8 lun[64];
|
||||
u8 itt[32]; /* ITT; initiator task tag */
|
||||
u8 ttt[32]; /* TTT; valid for R2T or 0xffffffff */
|
||||
u8 rsvd3[32];
|
||||
u8 exp_stat_sn[32];
|
||||
u8 rsvd4[32];
|
||||
u8 data_sn[32];
|
||||
u8 buffer_offset[32];
|
||||
u8 rsvd5[32];
|
||||
};
|
||||
|
||||
struct be_cmd_bhs {
|
||||
struct iscsi_cmd iscsi_hdr;
|
||||
unsigned char pad1[16];
|
||||
struct pdu_data_out iscsi_data_pdu;
|
||||
unsigned char pad2[BE_SENSE_INFO_SIZE -
|
||||
sizeof(struct pdu_data_out)];
|
||||
};
|
||||
|
||||
struct beiscsi_io_task {
|
||||
struct wrb_handle *pwrb_handle;
|
||||
struct sgl_handle *psgl_handle;
|
||||
struct beiscsi_conn *conn;
|
||||
struct scsi_cmnd *scsi_cmnd;
|
||||
unsigned int cmd_sn;
|
||||
unsigned int flags;
|
||||
unsigned short cid;
|
||||
unsigned short header_len;
|
||||
|
||||
struct be_cmd_bhs *cmd_bhs;
|
||||
struct be_bus_address bhs_pa;
|
||||
unsigned short bhs_len;
|
||||
};
|
||||
|
||||
struct be_nonio_bhs {
|
||||
struct iscsi_hdr iscsi_hdr;
|
||||
unsigned char pad1[16];
|
||||
struct pdu_data_out iscsi_data_pdu;
|
||||
unsigned char pad2[BE_SENSE_INFO_SIZE -
|
||||
sizeof(struct pdu_data_out)];
|
||||
};
|
||||
|
||||
struct be_status_bhs {
|
||||
struct iscsi_cmd iscsi_hdr;
|
||||
unsigned char pad1[16];
|
||||
/**
|
||||
* The plus 2 below is to hold the sense info length that gets
|
||||
* DMA'ed by RxULP
|
||||
*/
|
||||
unsigned char sense_info[BE_SENSE_INFO_SIZE];
|
||||
};
|
||||
|
||||
struct iscsi_sge {
|
||||
u32 dw[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_iscsi_sge {
|
||||
u8 addr_hi[32];
|
||||
u8 addr_lo[32];
|
||||
u8 sge_offset[22]; /* DWORD 2 */
|
||||
u8 rsvd0[9]; /* DWORD 2 */
|
||||
u8 last_sge; /* DWORD 2 */
|
||||
u8 len[17]; /* DWORD 3 */
|
||||
u8 rsvd1[15]; /* DWORD 3 */
|
||||
};
|
||||
|
||||
struct beiscsi_offload_params {
|
||||
u32 dw[5];
|
||||
};
|
||||
|
||||
#define OFFLD_PARAMS_ERL 0x00000003
|
||||
#define OFFLD_PARAMS_DDE 0x00000004
|
||||
#define OFFLD_PARAMS_HDE 0x00000008
|
||||
#define OFFLD_PARAMS_IR2T 0x00000010
|
||||
#define OFFLD_PARAMS_IMD 0x00000020
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_beiscsi_offload_params {
|
||||
u8 max_burst_length[32];
|
||||
u8 max_send_data_segment_length[32];
|
||||
u8 first_burst_length[32];
|
||||
u8 erl[2];
|
||||
u8 dde[1];
|
||||
u8 hde[1];
|
||||
u8 ir2t[1];
|
||||
u8 imd[1];
|
||||
u8 pad[26];
|
||||
u8 exp_statsn[32];
|
||||
};
|
||||
|
||||
/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
|
||||
struct beiscsi_hba *phba, struct sol_cqe *psol);*/
|
||||
|
||||
struct async_pdu_handle {
|
||||
struct list_head link;
|
||||
struct be_bus_address pa;
|
||||
void *pbuffer;
|
||||
unsigned int consumed;
|
||||
unsigned char index;
|
||||
unsigned char is_header;
|
||||
unsigned short cri;
|
||||
unsigned long buffer_len;
|
||||
};
|
||||
|
||||
struct hwi_async_entry {
|
||||
struct {
|
||||
unsigned char hdr_received;
|
||||
unsigned char hdr_len;
|
||||
unsigned short bytes_received;
|
||||
unsigned int bytes_needed;
|
||||
struct list_head list;
|
||||
} wait_queue;
|
||||
|
||||
struct list_head header_busy_list;
|
||||
struct list_head data_busy_list;
|
||||
};
|
||||
|
||||
#define BE_MIN_ASYNC_ENTRIES 128
|
||||
|
||||
struct hwi_async_pdu_context {
|
||||
struct {
|
||||
struct be_bus_address pa_base;
|
||||
void *va_base;
|
||||
void *ring_base;
|
||||
struct async_pdu_handle *handle_base;
|
||||
|
||||
unsigned int host_write_ptr;
|
||||
unsigned int ep_read_ptr;
|
||||
unsigned int writables;
|
||||
|
||||
unsigned int free_entries;
|
||||
unsigned int busy_entries;
|
||||
unsigned int buffer_size;
|
||||
unsigned int num_entries;
|
||||
|
||||
struct list_head free_list;
|
||||
} async_header;
|
||||
|
||||
struct {
|
||||
struct be_bus_address pa_base;
|
||||
void *va_base;
|
||||
void *ring_base;
|
||||
struct async_pdu_handle *handle_base;
|
||||
|
||||
unsigned int host_write_ptr;
|
||||
unsigned int ep_read_ptr;
|
||||
unsigned int writables;
|
||||
|
||||
unsigned int free_entries;
|
||||
unsigned int busy_entries;
|
||||
unsigned int buffer_size;
|
||||
struct list_head free_list;
|
||||
unsigned int num_entries;
|
||||
} async_data;
|
||||
|
||||
/**
|
||||
* This is a varying size list! Do not add anything
|
||||
* after this entry!!
|
||||
*/
|
||||
struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES];
|
||||
};
|
||||
|
||||
#define PDUCQE_CODE_MASK 0x0000003F
|
||||
#define PDUCQE_DPL_MASK 0xFFFF0000
|
||||
#define PDUCQE_INDEX_MASK 0x0000FFFF
|
||||
|
||||
struct i_t_dpdu_cqe {
|
||||
u32 dw[4];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_i_t_dpdu_cqe {
|
||||
u8 db_addr_hi[32];
|
||||
u8 db_addr_lo[32];
|
||||
u8 code[6];
|
||||
u8 cid[10];
|
||||
u8 dpl[16];
|
||||
u8 index[16];
|
||||
u8 num_cons[10];
|
||||
u8 rsvd0[4];
|
||||
u8 final;
|
||||
u8 valid;
|
||||
} __packed;
|
||||
|
||||
#define CQE_VALID_MASK 0x80000000
|
||||
#define CQE_CODE_MASK 0x0000003F
|
||||
#define CQE_CID_MASK 0x0000FFC0
|
||||
|
||||
#define EQE_VALID_MASK 0x00000001
|
||||
#define EQE_MAJORCODE_MASK 0x0000000E
|
||||
#define EQE_RESID_MASK 0xFFFF0000
|
||||
|
||||
struct be_eq_entry {
|
||||
u32 dw[1];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_eq_entry {
|
||||
u8 valid; /* DWORD 0 */
|
||||
u8 major_code[3]; /* DWORD 0 */
|
||||
u8 minor_code[12]; /* DWORD 0 */
|
||||
u8 resource_id[16]; /* DWORD 0 */
|
||||
|
||||
} __packed;
|
||||
|
||||
struct cq_db {
|
||||
u32 dw[1];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_cq_db {
|
||||
u8 qid[10];
|
||||
u8 event[1];
|
||||
u8 rsvd0[5];
|
||||
u8 num_popped[13];
|
||||
u8 rearm[1];
|
||||
u8 rsvd1[2];
|
||||
} __packed;
|
||||
|
||||
void beiscsi_process_eq(struct beiscsi_hba *phba);
|
||||
|
||||
|
||||
struct iscsi_wrb {
|
||||
u32 dw[16];
|
||||
} __packed;
|
||||
|
||||
#define WRB_TYPE_MASK 0xF0000000
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_iscsi_wrb {
|
||||
u8 lun[14]; /* DWORD 0 */
|
||||
u8 lt; /* DWORD 0 */
|
||||
u8 invld; /* DWORD 0 */
|
||||
u8 wrb_idx[8]; /* DWORD 0 */
|
||||
u8 dsp; /* DWORD 0 */
|
||||
u8 dmsg; /* DWORD 0 */
|
||||
u8 undr_run; /* DWORD 0 */
|
||||
u8 over_run; /* DWORD 0 */
|
||||
u8 type[4]; /* DWORD 0 */
|
||||
u8 ptr2nextwrb[8]; /* DWORD 1 */
|
||||
u8 r2t_exp_dtl[24]; /* DWORD 1 */
|
||||
u8 sgl_icd_idx[12]; /* DWORD 2 */
|
||||
u8 rsvd0[20]; /* DWORD 2 */
|
||||
u8 exp_data_sn[32]; /* DWORD 3 */
|
||||
u8 iscsi_bhs_addr_hi[32]; /* DWORD 4 */
|
||||
u8 iscsi_bhs_addr_lo[32]; /* DWORD 5 */
|
||||
u8 cmdsn_itt[32]; /* DWORD 6 */
|
||||
u8 dif_ref_tag[32]; /* DWORD 7 */
|
||||
u8 sge0_addr_hi[32]; /* DWORD 8 */
|
||||
u8 sge0_addr_lo[32]; /* DWORD 9 */
|
||||
u8 sge0_offset[22]; /* DWORD 10 */
|
||||
u8 pbs; /* DWORD 10 */
|
||||
u8 dif_mode[2]; /* DWORD 10 */
|
||||
u8 rsvd1[6]; /* DWORD 10 */
|
||||
u8 sge0_last; /* DWORD 10 */
|
||||
u8 sge0_len[17]; /* DWORD 11 */
|
||||
u8 dif_meta_tag[14]; /* DWORD 11 */
|
||||
u8 sge0_in_ddr; /* DWORD 11 */
|
||||
u8 sge1_addr_hi[32]; /* DWORD 12 */
|
||||
u8 sge1_addr_lo[32]; /* DWORD 13 */
|
||||
u8 sge1_r2t_offset[22]; /* DWORD 14 */
|
||||
u8 rsvd2[9]; /* DWORD 14 */
|
||||
u8 sge1_last; /* DWORD 14 */
|
||||
u8 sge1_len[17]; /* DWORD 15 */
|
||||
u8 ref_sgl_icd_idx[12]; /* DWORD 15 */
|
||||
u8 rsvd3[2]; /* DWORD 15 */
|
||||
u8 sge1_in_ddr; /* DWORD 15 */
|
||||
|
||||
} __packed;
|
||||
|
||||
struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
|
||||
int index);
|
||||
void
|
||||
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
|
||||
|
||||
struct pdu_nop_out {
|
||||
u32 dw[12];
|
||||
};
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_pdu_nop_out {
|
||||
u8 opcode[6]; /* opcode 0x00 */
|
||||
u8 i_bit; /* I Bit */
|
||||
u8 x_bit; /* reserved; should be 0 */
|
||||
u8 fp_bit_filler1[7];
|
||||
u8 f_bit; /* always 1 */
|
||||
u8 reserved1[16];
|
||||
u8 ahs_length[8]; /* no AHS */
|
||||
u8 data_len_hi[8];
|
||||
u8 data_len_lo[16]; /* DataSegmentLength */
|
||||
u8 lun[64];
|
||||
u8 itt[32]; /* initiator id for ping or 0xffffffff */
|
||||
u8 ttt[32]; /* target id for ping or 0xffffffff */
|
||||
u8 cmd_sn[32];
|
||||
u8 exp_stat_sn[32];
|
||||
u8 reserved5[128];
|
||||
};
|
||||
|
||||
#define PDUBASE_OPCODE_MASK 0x0000003F
|
||||
#define PDUBASE_DATALENHI_MASK 0x0000FF00
|
||||
#define PDUBASE_DATALENLO_MASK 0xFFFF0000
|
||||
|
||||
struct pdu_base {
|
||||
u32 dw[16];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_pdu_base {
|
||||
u8 opcode[6];
|
||||
u8 i_bit; /* immediate bit */
|
||||
u8 x_bit; /* reserved, always 0 */
|
||||
u8 reserved1[24]; /* opcode-specific fields */
|
||||
u8 ahs_length[8]; /* length units is 4 byte words */
|
||||
u8 data_len_hi[8];
|
||||
u8 data_len_lo[16]; /* DatasegmentLength */
|
||||
u8 lun[64]; /* lun or opcode-specific fields */
|
||||
u8 itt[32]; /* initiator task tag */
|
||||
u8 reserved4[224];
|
||||
};
|
||||
|
||||
struct iscsi_target_context_update_wrb {
|
||||
u32 dw[16];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_iscsi_target_context_update_wrb {
|
||||
u8 lun[14]; /* DWORD 0 */
|
||||
u8 lt; /* DWORD 0 */
|
||||
u8 invld; /* DWORD 0 */
|
||||
u8 wrb_idx[8]; /* DWORD 0 */
|
||||
u8 dsp; /* DWORD 0 */
|
||||
u8 dmsg; /* DWORD 0 */
|
||||
u8 undr_run; /* DWORD 0 */
|
||||
u8 over_run; /* DWORD 0 */
|
||||
u8 type[4]; /* DWORD 0 */
|
||||
u8 ptr2nextwrb[8]; /* DWORD 1 */
|
||||
u8 max_burst_length[19]; /* DWORD 1 */
|
||||
u8 rsvd0[5]; /* DWORD 1 */
|
||||
u8 rsvd1[15]; /* DWORD 2 */
|
||||
u8 max_send_data_segment_length[17]; /* DWORD 2 */
|
||||
u8 first_burst_length[14]; /* DWORD 3 */
|
||||
u8 rsvd2[2]; /* DWORD 3 */
|
||||
u8 tx_wrbindex_drv_msg[8]; /* DWORD 3 */
|
||||
u8 rsvd3[5]; /* DWORD 3 */
|
||||
u8 session_state[3]; /* DWORD 3 */
|
||||
u8 rsvd4[16]; /* DWORD 4 */
|
||||
u8 tx_jumbo; /* DWORD 4 */
|
||||
u8 hde; /* DWORD 4 */
|
||||
u8 dde; /* DWORD 4 */
|
||||
u8 erl[2]; /* DWORD 4 */
|
||||
u8 domain_id[5]; /* DWORD 4 */
|
||||
u8 mode; /* DWORD 4 */
|
||||
u8 imd; /* DWORD 4 */
|
||||
u8 ir2t; /* DWORD 4 */
|
||||
u8 notpredblq[2]; /* DWORD 4 */
|
||||
u8 compltonack; /* DWORD 4 */
|
||||
u8 stat_sn[32]; /* DWORD 5 */
|
||||
u8 pad_buffer_addr_hi[32]; /* DWORD 6 */
|
||||
u8 pad_buffer_addr_lo[32]; /* DWORD 7 */
|
||||
u8 pad_addr_hi[32]; /* DWORD 8 */
|
||||
u8 pad_addr_lo[32]; /* DWORD 9 */
|
||||
u8 rsvd5[32]; /* DWORD 10 */
|
||||
u8 rsvd6[32]; /* DWORD 11 */
|
||||
u8 rsvd7[32]; /* DWORD 12 */
|
||||
u8 rsvd8[32]; /* DWORD 13 */
|
||||
u8 rsvd9[32]; /* DWORD 14 */
|
||||
u8 rsvd10[32]; /* DWORD 15 */
|
||||
|
||||
} __packed;
|
||||
|
||||
struct be_ring {
|
||||
u32 pages; /* queue size in pages */
|
||||
u32 id; /* queue id assigned by beklib */
|
||||
u32 num; /* number of elements in queue */
|
||||
u32 cidx; /* consumer index */
|
||||
u32 pidx; /* producer index -- not used by most rings */
|
||||
u32 item_size; /* size in bytes of one object */
|
||||
|
||||
void *va; /* The virtual address of the ring. This
|
||||
* should be last to allow 32 & 64 bit debugger
|
||||
* extensions to work.
|
||||
*/
|
||||
};
|
||||
|
||||
struct hwi_wrb_context {
|
||||
struct list_head wrb_handle_list;
|
||||
struct list_head wrb_handle_drvr_list;
|
||||
struct wrb_handle **pwrb_handle_base;
|
||||
struct wrb_handle **pwrb_handle_basestd;
|
||||
struct iscsi_wrb *plast_wrb;
|
||||
unsigned short alloc_index;
|
||||
unsigned short free_index;
|
||||
unsigned short wrb_handles_available;
|
||||
unsigned short cid;
|
||||
};
|
||||
|
||||
struct hwi_controller {
|
||||
struct list_head io_sgl_list;
|
||||
struct list_head eh_sgl_list;
|
||||
struct sgl_handle *psgl_handle_base;
|
||||
unsigned int wrb_mem_index;
|
||||
|
||||
struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2];
|
||||
struct mcc_wrb *pmcc_wrb_base;
|
||||
struct be_ring default_pdu_hdr;
|
||||
struct be_ring default_pdu_data;
|
||||
struct hwi_context_memory *phwi_ctxt;
|
||||
unsigned short cq_errors[CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN];
|
||||
};
|
||||
|
||||
enum hwh_type_enum {
|
||||
HWH_TYPE_IO = 1,
|
||||
HWH_TYPE_LOGOUT = 2,
|
||||
HWH_TYPE_TMF = 3,
|
||||
HWH_TYPE_NOP = 4,
|
||||
HWH_TYPE_IO_RD = 5,
|
||||
HWH_TYPE_LOGIN = 11,
|
||||
HWH_TYPE_INVALID = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
struct wrb_handle {
|
||||
enum hwh_type_enum type;
|
||||
unsigned short wrb_index;
|
||||
unsigned short nxt_wrb_index;
|
||||
|
||||
struct iscsi_task *pio_handle;
|
||||
struct iscsi_wrb *pwrb;
|
||||
};
|
||||
|
||||
struct hwi_context_memory {
|
||||
struct be_eq_obj be_eq;
|
||||
struct be_queue_info be_cq;
|
||||
struct be_queue_info be_mcc_cq;
|
||||
struct be_queue_info be_mcc;
|
||||
|
||||
struct be_queue_info be_def_hdrq;
|
||||
struct be_queue_info be_def_dataq;
|
||||
|
||||
struct be_queue_info be_wrbq[BE2_MAX_SESSIONS];
|
||||
struct be_mcc_wrb_context *pbe_mcc_context;
|
||||
|
||||
struct hwi_async_pdu_context *pasync_ctx;
|
||||
};
|
||||
|
||||
#endif
|
321
drivers/scsi/be2iscsi/be_mgmt.c
Normal file
321
drivers/scsi/be2iscsi/be_mgmt.c
Normal file
@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*
|
||||
*/
|
||||
|
||||
#include "be_mgmt.h"
|
||||
#include "be_iscsi.h"
|
||||
|
||||
unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba)
|
||||
{
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_fw_cfg *req = embedded_payload(wrb);
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
struct be_fw_cfg *pfw_cfg;
|
||||
pfw_cfg = req;
|
||||
phba->fw_config.phys_port = pfw_cfg->phys_port;
|
||||
phba->fw_config.iscsi_icd_start =
|
||||
pfw_cfg->ulp[0].icd_base;
|
||||
phba->fw_config.iscsi_icd_count =
|
||||
pfw_cfg->ulp[0].icd_count;
|
||||
phba->fw_config.iscsi_cid_start =
|
||||
pfw_cfg->ulp[0].sq_base;
|
||||
phba->fw_config.iscsi_cid_count =
|
||||
pfw_cfg->ulp[0].sq_count;
|
||||
} else {
|
||||
shost_printk(KERN_WARNING, phba->shost,
|
||||
"Failed in mgmt_get_fw_config \n");
|
||||
}
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
|
||||
{
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_mgmt_controller_attributes *req;
|
||||
struct be_sge *sge = nonembedded_sgl(wrb);
|
||||
int status = 0;
|
||||
|
||||
nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
|
||||
sizeof(struct be_mgmt_controller_attributes),
|
||||
&nonemb_cmd.dma);
|
||||
if (nonemb_cmd.va == NULL) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"Failed to allocate memory for mgmt_check_supported_fw"
|
||||
"\n");
|
||||
return -1;
|
||||
}
|
||||
nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes);
|
||||
req = nonemb_cmd.va;
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req));
|
||||
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
|
||||
sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
|
||||
sge->len = cpu_to_le32(nonemb_cmd.size);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va;
|
||||
SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n",
|
||||
resp->params.hba_attribs.flashrom_version_string);
|
||||
SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n",
|
||||
resp->params.hba_attribs.firmware_version_string);
|
||||
SE_DEBUG(DBG_LVL_8,
|
||||
"Developer Build, not performing version check...\n");
|
||||
|
||||
} else
|
||||
SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n");
|
||||
if (nonemb_cmd.va)
|
||||
pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct iscsi_cleanup_req *req = embedded_payload(wrb);
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
|
||||
|
||||
req->chute = chute;
|
||||
req->hdr_ring_id = 0;
|
||||
req->data_ring_id = 0;
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status)
|
||||
shost_printk(KERN_WARNING, phba->shost,
|
||||
" mgmt_epfw_cleanup , FAILED\n");
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
unsigned int icd, unsigned int cid)
|
||||
{
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct be_sge *sge = nonembedded_sgl(wrb);
|
||||
struct invalidate_commands_params_in *req;
|
||||
int status = 0;
|
||||
|
||||
nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
|
||||
sizeof(struct invalidate_commands_params_in),
|
||||
&nonemb_cmd.dma);
|
||||
if (nonemb_cmd.va == NULL) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"Failed to allocate memory for"
|
||||
"mgmt_invalidate_icds \n");
|
||||
return -1;
|
||||
}
|
||||
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
|
||||
req = nonemb_cmd.va;
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
|
||||
sizeof(*req));
|
||||
req->ref_handle = 0;
|
||||
req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
|
||||
req->icd_count = 0;
|
||||
req->table[req->icd_count].icd = icd;
|
||||
req->table[req->icd_count].cid = cid;
|
||||
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
|
||||
sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
|
||||
sge->len = cpu_to_le32(nonemb_cmd.size);
|
||||
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status)
|
||||
SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n");
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
if (nonemb_cmd.va)
|
||||
pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
unsigned short cid,
|
||||
unsigned short issue_reset,
|
||||
unsigned short savecfg_flag)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct iscsi_invalidate_connection_params_in *req =
|
||||
embedded_payload(wrb);
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
|
||||
OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
|
||||
sizeof(*req));
|
||||
req->session_handle = beiscsi_ep->fw_handle;
|
||||
req->cid = cid;
|
||||
if (issue_reset)
|
||||
req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
|
||||
else
|
||||
req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
|
||||
req->save_cfg = savecfg_flag;
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status)
|
||||
SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n");
|
||||
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
|
||||
unsigned short cid, unsigned int upload_flag)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct tcp_upload_params_in *req = embedded_payload(wrb);
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
|
||||
OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
|
||||
req->id = (unsigned short)cid;
|
||||
req->upload_type = (unsigned char)upload_flag;
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (status)
|
||||
SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n");
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
struct sockaddr *dst_addr,
|
||||
struct beiscsi_endpoint *beiscsi_ep)
|
||||
{
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
struct hwi_context_memory *phwi_context;
|
||||
struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
|
||||
struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
|
||||
struct tcp_connect_and_offload_in *req = embedded_payload(wrb);
|
||||
unsigned short def_hdr_id;
|
||||
unsigned short def_data_id;
|
||||
struct phys_addr template_address = { 0, 0 };
|
||||
struct phys_addr *ptemplate_address;
|
||||
int status = 0;
|
||||
unsigned short cid = beiscsi_ep->ep_cid;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba);
|
||||
def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba);
|
||||
|
||||
ptemplate_address = &template_address;
|
||||
ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
memset(wrb, 0, sizeof(*wrb));
|
||||
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
|
||||
OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
|
||||
sizeof(*req));
|
||||
if (dst_addr->sa_family == PF_INET) {
|
||||
__be32 s_addr = daddr_in->sin_addr.s_addr;
|
||||
req->ip_address.ip_type = BE2_IPV4;
|
||||
req->ip_address.ip_address[0] = s_addr & 0x000000ff;
|
||||
req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
|
||||
req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
|
||||
req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
|
||||
req->tcp_port = ntohs(daddr_in->sin_port);
|
||||
beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
|
||||
beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
|
||||
beiscsi_ep->ip_type = BE2_IPV4;
|
||||
} else if (dst_addr->sa_family == PF_INET6) {
|
||||
req->ip_address.ip_type = BE2_IPV6;
|
||||
memcpy(&req->ip_address.ip_address,
|
||||
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
|
||||
req->tcp_port = ntohs(daddr_in6->sin6_port);
|
||||
beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
|
||||
memcpy(&beiscsi_ep->dst6_addr,
|
||||
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
|
||||
beiscsi_ep->ip_type = BE2_IPV6;
|
||||
} else{
|
||||
shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n",
|
||||
dst_addr->sa_family);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
req->cid = cid;
|
||||
req->cq_id = phwi_context->be_cq.id;
|
||||
req->defq_id = def_hdr_id;
|
||||
req->hdr_ring_id = def_hdr_id;
|
||||
req->data_ring_id = def_data_id;
|
||||
req->do_offload = 1;
|
||||
req->dataout_template_pa.lo = ptemplate_address->lo;
|
||||
req->dataout_template_pa.hi = ptemplate_address->hi;
|
||||
status = be_mbox_notify(ctrl);
|
||||
if (!status) {
|
||||
struct iscsi_endpoint *ep;
|
||||
struct tcp_connect_and_offload_out *ptcpcnct_out =
|
||||
embedded_payload(wrb);
|
||||
|
||||
ep = phba->ep_array[ptcpcnct_out->cid];
|
||||
beiscsi_ep = ep->dd_data;
|
||||
beiscsi_ep->fw_handle = 0;
|
||||
beiscsi_ep->cid_vld = 1;
|
||||
SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
|
||||
} else
|
||||
SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed\n");
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return status;
|
||||
}
|
249
drivers/scsi/be2iscsi/be_mgmt.h
Normal file
249
drivers/scsi/be2iscsi/be_mgmt.h
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2009 ServerEngines
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@serverengines.com
|
||||
*
|
||||
* ServerEngines
|
||||
* 209 N. Fair Oaks Ave
|
||||
* Sunnyvale, CA 94085
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BEISCSI_MGMT_
|
||||
#define _BEISCSI_MGMT_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
#include "be_iscsi.h"
|
||||
#include "be_main.h"
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_mcc_sge {
|
||||
u8 pa_lo[32]; /* dword 0 */
|
||||
u8 pa_hi[32]; /* dword 1 */
|
||||
u8 length[32]; /* DWORD 2 */
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_mcc_wrb_payload {
|
||||
union {
|
||||
struct amap_mcc_sge sgl[19];
|
||||
u8 embedded[59 * 32]; /* DWORDS 57 to 115 */
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Pseudo amap definition in which each bit of the actual structure is defined
|
||||
* as a byte: used to calculate offset/shift/mask of each field
|
||||
*/
|
||||
struct amap_mcc_wrb {
|
||||
u8 embedded; /* DWORD 0 */
|
||||
u8 rsvd0[2]; /* DWORD 0 */
|
||||
u8 sge_count[5]; /* DWORD 0 */
|
||||
u8 rsvd1[16]; /* DWORD 0 */
|
||||
u8 special[8]; /* DWORD 0 */
|
||||
u8 payload_length[32];
|
||||
u8 tag[64]; /* DWORD 2 */
|
||||
u8 rsvd2[32]; /* DWORD 4 */
|
||||
struct amap_mcc_wrb_payload payload;
|
||||
};
|
||||
|
||||
struct mcc_sge {
|
||||
u32 pa_lo; /* dword 0 */
|
||||
u32 pa_hi; /* dword 1 */
|
||||
u32 length; /* DWORD 2 */
|
||||
} __packed;
|
||||
|
||||
struct mcc_wrb_payload {
|
||||
union {
|
||||
struct mcc_sge sgl[19];
|
||||
u32 embedded[59]; /* DWORDS 57 to 115 */
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
#define MCC_WRB_EMBEDDED_MASK 0x00000001
|
||||
|
||||
struct mcc_wrb {
|
||||
u32 dw[0]; /* DWORD 0 */
|
||||
u32 payload_length;
|
||||
u32 tag[2]; /* DWORD 2 */
|
||||
u32 rsvd2[1]; /* DWORD 4 */
|
||||
struct mcc_wrb_payload payload;
|
||||
};
|
||||
|
||||
unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr,
|
||||
struct beiscsi_endpoint *beiscsi_ep);
|
||||
|
||||
unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
|
||||
unsigned short cid,
|
||||
unsigned int upload_flag);
|
||||
unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
unsigned int icd, unsigned int cid);
|
||||
|
||||
struct iscsi_invalidate_connection_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
unsigned int session_handle;
|
||||
unsigned short cid;
|
||||
unsigned short unused;
|
||||
unsigned short cleanup_type;
|
||||
unsigned short save_cfg;
|
||||
} __packed;
|
||||
|
||||
struct iscsi_invalidate_connection_params_out {
|
||||
unsigned int session_handle;
|
||||
unsigned short cid;
|
||||
unsigned short unused;
|
||||
} __packed;
|
||||
|
||||
union iscsi_invalidate_connection_params {
|
||||
struct iscsi_invalidate_connection_params_in request;
|
||||
struct iscsi_invalidate_connection_params_out response;
|
||||
} __packed;
|
||||
|
||||
struct invalidate_command_table {
|
||||
unsigned short icd;
|
||||
unsigned short cid;
|
||||
} __packed;
|
||||
|
||||
struct invalidate_commands_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
unsigned int ref_handle;
|
||||
unsigned int icd_count;
|
||||
struct invalidate_command_table table[128];
|
||||
unsigned short cleanup_type;
|
||||
unsigned short unused;
|
||||
} __packed;
|
||||
|
||||
struct invalidate_commands_params_out {
|
||||
unsigned int ref_handle;
|
||||
unsigned int icd_count;
|
||||
unsigned int icd_status[128];
|
||||
} __packed;
|
||||
|
||||
union invalidate_commands_params {
|
||||
struct invalidate_commands_params_in request;
|
||||
struct invalidate_commands_params_out response;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_hba_attributes {
|
||||
u8 flashrom_version_string[32];
|
||||
u8 manufacturer_name[32];
|
||||
u32 supported_modes;
|
||||
u8 seeprom_version_lo;
|
||||
u8 seeprom_version_hi;
|
||||
u8 rsvd0[2];
|
||||
u32 fw_cmd_data_struct_version;
|
||||
u32 ep_fw_data_struct_version;
|
||||
u32 future_reserved[12];
|
||||
u32 default_extended_timeout;
|
||||
u8 controller_model_number[32];
|
||||
u8 controller_description[64];
|
||||
u8 controller_serial_number[32];
|
||||
u8 ip_version_string[32];
|
||||
u8 firmware_version_string[32];
|
||||
u8 bios_version_string[32];
|
||||
u8 redboot_version_string[32];
|
||||
u8 driver_version_string[32];
|
||||
u8 fw_on_flash_version_string[32];
|
||||
u32 functionalities_supported;
|
||||
u16 max_cdblength;
|
||||
u8 asic_revision;
|
||||
u8 generational_guid[16];
|
||||
u8 hba_port_count;
|
||||
u16 default_link_down_timeout;
|
||||
u8 iscsi_ver_min_max;
|
||||
u8 multifunction_device;
|
||||
u8 cache_valid;
|
||||
u8 hba_status;
|
||||
u8 max_domains_supported;
|
||||
u8 phy_port;
|
||||
u32 firmware_post_status;
|
||||
u32 hba_mtu[8];
|
||||
u32 future_u32[4];
|
||||
} __packed;
|
||||
|
||||
struct mgmt_controller_attributes {
|
||||
struct mgmt_hba_attributes hba_attribs;
|
||||
u16 pci_vendor_id;
|
||||
u16 pci_device_id;
|
||||
u16 pci_sub_vendor_id;
|
||||
u16 pci_sub_system_id;
|
||||
u8 pci_bus_number;
|
||||
u8 pci_device_number;
|
||||
u8 pci_function_number;
|
||||
u8 interface_type;
|
||||
u64 unique_identifier;
|
||||
u8 netfilters;
|
||||
u8 rsvd0[3];
|
||||
u8 future_u32[4];
|
||||
} __packed;
|
||||
|
||||
struct be_mgmt_controller_attributes {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
struct mgmt_controller_attributes params;
|
||||
} __packed;
|
||||
|
||||
struct be_mgmt_controller_attributes_resp {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
struct mgmt_controller_attributes params;
|
||||
} __packed;
|
||||
|
||||
/* configuration management */
|
||||
|
||||
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
|
||||
|
||||
/* MGMT CMD flags */
|
||||
|
||||
#define MGMT_CMDH_FREE (1<<0)
|
||||
|
||||
/* --- MGMT_ERROR_CODES --- */
|
||||
/* Error Codes returned in the status field of the CMD response header */
|
||||
#define MGMT_STATUS_SUCCESS 0 /* The CMD completed without errors */
|
||||
#define MGMT_STATUS_FAILED 1 /* Error status in the Status field of */
|
||||
/* the CMD_RESPONSE_HEADER */
|
||||
|
||||
#define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\
|
||||
pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
|
||||
bus_address.u.a32.address_lo; \
|
||||
pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
|
||||
bus_address.u.a32.address_hi; \
|
||||
}
|
||||
|
||||
struct beiscsi_endpoint {
|
||||
struct beiscsi_hba *phba;
|
||||
struct beiscsi_sess *sess;
|
||||
struct beiscsi_conn *conn;
|
||||
unsigned short ip_type;
|
||||
char dst6_addr[ISCSI_ADDRESS_BUF_LEN];
|
||||
unsigned long dst_addr;
|
||||
unsigned short ep_cid;
|
||||
unsigned int fw_handle;
|
||||
u16 dst_tcpport;
|
||||
u16 cid_vld;
|
||||
};
|
||||
|
||||
unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
|
||||
unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
unsigned short cid,
|
||||
unsigned short issue_reset,
|
||||
unsigned short savecfg_flag);
|
||||
#endif
|
15
drivers/scsi/bfa/Makefile
Normal file
15
drivers/scsi/bfa/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
|
||||
|
||||
bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
|
||||
|
||||
bfa-y += bfa_core.o bfa_ioc.o bfa_iocfc.o bfa_fcxp.o bfa_lps.o
|
||||
bfa-y += bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o
|
||||
bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
|
||||
bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
|
||||
bfa-y += bfa_csdebug.o bfa_sm.o plog.o
|
||||
|
||||
bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o
|
||||
bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
|
||||
bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
|
||||
|
||||
ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna
|
57
drivers/scsi/bfa/bfa_callback_priv.h
Normal file
57
drivers/scsi/bfa/bfa_callback_priv.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_CALLBACK_PRIV_H__
|
||||
#define __BFA_CALLBACK_PRIV_H__
|
||||
|
||||
#include <cs/bfa_q.h>
|
||||
|
||||
typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
|
||||
|
||||
/**
|
||||
* Generic BFA callback element.
|
||||
*/
|
||||
struct bfa_cb_qe_s {
|
||||
struct list_head qe;
|
||||
bfa_cb_cbfn_t cbfn;
|
||||
bfa_boolean_t once;
|
||||
u32 rsvd;
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
|
||||
(__hcb_qe)->cbfn = (__cbfn); \
|
||||
(__hcb_qe)->cbarg = (__cbarg); \
|
||||
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
|
||||
} while (0)
|
||||
|
||||
#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
|
||||
|
||||
#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
|
||||
(__hcb_qe)->cbfn = (__cbfn); \
|
||||
(__hcb_qe)->cbarg = (__cbarg); \
|
||||
if (!(__hcb_qe)->once) { \
|
||||
list_add_tail((__hcb_qe), &(__bfa)->comp_q); \
|
||||
(__hcb_qe)->once = BFA_TRUE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define bfa_cb_queue_done(__hcb_qe) do { \
|
||||
(__hcb_qe)->once = BFA_FALSE; \
|
||||
} while (0)
|
||||
|
||||
#endif /* __BFA_CALLBACK_PRIV_H__ */
|
205
drivers/scsi/bfa/bfa_cb_ioim_macros.h
Normal file
205
drivers/scsi/bfa/bfa_cb_ioim_macros.h
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
|
||||
*/
|
||||
|
||||
#ifndef __BFA_HCB_IOIM_MACROS_H__
|
||||
#define __BFA_HCB_IOIM_MACROS_H__
|
||||
|
||||
#include <bfa_os_inc.h>
|
||||
/*
|
||||
* #include <linux/dma-mapping.h>
|
||||
*
|
||||
* #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
|
||||
* <scsi/scsi_device.h> #include <scsi/scsi_host.h>
|
||||
*/
|
||||
#include "bfad_im_compat.h"
|
||||
|
||||
/*
|
||||
* task attribute values in FCP-2 FCP_CMND IU
|
||||
*/
|
||||
#define SIMPLE_Q 0
|
||||
#define HEAD_OF_Q 1
|
||||
#define ORDERED_Q 2
|
||||
#define ACA_Q 4
|
||||
#define UNTAGGED 5
|
||||
|
||||
static inline lun_t
|
||||
bfad_int_to_lun(u32 luno)
|
||||
{
|
||||
union {
|
||||
u16 scsi_lun[4];
|
||||
lun_t bfa_lun;
|
||||
} lun;
|
||||
|
||||
lun.bfa_lun = 0;
|
||||
lun.scsi_lun[0] = bfa_os_htons(luno);
|
||||
|
||||
return (lun.bfa_lun);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LUN for the I/O request
|
||||
*/
|
||||
#define bfa_cb_ioim_get_lun(__dio) \
|
||||
bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
|
||||
|
||||
/**
|
||||
* Get CDB for the I/O request
|
||||
*/
|
||||
static inline u8 *
|
||||
bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
|
||||
return ((u8 *) cmnd->cmnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get I/O direction (read/write) for the I/O request
|
||||
*/
|
||||
static inline enum fcp_iodir
|
||||
bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
enum dma_data_direction dmadir;
|
||||
|
||||
dmadir = cmnd->sc_data_direction;
|
||||
if (dmadir == DMA_TO_DEVICE)
|
||||
return FCP_IODIR_WRITE;
|
||||
else if (dmadir == DMA_FROM_DEVICE)
|
||||
return FCP_IODIR_READ;
|
||||
else
|
||||
return FCP_IODIR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IO size in bytes for the I/O request
|
||||
*/
|
||||
static inline u32
|
||||
bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
|
||||
return (scsi_bufflen(cmnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timeout for the I/O request
|
||||
*/
|
||||
static inline u8
|
||||
bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
/*
|
||||
* TBD: need a timeout for scsi passthru
|
||||
*/
|
||||
if (cmnd->device->host == NULL)
|
||||
return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SG element for the I/O request given the SG element index
|
||||
*/
|
||||
static inline union bfi_addr_u
|
||||
bfa_cb_ioim_get_sgaddr(struct bfad_ioim_s *dio, int sgeid)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
struct scatterlist *sge;
|
||||
u64 addr;
|
||||
|
||||
sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
|
||||
addr = (u64) sg_dma_address(sge);
|
||||
|
||||
return (*(union bfi_addr_u *) &addr);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
bfa_cb_ioim_get_sglen(struct bfad_ioim_s *dio, int sgeid)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
struct scatterlist *sge;
|
||||
u32 len;
|
||||
|
||||
sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
|
||||
len = sg_dma_len(sge);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Command Reference Number for the I/O request. 0 if none.
|
||||
*/
|
||||
static inline u8
|
||||
bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SAM-3 priority for the I/O request. 0 is default.
|
||||
*/
|
||||
static inline u8
|
||||
bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
|
||||
*/
|
||||
static inline u8
|
||||
bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
u8 task_attr = UNTAGGED;
|
||||
|
||||
if (cmnd->device->tagged_supported) {
|
||||
switch (cmnd->tag) {
|
||||
case HEAD_OF_QUEUE_TAG:
|
||||
task_attr = HEAD_OF_Q;
|
||||
break;
|
||||
case ORDERED_QUEUE_TAG:
|
||||
task_attr = ORDERED_Q;
|
||||
break;
|
||||
default:
|
||||
task_attr = SIMPLE_Q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return task_attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
|
||||
*/
|
||||
static inline u8
|
||||
bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
|
||||
|
||||
return (cmnd->cmd_len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* __BFA_HCB_IOIM_MACROS_H__ */
|
492
drivers/scsi/bfa/bfa_cee.c
Normal file
492
drivers/scsi/bfa/bfa_cee.c
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <defs/bfa_defs_cee.h>
|
||||
#include <cs/bfa_trc.h>
|
||||
#include <cs/bfa_log.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
#include <cee/bfa_cee.h>
|
||||
#include <bfi/bfi_cee.h>
|
||||
#include <bfi/bfi.h>
|
||||
#include <bfa_ioc.h>
|
||||
#include <cna/bfa_cna_trcmod.h>
|
||||
|
||||
BFA_TRC_FILE(CNA, CEE);
|
||||
|
||||
#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
|
||||
#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
|
||||
|
||||
static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
|
||||
static void bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
|
||||
*dcbcx_stats);
|
||||
static void bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
|
||||
*lldp_stats);
|
||||
static void bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
|
||||
static void bfa_cee_format_cee_cfg(void *buffer);
|
||||
static void bfa_cee_format_cee_stats(void *buffer);
|
||||
|
||||
static void
|
||||
bfa_cee_format_cee_stats(void *buffer)
|
||||
{
|
||||
struct bfa_cee_stats_s *cee_stats = buffer;
|
||||
bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
|
||||
bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
|
||||
bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_cee_format_cee_cfg(void *buffer)
|
||||
{
|
||||
struct bfa_cee_attr_s *cee_cfg = buffer;
|
||||
bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
|
||||
{
|
||||
dcbcx_stats->subtlvs_unrecognized =
|
||||
bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
|
||||
dcbcx_stats->negotiation_failed =
|
||||
bfa_os_ntohl(dcbcx_stats->negotiation_failed);
|
||||
dcbcx_stats->remote_cfg_changed =
|
||||
bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
|
||||
dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
|
||||
dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
|
||||
dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
|
||||
dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
|
||||
dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
|
||||
dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
|
||||
{
|
||||
lldp_stats->frames_transmitted =
|
||||
bfa_os_ntohl(lldp_stats->frames_transmitted);
|
||||
lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
|
||||
lldp_stats->frames_discarded =
|
||||
bfa_os_ntohl(lldp_stats->frames_discarded);
|
||||
lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
|
||||
lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
|
||||
lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
|
||||
lldp_stats->tlvs_unrecognized =
|
||||
bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
|
||||
{
|
||||
cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
|
||||
cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
|
||||
cfg_stats->cee_hw_cfg_changed =
|
||||
bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
|
||||
cfg_stats->recvd_invalid_cfg =
|
||||
bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
|
||||
{
|
||||
lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
|
||||
lldp_cfg->enabled_system_cap =
|
||||
bfa_os_ntohs(lldp_cfg->enabled_system_cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_attr_meminfo()
|
||||
*
|
||||
*
|
||||
* @param[in] void
|
||||
*
|
||||
* @return Size of DMA region
|
||||
*/
|
||||
static u32
|
||||
bfa_cee_attr_meminfo(void)
|
||||
{
|
||||
return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_stats_meminfo()
|
||||
*
|
||||
*
|
||||
* @param[in] void
|
||||
*
|
||||
* @return Size of DMA region
|
||||
*/
|
||||
static u32
|
||||
bfa_cee_stats_meminfo(void)
|
||||
{
|
||||
return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_get_attr_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] cee - Pointer to the CEE module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
|
||||
{
|
||||
cee->get_attr_status = status;
|
||||
bfa_trc(cee, 0);
|
||||
if (status == BFA_STATUS_OK) {
|
||||
bfa_trc(cee, 0);
|
||||
/*
|
||||
* The requested data has been copied to the DMA area, *process
|
||||
* it.
|
||||
*/
|
||||
memcpy(cee->attr, cee->attr_dma.kva,
|
||||
sizeof(struct bfa_cee_attr_s));
|
||||
bfa_cee_format_cee_cfg(cee->attr);
|
||||
}
|
||||
cee->get_attr_pending = BFA_FALSE;
|
||||
if (cee->cbfn.get_attr_cbfn) {
|
||||
bfa_trc(cee, 0);
|
||||
cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
|
||||
}
|
||||
bfa_trc(cee, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_get_attr_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] cee - Pointer to the CEE module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
|
||||
{
|
||||
cee->get_stats_status = status;
|
||||
bfa_trc(cee, 0);
|
||||
if (status == BFA_STATUS_OK) {
|
||||
bfa_trc(cee, 0);
|
||||
/*
|
||||
* The requested data has been copied to the DMA area, process
|
||||
* it.
|
||||
*/
|
||||
memcpy(cee->stats, cee->stats_dma.kva,
|
||||
sizeof(struct bfa_cee_stats_s));
|
||||
bfa_cee_format_cee_stats(cee->stats);
|
||||
}
|
||||
cee->get_stats_pending = BFA_FALSE;
|
||||
bfa_trc(cee, 0);
|
||||
if (cee->cbfn.get_stats_cbfn) {
|
||||
bfa_trc(cee, 0);
|
||||
cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
|
||||
}
|
||||
bfa_trc(cee, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_get_attr_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] cee - Pointer to the CEE module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
|
||||
{
|
||||
cee->reset_stats_status = status;
|
||||
cee->reset_stats_pending = BFA_FALSE;
|
||||
if (cee->cbfn.reset_stats_cbfn)
|
||||
cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_meminfo()
|
||||
*
|
||||
*
|
||||
* @param[in] void
|
||||
*
|
||||
* @return Size of DMA region
|
||||
*/
|
||||
u32
|
||||
bfa_cee_meminfo(void)
|
||||
{
|
||||
return (bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_mem_claim()
|
||||
*
|
||||
*
|
||||
* @param[in] cee CEE module pointer
|
||||
* dma_kva Kernel Virtual Address of CEE DMA Memory
|
||||
* dma_pa Physical Address of CEE DMA Memory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
|
||||
{
|
||||
cee->attr_dma.kva = dma_kva;
|
||||
cee->attr_dma.pa = dma_pa;
|
||||
cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
|
||||
cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
|
||||
cee->attr = (struct bfa_cee_attr_s *)dma_kva;
|
||||
cee->stats =
|
||||
(struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_get_attr()
|
||||
*
|
||||
* Send the request to the f/w to fetch CEE attributes.
|
||||
*
|
||||
* @param[in] Pointer to the CEE module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
|
||||
bfa_status_t
|
||||
bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
|
||||
bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
|
||||
{
|
||||
struct bfi_cee_get_req_s *cmd;
|
||||
|
||||
bfa_assert((cee != NULL) && (cee->ioc != NULL));
|
||||
bfa_trc(cee, 0);
|
||||
if (!bfa_ioc_is_operational(cee->ioc)) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
if (cee->get_attr_pending == BFA_TRUE) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
cee->get_attr_pending = BFA_TRUE;
|
||||
cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
|
||||
cee->attr = attr;
|
||||
cee->cbfn.get_attr_cbfn = cbfn;
|
||||
cee->cbfn.get_attr_cbarg = cbarg;
|
||||
bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
|
||||
bfa_ioc_portid(cee->ioc));
|
||||
bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
|
||||
bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
|
||||
bfa_trc(cee, 0);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_get_stats()
|
||||
*
|
||||
* Send the request to the f/w to fetch CEE statistics.
|
||||
*
|
||||
* @param[in] Pointer to the CEE module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
|
||||
bfa_status_t
|
||||
bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
|
||||
bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
|
||||
{
|
||||
struct bfi_cee_get_req_s *cmd;
|
||||
|
||||
bfa_assert((cee != NULL) && (cee->ioc != NULL));
|
||||
|
||||
if (!bfa_ioc_is_operational(cee->ioc)) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
if (cee->get_stats_pending == BFA_TRUE) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
cee->get_stats_pending = BFA_TRUE;
|
||||
cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
|
||||
cee->stats = stats;
|
||||
cee->cbfn.get_stats_cbfn = cbfn;
|
||||
cee->cbfn.get_stats_cbarg = cbarg;
|
||||
bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
|
||||
bfa_ioc_portid(cee->ioc));
|
||||
bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
|
||||
bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
|
||||
bfa_trc(cee, 0);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_reset_stats()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the CEE module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
|
||||
bfa_status_t
|
||||
bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
|
||||
void *cbarg)
|
||||
{
|
||||
struct bfi_cee_reset_stats_s *cmd;
|
||||
|
||||
bfa_assert((cee != NULL) && (cee->ioc != NULL));
|
||||
if (!bfa_ioc_is_operational(cee->ioc)) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
if (cee->reset_stats_pending == BFA_TRUE) {
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
cee->reset_stats_pending = BFA_TRUE;
|
||||
cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
|
||||
cee->cbfn.reset_stats_cbfn = cbfn;
|
||||
cee->cbfn.reset_stats_cbarg = cbarg;
|
||||
bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
|
||||
bfa_ioc_portid(cee->ioc));
|
||||
bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
|
||||
bfa_trc(cee, 0);
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_isrs()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the CEE module data structure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
void
|
||||
bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
|
||||
{
|
||||
union bfi_cee_i2h_msg_u *msg;
|
||||
struct bfi_cee_get_rsp_s *get_rsp;
|
||||
struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
|
||||
msg = (union bfi_cee_i2h_msg_u *)m;
|
||||
get_rsp = (struct bfi_cee_get_rsp_s *)m;
|
||||
bfa_trc(cee, msg->mh.msg_id);
|
||||
switch (msg->mh.msg_id) {
|
||||
case BFI_CEE_I2H_GET_CFG_RSP:
|
||||
bfa_trc(cee, get_rsp->cmd_status);
|
||||
bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
|
||||
break;
|
||||
case BFI_CEE_I2H_GET_STATS_RSP:
|
||||
bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
|
||||
break;
|
||||
case BFI_CEE_I2H_RESET_STATS_RSP:
|
||||
bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
|
||||
break;
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_hbfail()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the CEE module data structure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
void
|
||||
bfa_cee_hbfail(void *arg)
|
||||
{
|
||||
struct bfa_cee_s *cee;
|
||||
cee = (struct bfa_cee_s *)arg;
|
||||
|
||||
if (cee->get_attr_pending == BFA_TRUE) {
|
||||
cee->get_attr_status = BFA_STATUS_FAILED;
|
||||
cee->get_attr_pending = BFA_FALSE;
|
||||
if (cee->cbfn.get_attr_cbfn) {
|
||||
cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
|
||||
BFA_STATUS_FAILED);
|
||||
}
|
||||
}
|
||||
if (cee->get_stats_pending == BFA_TRUE) {
|
||||
cee->get_stats_status = BFA_STATUS_FAILED;
|
||||
cee->get_stats_pending = BFA_FALSE;
|
||||
if (cee->cbfn.get_stats_cbfn) {
|
||||
cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
|
||||
BFA_STATUS_FAILED);
|
||||
}
|
||||
}
|
||||
if (cee->reset_stats_pending == BFA_TRUE) {
|
||||
cee->reset_stats_status = BFA_STATUS_FAILED;
|
||||
cee->reset_stats_pending = BFA_FALSE;
|
||||
if (cee->cbfn.reset_stats_cbfn) {
|
||||
cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
|
||||
BFA_STATUS_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_attach()
|
||||
*
|
||||
*
|
||||
* @param[in] cee - Pointer to the CEE module data structure
|
||||
* ioc - Pointer to the ioc module data structure
|
||||
* dev - Pointer to the device driver module data structure
|
||||
* The device driver specific mbox ISR functions have
|
||||
* this pointer as one of the parameters.
|
||||
* trcmod -
|
||||
* logmod -
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
|
||||
struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
|
||||
{
|
||||
bfa_assert(cee != NULL);
|
||||
cee->dev = dev;
|
||||
cee->trcmod = trcmod;
|
||||
cee->logmod = logmod;
|
||||
cee->ioc = ioc;
|
||||
|
||||
bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
|
||||
bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
|
||||
bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
|
||||
bfa_trc(cee, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_cee_detach()
|
||||
*
|
||||
*
|
||||
* @param[in] cee - Pointer to the CEE module data structure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_cee_detach(struct bfa_cee_s *cee)
|
||||
{
|
||||
/*
|
||||
* For now, just check if there is some ioctl pending and mark that as
|
||||
* failed?
|
||||
*/
|
||||
/* bfa_cee_hbfail(cee); */
|
||||
}
|
402
drivers/scsi/bfa/bfa_core.c
Normal file
402
drivers/scsi/bfa/bfa_core.c
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <defs/bfa_defs_pci.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
#include <bfa_iocfc.h>
|
||||
|
||||
#define DEF_CFG_NUM_FABRICS 1
|
||||
#define DEF_CFG_NUM_LPORTS 256
|
||||
#define DEF_CFG_NUM_CQS 4
|
||||
#define DEF_CFG_NUM_IOIM_REQS (BFA_IOIM_MAX)
|
||||
#define DEF_CFG_NUM_TSKIM_REQS 128
|
||||
#define DEF_CFG_NUM_FCXP_REQS 64
|
||||
#define DEF_CFG_NUM_UF_BUFS 64
|
||||
#define DEF_CFG_NUM_RPORTS 1024
|
||||
#define DEF_CFG_NUM_ITNIMS (DEF_CFG_NUM_RPORTS)
|
||||
#define DEF_CFG_NUM_TINS 256
|
||||
|
||||
#define DEF_CFG_NUM_SGPGS 2048
|
||||
#define DEF_CFG_NUM_REQQ_ELEMS 256
|
||||
#define DEF_CFG_NUM_RSPQ_ELEMS 64
|
||||
#define DEF_CFG_NUM_SBOOT_TGTS 16
|
||||
#define DEF_CFG_NUM_SBOOT_LUNS 16
|
||||
|
||||
/**
|
||||
* Use this function query the memory requirement of the BFA library.
|
||||
* This function needs to be called before bfa_attach() to get the
|
||||
* memory required of the BFA layer for a given driver configuration.
|
||||
*
|
||||
* This call will fail, if the cap is out of range compared to pre-defined
|
||||
* values within the BFA library
|
||||
*
|
||||
* @param[in] cfg - pointer to bfa_ioc_cfg_t. Driver layer should indicate
|
||||
* its configuration in this structure.
|
||||
* The default values for struct bfa_iocfc_cfg_s can be
|
||||
* fetched using bfa_cfg_get_default() API.
|
||||
*
|
||||
* If cap's boundary check fails, the library will use
|
||||
* the default bfa_cap_t values (and log a warning msg).
|
||||
*
|
||||
* @param[out] meminfo - pointer to bfa_meminfo_t. This content
|
||||
* indicates the memory type (see bfa_mem_type_t) and
|
||||
* amount of memory required.
|
||||
*
|
||||
* Driver should allocate the memory, populate the
|
||||
* starting address for each block and provide the same
|
||||
* structure as input parameter to bfa_attach() call.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* Special Considerations: @note
|
||||
*/
|
||||
void
|
||||
bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
|
||||
{
|
||||
int i;
|
||||
u32 km_len = 0, dm_len = 0;
|
||||
|
||||
bfa_assert((cfg != NULL) && (meminfo != NULL));
|
||||
|
||||
bfa_os_memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
|
||||
meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
|
||||
BFA_MEM_TYPE_KVA;
|
||||
meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type =
|
||||
BFA_MEM_TYPE_DMA;
|
||||
|
||||
bfa_iocfc_meminfo(cfg, &km_len, &dm_len);
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
|
||||
|
||||
|
||||
meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
|
||||
meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function to do attach the driver instance with the BFA
|
||||
* library. This function will not trigger any HW initialization
|
||||
* process (which will be done in bfa_init() call)
|
||||
*
|
||||
* This call will fail, if the cap is out of range compared to
|
||||
* pre-defined values within the BFA library
|
||||
*
|
||||
* @param[out] bfa Pointer to bfa_t.
|
||||
* @param[in] bfad Opaque handle back to the driver's IOC structure
|
||||
* @param[in] cfg Pointer to bfa_ioc_cfg_t. Should be same structure
|
||||
* that was used in bfa_cfg_get_meminfo().
|
||||
* @param[in] meminfo Pointer to bfa_meminfo_t. The driver should
|
||||
* use the bfa_cfg_get_meminfo() call to
|
||||
* find the memory blocks required, allocate the
|
||||
* required memory and provide the starting addresses.
|
||||
* @param[in] pcidev pointer to struct bfa_pcidev_s
|
||||
*
|
||||
* @return
|
||||
* void
|
||||
*
|
||||
* Special Considerations:
|
||||
*
|
||||
* @note
|
||||
*
|
||||
*/
|
||||
void
|
||||
bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
int i;
|
||||
struct bfa_mem_elem_s *melem;
|
||||
|
||||
bfa->fcs = BFA_FALSE;
|
||||
|
||||
bfa_assert((cfg != NULL) && (meminfo != NULL));
|
||||
|
||||
/**
|
||||
* initialize all memory pointers for iterative allocation
|
||||
*/
|
||||
for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
|
||||
melem = meminfo->meminfo + i;
|
||||
melem->kva_curp = melem->kva;
|
||||
melem->dma_curp = melem->dma;
|
||||
}
|
||||
|
||||
bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function to delete a BFA IOC. IOC should be stopped (by
|
||||
* calling bfa_stop()) before this function call.
|
||||
*
|
||||
* @param[in] bfa - pointer to bfa_t.
|
||||
*
|
||||
* @return
|
||||
* void
|
||||
*
|
||||
* Special Considerations:
|
||||
*
|
||||
* @note
|
||||
*/
|
||||
void
|
||||
bfa_detach(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->detach(bfa);
|
||||
|
||||
bfa_iocfc_detach(bfa);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod)
|
||||
{
|
||||
bfa->trcmod = trcmod;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod)
|
||||
{
|
||||
bfa->logm = logmod;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen)
|
||||
{
|
||||
bfa->aen = aen;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
|
||||
{
|
||||
bfa->plog = plog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize IOC.
|
||||
*
|
||||
* This function will return immediately, when the IOC initialization is
|
||||
* completed, the bfa_cb_init() will be called.
|
||||
*
|
||||
* @param[in] bfa instance
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* Special Considerations:
|
||||
*
|
||||
* @note
|
||||
* When this function returns, the driver should register the interrupt service
|
||||
* routine(s) and enable the device interrupts. If this is not done,
|
||||
* bfa_cb_init() will never get called
|
||||
*/
|
||||
void
|
||||
bfa_init(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_iocfc_init(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function initiate the IOC configuration setup. This function
|
||||
* will return immediately.
|
||||
*
|
||||
* @param[in] bfa instance
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
bfa_start(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_iocfc_start(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function quiese the IOC. This function will return immediately,
|
||||
* when the IOC is actually stopped, the bfa_cb_stop() will be called.
|
||||
*
|
||||
* @param[in] bfa - pointer to bfa_t.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* Special Considerations:
|
||||
* bfa_cb_stop() could be called before or after bfa_stop() returns.
|
||||
*
|
||||
* @note
|
||||
* In case of any failure, we could handle it automatically by doing a
|
||||
* reset and then succeed the bfa_stop() call.
|
||||
*/
|
||||
void
|
||||
bfa_stop(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_iocfc_stop(bfa);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q)
|
||||
{
|
||||
INIT_LIST_HEAD(comp_q);
|
||||
list_splice_tail_init(&bfa->comp_q, comp_q);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
|
||||
{
|
||||
struct list_head *qe;
|
||||
struct list_head *qen;
|
||||
struct bfa_cb_qe_s *hcb_qe;
|
||||
|
||||
list_for_each_safe(qe, qen, comp_q) {
|
||||
hcb_qe = (struct bfa_cb_qe_s *) qe;
|
||||
hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
|
||||
{
|
||||
struct list_head *qe;
|
||||
struct bfa_cb_qe_s *hcb_qe;
|
||||
|
||||
while (!list_empty(comp_q)) {
|
||||
bfa_q_deq(comp_q, &qe);
|
||||
hcb_qe = (struct bfa_cb_qe_s *) qe;
|
||||
hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_attach_fcs(struct bfa_s *bfa)
|
||||
{
|
||||
bfa->fcs = BFA_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic timer heart beat from driver
|
||||
*/
|
||||
void
|
||||
bfa_timer_tick(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_timer_beat(&bfa->timer_mod);
|
||||
}
|
||||
|
||||
#ifndef BFA_BIOS_BUILD
|
||||
/**
|
||||
* Return the list of PCI vendor/device id lists supported by this
|
||||
* BFA instance.
|
||||
*/
|
||||
void
|
||||
bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids)
|
||||
{
|
||||
static struct bfa_pciid_s __pciids[] = {
|
||||
{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G2P},
|
||||
{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G1P},
|
||||
{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT},
|
||||
};
|
||||
|
||||
*npciids = sizeof(__pciids) / sizeof(__pciids[0]);
|
||||
*pciids = __pciids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function query the default struct bfa_iocfc_cfg_s value (compiled
|
||||
* into BFA layer). The OS driver can then turn back and overwrite entries that
|
||||
* have been configured by the user.
|
||||
*
|
||||
* @param[in] cfg - pointer to bfa_ioc_cfg_t
|
||||
*
|
||||
* @return
|
||||
* void
|
||||
*
|
||||
* Special Considerations:
|
||||
* note
|
||||
*/
|
||||
void
|
||||
bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
|
||||
{
|
||||
cfg->fwcfg.num_fabrics = DEF_CFG_NUM_FABRICS;
|
||||
cfg->fwcfg.num_lports = DEF_CFG_NUM_LPORTS;
|
||||
cfg->fwcfg.num_rports = DEF_CFG_NUM_RPORTS;
|
||||
cfg->fwcfg.num_ioim_reqs = DEF_CFG_NUM_IOIM_REQS;
|
||||
cfg->fwcfg.num_tskim_reqs = DEF_CFG_NUM_TSKIM_REQS;
|
||||
cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;
|
||||
cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;
|
||||
cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS;
|
||||
|
||||
cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;
|
||||
cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS;
|
||||
cfg->drvcfg.num_sgpgs = DEF_CFG_NUM_SGPGS;
|
||||
cfg->drvcfg.num_sboot_tgts = DEF_CFG_NUM_SBOOT_TGTS;
|
||||
cfg->drvcfg.num_sboot_luns = DEF_CFG_NUM_SBOOT_LUNS;
|
||||
cfg->drvcfg.path_tov = BFA_FCPIM_PATHTOV_DEF;
|
||||
cfg->drvcfg.ioc_recover = BFA_FALSE;
|
||||
cfg->drvcfg.delay_comp = BFA_FALSE;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
|
||||
{
|
||||
bfa_cfg_get_default(cfg);
|
||||
cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
|
||||
cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN;
|
||||
cfg->fwcfg.num_fcxp_reqs = BFA_FCXP_MIN;
|
||||
cfg->fwcfg.num_uf_bufs = BFA_UF_MIN;
|
||||
cfg->fwcfg.num_rports = BFA_RPORT_MIN;
|
||||
|
||||
cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
|
||||
cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
|
||||
cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
|
||||
cfg->drvcfg.min_cfg = BFA_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr)
|
||||
{
|
||||
bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve firmware trace information on IOC failure.
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen)
|
||||
{
|
||||
return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch firmware trace data.
|
||||
*
|
||||
* @param[in] bfa BFA instance
|
||||
* @param[out] trcdata Firmware trace buffer
|
||||
* @param[in,out] trclen Firmware trace buffer len
|
||||
*
|
||||
* @retval BFA_STATUS_OK Firmware trace is fetched.
|
||||
* @retval BFA_STATUS_INPROGRESS Firmware trace fetch is in progress.
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen)
|
||||
{
|
||||
return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen);
|
||||
}
|
||||
#endif
|
58
drivers/scsi/bfa/bfa_csdebug.c
Normal file
58
drivers/scsi/bfa/bfa_csdebug.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <cs/bfa_debug.h>
|
||||
#include <bfa_os_inc.h>
|
||||
#include <cs/bfa_q.h>
|
||||
#include <log/bfa_log_hal.h>
|
||||
|
||||
/**
|
||||
* cs_debug_api
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
bfa_panic(int line, char *file, char *panicstr)
|
||||
{
|
||||
bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
|
||||
bfa_os_panic();
|
||||
}
|
||||
|
||||
void
|
||||
bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
|
||||
{
|
||||
bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
|
||||
bfa_os_panic();
|
||||
}
|
||||
|
||||
int
|
||||
bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
|
||||
{
|
||||
struct list_head *tqe;
|
||||
|
||||
tqe = bfa_q_next(q);
|
||||
while (tqe != q) {
|
||||
if (tqe == qe)
|
||||
return (1);
|
||||
tqe = bfa_q_next(tqe);
|
||||
if (tqe == NULL)
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
175
drivers/scsi/bfa/bfa_fcpim.c
Normal file
175
drivers/scsi/bfa/bfa_fcpim.c
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <log/bfa_log_hal.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, FCPIM);
|
||||
BFA_MODULE(fcpim);
|
||||
|
||||
/**
|
||||
* hal_fcpim_mod BFA FCP Initiator Mode module
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compute and return memory needed by FCP(im) module.
|
||||
*/
|
||||
static void
|
||||
bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len)
|
||||
{
|
||||
bfa_itnim_meminfo(cfg, km_len, dm_len);
|
||||
|
||||
/**
|
||||
* IO memory
|
||||
*/
|
||||
if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
|
||||
cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
|
||||
else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
|
||||
cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
|
||||
|
||||
*km_len += cfg->fwcfg.num_ioim_reqs *
|
||||
(sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
|
||||
|
||||
*dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN;
|
||||
|
||||
/**
|
||||
* task management command memory
|
||||
*/
|
||||
if (cfg->fwcfg.num_tskim_reqs < BFA_TSKIM_MIN)
|
||||
cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN;
|
||||
*km_len += cfg->fwcfg.num_tskim_reqs * sizeof(struct bfa_tskim_s);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
bfa_trc(bfa, cfg->drvcfg.path_tov);
|
||||
bfa_trc(bfa, cfg->fwcfg.num_rports);
|
||||
bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
|
||||
bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
|
||||
|
||||
fcpim->bfa = bfa;
|
||||
fcpim->num_itnims = cfg->fwcfg.num_rports;
|
||||
fcpim->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
|
||||
fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
|
||||
fcpim->path_tov = cfg->drvcfg.path_tov;
|
||||
fcpim->delay_comp = cfg->drvcfg.delay_comp;
|
||||
|
||||
bfa_itnim_attach(fcpim, meminfo);
|
||||
bfa_tskim_attach(fcpim, meminfo);
|
||||
bfa_ioim_attach(fcpim, meminfo);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcpim_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcpim_detach(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
bfa_ioim_detach(fcpim);
|
||||
bfa_tskim_detach(fcpim);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcpim_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcpim_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcpim_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
struct bfa_itnim_s *itnim;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &fcpim->itnim_q) {
|
||||
itnim = (struct bfa_itnim_s *) qe;
|
||||
bfa_itnim_iocdisable(itnim);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
fcpim->path_tov = path_tov * 1000;
|
||||
if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
|
||||
fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX;
|
||||
}
|
||||
|
||||
u16
|
||||
bfa_fcpim_path_tov_get(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
return (fcpim->path_tov / 1000);
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
*modstats = fcpim->stats;
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_fcpim_clr_modstats(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s));
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX);
|
||||
|
||||
fcpim->q_depth = q_depth;
|
||||
}
|
||||
|
||||
u16
|
||||
bfa_fcpim_qdepth_get(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
|
||||
return (fcpim->q_depth);
|
||||
}
|
||||
|
||||
|
188
drivers/scsi/bfa/bfa_fcpim_priv.h
Normal file
188
drivers/scsi/bfa/bfa_fcpim_priv.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_FCPIM_PRIV_H__
|
||||
#define __BFA_FCPIM_PRIV_H__
|
||||
|
||||
#include <bfa_fcpim.h>
|
||||
#include <defs/bfa_defs_fcpim.h>
|
||||
#include <cs/bfa_wc.h>
|
||||
#include "bfa_sgpg_priv.h"
|
||||
|
||||
#define BFA_ITNIM_MIN 32
|
||||
#define BFA_ITNIM_MAX 1024
|
||||
|
||||
#define BFA_IOIM_MIN 8
|
||||
#define BFA_IOIM_MAX 2000
|
||||
|
||||
#define BFA_TSKIM_MIN 4
|
||||
#define BFA_TSKIM_MAX 512
|
||||
#define BFA_FCPIM_PATHTOV_DEF (30 * 1000) /* in millisecs */
|
||||
#define BFA_FCPIM_PATHTOV_MAX (90 * 1000) /* in millisecs */
|
||||
|
||||
#define bfa_fcpim_stats(__fcpim, __stats) \
|
||||
(__fcpim)->stats.__stats ++
|
||||
|
||||
struct bfa_fcpim_mod_s {
|
||||
struct bfa_s *bfa;
|
||||
struct bfa_itnim_s *itnim_arr;
|
||||
struct bfa_ioim_s *ioim_arr;
|
||||
struct bfa_ioim_sp_s *ioim_sp_arr;
|
||||
struct bfa_tskim_s *tskim_arr;
|
||||
struct bfa_dma_s snsbase;
|
||||
int num_itnims;
|
||||
int num_ioim_reqs;
|
||||
int num_tskim_reqs;
|
||||
u32 path_tov;
|
||||
u16 q_depth;
|
||||
u16 rsvd;
|
||||
struct list_head itnim_q; /* queue of active itnim */
|
||||
struct list_head ioim_free_q; /* free IO resources */
|
||||
struct list_head ioim_resfree_q; /* IOs waiting for f/w */
|
||||
struct list_head ioim_comp_q; /* IO global comp Q */
|
||||
struct list_head tskim_free_q;
|
||||
u32 ios_active; /* current active IOs */
|
||||
u32 delay_comp;
|
||||
struct bfa_fcpim_stats_s stats;
|
||||
};
|
||||
|
||||
struct bfa_ioim_s;
|
||||
struct bfa_tskim_s;
|
||||
|
||||
/**
|
||||
* BFA IO (initiator mode)
|
||||
*/
|
||||
struct bfa_ioim_s {
|
||||
struct list_head qe; /* queue elememt */
|
||||
bfa_sm_t sm; /* BFA ioim state machine */
|
||||
struct bfa_s *bfa; /* BFA module */
|
||||
struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
|
||||
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
|
||||
struct bfad_ioim_s *dio; /* driver IO handle */
|
||||
u16 iotag; /* FWI IO tag */
|
||||
u16 abort_tag; /* unqiue abort request tag */
|
||||
u16 nsges; /* number of SG elements */
|
||||
u16 nsgpgs; /* number of SG pages */
|
||||
struct bfa_sgpg_s *sgpg; /* first SG page */
|
||||
struct list_head sgpg_q; /* allocated SG pages */
|
||||
struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
|
||||
bfa_cb_cbfn_t io_cbfn; /* IO completion handler */
|
||||
struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */
|
||||
};
|
||||
|
||||
struct bfa_ioim_sp_s {
|
||||
struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */
|
||||
u8 *snsinfo; /* sense info for this IO */
|
||||
struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
|
||||
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
|
||||
bfa_boolean_t abort_explicit; /* aborted by OS */
|
||||
struct bfa_tskim_s *tskim; /* Relevant TM cmd */
|
||||
};
|
||||
|
||||
/**
|
||||
* BFA Task management command (initiator mode)
|
||||
*/
|
||||
struct bfa_tskim_s {
|
||||
struct list_head qe;
|
||||
bfa_sm_t sm;
|
||||
struct bfa_s *bfa; /* BFA module */
|
||||
struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
|
||||
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
|
||||
struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
|
||||
bfa_boolean_t notify; /* notify itnim on TM comp */
|
||||
lun_t lun; /* lun if applicable */
|
||||
enum fcp_tm_cmnd tm_cmnd; /* task management command */
|
||||
u16 tsk_tag; /* FWI IO tag */
|
||||
u8 tsecs; /* timeout in seconds */
|
||||
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
|
||||
struct list_head io_q; /* queue of affected IOs */
|
||||
struct bfa_wc_s wc; /* waiting counter */
|
||||
struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
|
||||
enum bfi_tskim_status tsk_status; /* TM status */
|
||||
};
|
||||
|
||||
/**
|
||||
* BFA i-t-n (initiator mode)
|
||||
*/
|
||||
struct bfa_itnim_s {
|
||||
struct list_head qe; /* queue element */
|
||||
bfa_sm_t sm; /* i-t-n im BFA state machine */
|
||||
struct bfa_s *bfa; /* bfa instance */
|
||||
struct bfa_rport_s *rport; /* bfa rport */
|
||||
void *ditn; /* driver i-t-n structure */
|
||||
struct bfi_mhdr_s mhdr; /* pre-built mhdr */
|
||||
u8 msg_no; /* itnim/rport firmware handle */
|
||||
u8 reqq; /* CQ for requests */
|
||||
struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
|
||||
struct list_head pending_q; /* queue of pending IO requests*/
|
||||
struct list_head io_q; /* queue of active IO requests */
|
||||
struct list_head io_cleanup_q; /* IO being cleaned up */
|
||||
struct list_head tsk_q; /* queue of active TM commands */
|
||||
struct list_head delay_comp_q;/* queue of failed inflight cmds */
|
||||
bfa_boolean_t seq_rec; /* SQER supported */
|
||||
bfa_boolean_t is_online; /* itnim is ONLINE for IO */
|
||||
bfa_boolean_t iotov_active; /* IO TOV timer is active */
|
||||
struct bfa_wc_s wc; /* waiting counter */
|
||||
struct bfa_timer_s timer; /* pending IO TOV */
|
||||
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
|
||||
struct bfa_fcpim_mod_s *fcpim; /* fcpim module */
|
||||
struct bfa_itnim_hal_stats_s stats;
|
||||
};
|
||||
|
||||
#define bfa_itnim_is_online(_itnim) (_itnim)->is_online
|
||||
#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
|
||||
#define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \
|
||||
(&fcpim->ioim_arr[_iotag])
|
||||
#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \
|
||||
(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
|
||||
|
||||
/*
|
||||
* function prototypes
|
||||
*/
|
||||
void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
|
||||
struct bfa_meminfo_s *minfo);
|
||||
void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
|
||||
void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
void bfa_ioim_good_comp_isr(struct bfa_s *bfa,
|
||||
struct bfi_msg_s *msg);
|
||||
void bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
|
||||
void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
|
||||
struct bfa_tskim_s *tskim);
|
||||
void bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
|
||||
void bfa_ioim_tov(struct bfa_ioim_s *ioim);
|
||||
|
||||
void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
|
||||
struct bfa_meminfo_s *minfo);
|
||||
void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
|
||||
void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
void bfa_tskim_iodone(struct bfa_tskim_s *tskim);
|
||||
void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
|
||||
void bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
|
||||
|
||||
void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len);
|
||||
void bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
|
||||
struct bfa_meminfo_s *minfo);
|
||||
void bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
|
||||
void bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
|
||||
void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
void bfa_itnim_iodone(struct bfa_itnim_s *itnim);
|
||||
void bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
|
||||
bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
|
||||
|
||||
#endif /* __BFA_FCPIM_PRIV_H__ */
|
||||
|
1671
drivers/scsi/bfa/bfa_fcport.c
Normal file
1671
drivers/scsi/bfa/bfa_fcport.c
Normal file
File diff suppressed because it is too large
Load Diff
182
drivers/scsi/bfa/bfa_fcs.c
Normal file
182
drivers/scsi/bfa/bfa_fcs.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_fcs.c BFA FCS main
|
||||
*/
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include "fcs_port.h"
|
||||
#include "fcs_uf.h"
|
||||
#include "fcs_vport.h"
|
||||
#include "fcs_rport.h"
|
||||
#include "fcs_fabric.h"
|
||||
#include "fcs_fcpim.h"
|
||||
#include "fcs_fcptm.h"
|
||||
#include "fcbuild.h"
|
||||
#include "fcs.h"
|
||||
#include "bfad_drv.h"
|
||||
#include <fcb/bfa_fcb.h>
|
||||
|
||||
/**
|
||||
* FCS sub-modules
|
||||
*/
|
||||
struct bfa_fcs_mod_s {
|
||||
void (*modinit) (struct bfa_fcs_s *fcs);
|
||||
void (*modexit) (struct bfa_fcs_s *fcs);
|
||||
};
|
||||
|
||||
#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
|
||||
|
||||
static struct bfa_fcs_mod_s fcs_modules[] = {
|
||||
BFA_FCS_MODULE(bfa_fcs_pport),
|
||||
BFA_FCS_MODULE(bfa_fcs_uf),
|
||||
BFA_FCS_MODULE(bfa_fcs_fabric),
|
||||
BFA_FCS_MODULE(bfa_fcs_vport),
|
||||
BFA_FCS_MODULE(bfa_fcs_rport),
|
||||
BFA_FCS_MODULE(bfa_fcs_fcpim),
|
||||
};
|
||||
|
||||
/**
|
||||
* fcs_api BFA FCS API
|
||||
*/
|
||||
|
||||
static void
|
||||
bfa_fcs_exit_comp(void *fcs_cbarg)
|
||||
{
|
||||
struct bfa_fcs_s *fcs = fcs_cbarg;
|
||||
struct bfad_s *bfad = fcs->bfad;
|
||||
|
||||
complete(&bfad->comp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fcs_api BFA FCS API
|
||||
*/
|
||||
|
||||
/**
|
||||
* FCS instance initialization.
|
||||
*
|
||||
* param[in] fcs FCS instance
|
||||
* param[in] bfa BFA instance
|
||||
* param[in] bfad BFA driver instance
|
||||
*
|
||||
* return None
|
||||
*/
|
||||
void
|
||||
bfa_fcs_init(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
|
||||
bfa_boolean_t min_cfg)
|
||||
{
|
||||
int i;
|
||||
struct bfa_fcs_mod_s *mod;
|
||||
|
||||
fcs->bfa = bfa;
|
||||
fcs->bfad = bfad;
|
||||
fcs->min_cfg = min_cfg;
|
||||
|
||||
bfa_attach_fcs(bfa);
|
||||
fcbuild_init();
|
||||
|
||||
for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
|
||||
mod = &fcs_modules[i];
|
||||
mod->modinit(fcs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start FCS operations.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_start(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_fcs_fabric_modstart(fcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* FCS driver details initialization.
|
||||
*
|
||||
* param[in] fcs FCS instance
|
||||
* param[in] driver_info Driver Details
|
||||
*
|
||||
* return None
|
||||
*/
|
||||
void
|
||||
bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
|
||||
struct bfa_fcs_driver_info_s *driver_info)
|
||||
{
|
||||
|
||||
fcs->driver_info = *driver_info;
|
||||
|
||||
bfa_fcs_fabric_psymb_init(&fcs->fabric);
|
||||
}
|
||||
|
||||
/**
|
||||
* FCS instance cleanup and exit.
|
||||
*
|
||||
* param[in] fcs FCS instance
|
||||
* return None
|
||||
*/
|
||||
void
|
||||
bfa_fcs_exit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
struct bfa_fcs_mod_s *mod;
|
||||
int nmods, i;
|
||||
|
||||
bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
|
||||
|
||||
nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
|
||||
|
||||
for (i = 0; i < nmods; i++) {
|
||||
bfa_wc_up(&fcs->wc);
|
||||
|
||||
mod = &fcs_modules[i];
|
||||
mod->modexit(fcs);
|
||||
}
|
||||
|
||||
bfa_wc_wait(&fcs->wc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod)
|
||||
{
|
||||
fcs->trcmod = trcmod;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod)
|
||||
{
|
||||
fcs->logm = logmod;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen)
|
||||
{
|
||||
fcs->aen = aen;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_wc_down(&fcs->wc);
|
||||
}
|
||||
|
||||
|
940
drivers/scsi/bfa/bfa_fcs_lport.c
Normal file
940
drivers/scsi/bfa/bfa_fcs_lport.c
Normal file
@ -0,0 +1,940 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_fcs_port.c BFA FCS port
|
||||
*/
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
#include <fcb/bfa_fcb_port.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <log/bfa_log_fcs.h>
|
||||
#include "fcs.h"
|
||||
#include "fcs_lport.h"
|
||||
#include "fcs_vport.h"
|
||||
#include "fcs_rport.h"
|
||||
#include "fcs_fcxp.h"
|
||||
#include "fcs_trcmod.h"
|
||||
#include "lport_priv.h"
|
||||
#include <aen/bfa_aen_lport.h>
|
||||
|
||||
BFA_TRC_FILE(FCS, PORT);
|
||||
|
||||
/**
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
|
||||
enum bfa_lport_aen_event event);
|
||||
static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
|
||||
struct fchs_s *rx_fchs, u8 reason_code,
|
||||
u8 reason_code_expl);
|
||||
static void bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
|
||||
struct fchs_s *rx_fchs,
|
||||
struct fc_logi_s *plogi);
|
||||
static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
|
||||
static void bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
|
||||
struct fchs_s *rx_fchs,
|
||||
struct fc_echo_s *echo, u16 len);
|
||||
static void bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
|
||||
struct fchs_s *rx_fchs,
|
||||
struct fc_rnid_cmd_s *rnid, u16 len);
|
||||
static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
|
||||
struct fc_rnid_general_topology_data_s *gen_topo_data);
|
||||
|
||||
static struct {
|
||||
void (*init) (struct bfa_fcs_port_s *port);
|
||||
void (*online) (struct bfa_fcs_port_s *port);
|
||||
void (*offline) (struct bfa_fcs_port_s *port);
|
||||
} __port_action[] = {
|
||||
{
|
||||
bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
|
||||
bfa_fcs_port_unknown_offline}, {
|
||||
bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
|
||||
bfa_fcs_port_fab_offline}, {
|
||||
bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
|
||||
bfa_fcs_port_loop_offline}, {
|
||||
bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
|
||||
bfa_fcs_port_n2n_offline},};
|
||||
|
||||
/**
|
||||
* fcs_port_sm FCS logical port state machine
|
||||
*/
|
||||
|
||||
enum bfa_fcs_port_event {
|
||||
BFA_FCS_PORT_SM_CREATE = 1,
|
||||
BFA_FCS_PORT_SM_ONLINE = 2,
|
||||
BFA_FCS_PORT_SM_OFFLINE = 3,
|
||||
BFA_FCS_PORT_SM_DELETE = 4,
|
||||
BFA_FCS_PORT_SM_DELRPORT = 5,
|
||||
};
|
||||
|
||||
static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event);
|
||||
static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event);
|
||||
static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event);
|
||||
static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event);
|
||||
static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event);
|
||||
|
||||
static void
|
||||
bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event)
|
||||
{
|
||||
bfa_trc(port->fcs, port->port_cfg.pwwn);
|
||||
bfa_trc(port->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_PORT_SM_CREATE:
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_init);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
|
||||
{
|
||||
bfa_trc(port->fcs, port->port_cfg.pwwn);
|
||||
bfa_trc(port->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_PORT_SM_ONLINE:
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_online);
|
||||
bfa_fcs_port_online_actions(port);
|
||||
break;
|
||||
|
||||
case BFA_FCS_PORT_SM_DELETE:
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
|
||||
bfa_fcs_port_deleted(port);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
bfa_trc(port->fcs, port->port_cfg.pwwn);
|
||||
bfa_trc(port->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_PORT_SM_OFFLINE:
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
|
||||
bfa_fcs_port_offline_actions(port);
|
||||
break;
|
||||
|
||||
case BFA_FCS_PORT_SM_DELETE:
|
||||
|
||||
__port_action[port->fabric->fab_type].offline(port);
|
||||
|
||||
if (port->num_rports == 0) {
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
|
||||
bfa_fcs_port_deleted(port);
|
||||
} else {
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
|
||||
list_for_each_safe(qe, qen, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
bfa_fcs_rport_delete(rport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_FCS_PORT_SM_DELRPORT:
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
bfa_trc(port->fcs, port->port_cfg.pwwn);
|
||||
bfa_trc(port->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_PORT_SM_ONLINE:
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_online);
|
||||
bfa_fcs_port_online_actions(port);
|
||||
break;
|
||||
|
||||
case BFA_FCS_PORT_SM_DELETE:
|
||||
if (port->num_rports == 0) {
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
|
||||
bfa_fcs_port_deleted(port);
|
||||
} else {
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
|
||||
list_for_each_safe(qe, qen, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
bfa_fcs_rport_delete(rport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_FCS_PORT_SM_DELRPORT:
|
||||
case BFA_FCS_PORT_SM_OFFLINE:
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
|
||||
enum bfa_fcs_port_event event)
|
||||
{
|
||||
bfa_trc(port->fcs, port->port_cfg.pwwn);
|
||||
bfa_trc(port->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_PORT_SM_DELRPORT:
|
||||
if (port->num_rports == 0) {
|
||||
bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
|
||||
bfa_fcs_port_deleted(port);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fcs_port_pvt
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send AEN notification
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
|
||||
enum bfa_lport_aen_event event)
|
||||
{
|
||||
union bfa_aen_data_u aen_data;
|
||||
struct bfa_log_mod_s *logmod = port->fcs->logm;
|
||||
enum bfa_port_role role = port->port_cfg.roles;
|
||||
wwn_t lpwwn = bfa_fcs_port_get_pwwn(port);
|
||||
char lpwwn_ptr[BFA_STRING_32];
|
||||
char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
|
||||
{ "Initiator", "Target", "IPFC" };
|
||||
|
||||
wwn2str(lpwwn_ptr, lpwwn);
|
||||
|
||||
bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPORT_AEN_ONLINE:
|
||||
bfa_log(logmod, BFA_AEN_LPORT_ONLINE, lpwwn_ptr,
|
||||
role_str[role / 2]);
|
||||
break;
|
||||
case BFA_LPORT_AEN_OFFLINE:
|
||||
bfa_log(logmod, BFA_AEN_LPORT_OFFLINE, lpwwn_ptr,
|
||||
role_str[role / 2]);
|
||||
break;
|
||||
case BFA_LPORT_AEN_NEW:
|
||||
bfa_log(logmod, BFA_AEN_LPORT_NEW, lpwwn_ptr,
|
||||
role_str[role / 2]);
|
||||
break;
|
||||
case BFA_LPORT_AEN_DELETE:
|
||||
bfa_log(logmod, BFA_AEN_LPORT_DELETE, lpwwn_ptr,
|
||||
role_str[role / 2]);
|
||||
break;
|
||||
case BFA_LPORT_AEN_DISCONNECT:
|
||||
bfa_log(logmod, BFA_AEN_LPORT_DISCONNECT, lpwwn_ptr,
|
||||
role_str[role / 2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
aen_data.lport.vf_id = port->fabric->vf_id;
|
||||
aen_data.lport.roles = role;
|
||||
aen_data.lport.ppwwn =
|
||||
bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
|
||||
aen_data.lport.lpwwn = lpwwn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a LS reject
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
|
||||
u8 reason_code, u8 reason_code_expl)
|
||||
{
|
||||
struct fchs_s fchs;
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
struct bfa_rport_s *bfa_rport = NULL;
|
||||
int len;
|
||||
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
|
||||
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
|
||||
if (!fcxp)
|
||||
return;
|
||||
|
||||
len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
|
||||
bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
|
||||
reason_code, reason_code_expl);
|
||||
|
||||
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
|
||||
BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
|
||||
FC_MAX_PDUSZ, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process incoming plogi from a remote port.
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
|
||||
struct fc_logi_s *plogi)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
|
||||
bfa_trc(port->fcs, rx_fchs->d_id);
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
|
||||
/*
|
||||
* If min cfg mode is enabled, drop any incoming PLOGIs
|
||||
*/
|
||||
if (__fcs_min_cfg(port->fcs)) {
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
/*
|
||||
* send a LS reject
|
||||
*/
|
||||
bfa_fcs_port_send_ls_rjt(port, rx_fchs,
|
||||
FC_LS_RJT_RSN_PROTOCOL_ERROR,
|
||||
FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct Attach P2P mode : verify address assigned by the r-port.
|
||||
*/
|
||||
if ((!bfa_fcs_fabric_is_switched(port->fabric))
|
||||
&&
|
||||
(memcmp
|
||||
((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
|
||||
sizeof(wwn_t)) < 0)) {
|
||||
if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
|
||||
/*
|
||||
* Address assigned to us cannot be a WKA
|
||||
*/
|
||||
bfa_fcs_port_send_ls_rjt(port, rx_fchs,
|
||||
FC_LS_RJT_RSN_PROTOCOL_ERROR,
|
||||
FC_LS_RJT_EXP_INVALID_NPORT_ID);
|
||||
return;
|
||||
}
|
||||
port->pid = rx_fchs->d_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* First, check if we know the device by pwwn.
|
||||
*/
|
||||
rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
|
||||
if (rport) {
|
||||
/**
|
||||
* Direct Attach P2P mode: handle address assigned by the rport.
|
||||
*/
|
||||
if ((!bfa_fcs_fabric_is_switched(port->fabric))
|
||||
&&
|
||||
(memcmp
|
||||
((void *)&bfa_fcs_port_get_pwwn(port),
|
||||
(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
|
||||
port->pid = rx_fchs->d_id;
|
||||
rport->pid = rx_fchs->s_id;
|
||||
}
|
||||
bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Next, lookup rport by PID.
|
||||
*/
|
||||
rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
|
||||
if (!rport) {
|
||||
/**
|
||||
* Inbound PLOGI from a new device.
|
||||
*/
|
||||
bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rport is known only by PID.
|
||||
*/
|
||||
if (rport->pwwn) {
|
||||
/**
|
||||
* This is a different device with the same pid. Old device
|
||||
* disappeared. Send implicit LOGO to old device.
|
||||
*/
|
||||
bfa_assert(rport->pwwn != plogi->port_name);
|
||||
bfa_fcs_rport_logo_imp(rport);
|
||||
|
||||
/**
|
||||
* Inbound PLOGI from a new device (with old PID).
|
||||
*/
|
||||
bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* PLOGI crossing each other.
|
||||
*/
|
||||
bfa_assert(rport->pwwn == WWN_NULL);
|
||||
bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process incoming ECHO.
|
||||
* Since it does not require a login, it is processed here.
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
|
||||
struct fc_echo_s *echo, u16 rx_len)
|
||||
{
|
||||
struct fchs_s fchs;
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
struct bfa_rport_s *bfa_rport = NULL;
|
||||
int len, pyld_len;
|
||||
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
bfa_trc(port->fcs, rx_fchs->d_id);
|
||||
bfa_trc(port->fcs, rx_len);
|
||||
|
||||
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
|
||||
if (!fcxp)
|
||||
return;
|
||||
|
||||
len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
|
||||
bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
|
||||
|
||||
/*
|
||||
* Copy the payload (if any) from the echo frame
|
||||
*/
|
||||
pyld_len = rx_len - sizeof(struct fchs_s);
|
||||
bfa_trc(port->fcs, pyld_len);
|
||||
|
||||
if (pyld_len > len)
|
||||
memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
|
||||
sizeof(struct fc_echo_s), (echo + 1),
|
||||
(pyld_len - sizeof(struct fc_echo_s)));
|
||||
|
||||
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
|
||||
BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
|
||||
FC_MAX_PDUSZ, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process incoming RNID.
|
||||
* Since it does not require a login, it is processed here.
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
|
||||
struct fc_rnid_cmd_s *rnid, u16 rx_len)
|
||||
{
|
||||
struct fc_rnid_common_id_data_s common_id_data;
|
||||
struct fc_rnid_general_topology_data_s gen_topo_data;
|
||||
struct fchs_s fchs;
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
struct bfa_rport_s *bfa_rport = NULL;
|
||||
u16 len;
|
||||
u32 data_format;
|
||||
|
||||
bfa_trc(port->fcs, rx_fchs->s_id);
|
||||
bfa_trc(port->fcs, rx_fchs->d_id);
|
||||
bfa_trc(port->fcs, rx_len);
|
||||
|
||||
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
|
||||
if (!fcxp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check Node Indentification Data Format
|
||||
* We only support General Topology Discovery Format.
|
||||
* For any other requested Data Formats, we return Common Node Id Data
|
||||
* only, as per FC-LS.
|
||||
*/
|
||||
bfa_trc(port->fcs, rnid->node_id_data_format);
|
||||
if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
|
||||
data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
|
||||
/*
|
||||
* Get General topology data for this port
|
||||
*/
|
||||
bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
|
||||
} else {
|
||||
data_format = RNID_NODEID_DATA_FORMAT_COMMON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the Node Id Info
|
||||
*/
|
||||
common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
|
||||
common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
|
||||
|
||||
len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
|
||||
bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
|
||||
data_format, &common_id_data, &gen_topo_data);
|
||||
|
||||
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
|
||||
BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
|
||||
FC_MAX_PDUSZ, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill out General Topolpgy Discovery Data for RNID ELS.
|
||||
*/
|
||||
static void
|
||||
bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
|
||||
struct fc_rnid_general_topology_data_s *gen_topo_data)
|
||||
{
|
||||
|
||||
bfa_os_memset(gen_topo_data, 0,
|
||||
sizeof(struct fc_rnid_general_topology_data_s));
|
||||
|
||||
gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST);
|
||||
gen_topo_data->phy_port_num = 0; /* @todo */
|
||||
gen_topo_data->num_attached_nodes = bfa_os_htonl(1);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_trc(port->fcs, port->fabric->oper_type);
|
||||
|
||||
__port_action[port->fabric->fab_type].init(port);
|
||||
__port_action[port->fabric->fab_type].online(port);
|
||||
|
||||
bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
|
||||
bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
|
||||
port->fabric->vf_drv, (port->vport == NULL) ?
|
||||
NULL : port->vport->vport_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
struct list_head *qe, *qen;
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
|
||||
bfa_trc(port->fcs, port->fabric->oper_type);
|
||||
|
||||
__port_action[port->fabric->fab_type].offline(port);
|
||||
|
||||
if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) {
|
||||
bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
|
||||
} else {
|
||||
bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
|
||||
}
|
||||
bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
|
||||
port->fabric->vf_drv,
|
||||
(port->vport == NULL) ? NULL : port->vport->vport_drv);
|
||||
|
||||
list_for_each_safe(qe, qen, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
bfa_fcs_rport_offline(rport);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
|
||||
|
||||
/*
|
||||
* Base port will be deleted by the OS driver
|
||||
*/
|
||||
if (port->vport) {
|
||||
bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
|
||||
port->fabric->vf_drv,
|
||||
port->vport ? port->vport->vport_drv : NULL);
|
||||
bfa_fcs_vport_delete_comp(port->vport);
|
||||
} else {
|
||||
bfa_fcs_fabric_port_delete_comp(port->fabric);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fcs_lport_api BFA FCS port API
|
||||
*/
|
||||
/**
|
||||
* Module initialization
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Module cleanup
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_fcs_modexit_comp(fcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsolicited frame receive handling.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
|
||||
u16 len)
|
||||
{
|
||||
u32 pid = fchs->s_id;
|
||||
struct bfa_fcs_rport_s *rport = NULL;
|
||||
struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
|
||||
|
||||
bfa_stats(lport, uf_recvs);
|
||||
|
||||
if (!bfa_fcs_port_is_online(lport)) {
|
||||
bfa_stats(lport, uf_recv_drops);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* First, handle ELSs that donot require a login.
|
||||
*/
|
||||
/*
|
||||
* Handle PLOGI first
|
||||
*/
|
||||
if ((fchs->type == FC_TYPE_ELS) &&
|
||||
(els_cmd->els_code == FC_ELS_PLOGI)) {
|
||||
bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle ECHO separately.
|
||||
*/
|
||||
if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
|
||||
bfa_fcs_port_echo(lport, fchs,
|
||||
(struct fc_echo_s *) els_cmd, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle RNID separately.
|
||||
*/
|
||||
if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
|
||||
bfa_fcs_port_rnid(lport, fchs,
|
||||
(struct fc_rnid_cmd_s *) els_cmd, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* look for a matching remote port ID
|
||||
*/
|
||||
rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
|
||||
if (rport) {
|
||||
bfa_trc(rport->fcs, fchs->s_id);
|
||||
bfa_trc(rport->fcs, fchs->d_id);
|
||||
bfa_trc(rport->fcs, fchs->type);
|
||||
|
||||
bfa_fcs_rport_uf_recv(rport, fchs, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only handles ELS frames for now.
|
||||
*/
|
||||
if (fchs->type != FC_TYPE_ELS) {
|
||||
bfa_trc(lport->fcs, fchs->type);
|
||||
bfa_assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_trc(lport->fcs, els_cmd->els_code);
|
||||
if (els_cmd->els_code == FC_ELS_RSCN) {
|
||||
bfa_fcs_port_scn_process_rscn(lport, fchs, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (els_cmd->els_code == FC_ELS_LOGO) {
|
||||
/**
|
||||
* @todo Handle LOGO frames received.
|
||||
*/
|
||||
bfa_trc(lport->fcs, els_cmd->els_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (els_cmd->els_code == FC_ELS_PRLI) {
|
||||
/**
|
||||
* @todo Handle PRLI frames received.
|
||||
*/
|
||||
bfa_trc(lport->fcs, els_cmd->els_code);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unhandled ELS frames. Send a LS_RJT.
|
||||
*/
|
||||
bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
|
||||
FC_LS_RJT_EXP_NO_ADDL_INFO);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* PID based Lookup for a R-Port in the Port R-Port Queue
|
||||
*/
|
||||
struct bfa_fcs_rport_s *
|
||||
bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
struct list_head *qe;
|
||||
|
||||
list_for_each(qe, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
if (rport->pid == pid)
|
||||
return rport;
|
||||
}
|
||||
|
||||
bfa_trc(port->fcs, pid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* PWWN based Lookup for a R-Port in the Port R-Port Queue
|
||||
*/
|
||||
struct bfa_fcs_rport_s *
|
||||
bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
struct list_head *qe;
|
||||
|
||||
list_for_each(qe, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
if (wwn_is_equal(rport->pwwn, pwwn))
|
||||
return rport;
|
||||
}
|
||||
|
||||
bfa_trc(port->fcs, pwwn);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* NWWN based Lookup for a R-Port in the Port R-Port Queue
|
||||
*/
|
||||
struct bfa_fcs_rport_s *
|
||||
bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
struct list_head *qe;
|
||||
|
||||
list_for_each(qe, &port->rport_q) {
|
||||
rport = (struct bfa_fcs_rport_s *)qe;
|
||||
if (wwn_is_equal(rport->nwwn, nwwn))
|
||||
return rport;
|
||||
}
|
||||
|
||||
bfa_trc(port->fcs, nwwn);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport module when new rports are discovered.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
|
||||
struct bfa_fcs_rport_s *rport)
|
||||
{
|
||||
list_add_tail(&rport->qe, &port->rport_q);
|
||||
port->num_rports++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport module to when rports are deleted.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
|
||||
struct bfa_fcs_rport_s *rport)
|
||||
{
|
||||
bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
|
||||
list_del(&rport->qe);
|
||||
port->num_rports--;
|
||||
|
||||
bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by fabric for base port when fabric login is complete.
|
||||
* Called by vport for virtual ports when FDISC is complete.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_online(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by fabric for base port when fabric goes offline.
|
||||
* Called by vport for virtual ports when virtual port becomes offline.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by fabric to delete base lport and associated resources.
|
||||
*
|
||||
* Called by vport to delete lport and associated resources. Should call
|
||||
* bfa_fcs_vport_delete_comp() for vports on completion.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by fabric in private loop topology to process LIP event.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return TRUE if port is online, else return FALSE
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
return (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logical port initialization of base or virtual port.
|
||||
* Called by fabric for base port or by vport for virtual ports.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
|
||||
u16 vf_id, struct bfa_port_cfg_s *port_cfg,
|
||||
struct bfa_fcs_vport_s *vport)
|
||||
{
|
||||
lport->fcs = fcs;
|
||||
lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
|
||||
bfa_os_assign(lport->port_cfg, *port_cfg);
|
||||
lport->vport = vport;
|
||||
lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
|
||||
bfa_lps_get_tag(lport->fabric->lps);
|
||||
|
||||
INIT_LIST_HEAD(&lport->rport_q);
|
||||
lport->num_rports = 0;
|
||||
|
||||
lport->bfad_port =
|
||||
bfa_fcb_port_new(fcs->bfad, lport, lport->port_cfg.roles,
|
||||
lport->fabric->vf_drv,
|
||||
vport ? vport->vport_drv : NULL);
|
||||
bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
|
||||
|
||||
bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
|
||||
bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fcs_lport_api
|
||||
*/
|
||||
|
||||
void
|
||||
bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
|
||||
struct bfa_port_attr_s *port_attr)
|
||||
{
|
||||
if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
|
||||
port_attr->pid = port->pid;
|
||||
else
|
||||
port_attr->pid = 0;
|
||||
|
||||
port_attr->port_cfg = port->port_cfg;
|
||||
|
||||
if (port->fabric) {
|
||||
port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
|
||||
port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
|
||||
port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
|
||||
memcpy(port_attr->fabric_ip_addr,
|
||||
bfa_fcs_port_get_fabric_ipaddr(port),
|
||||
BFA_FCS_FABRIC_IPADDR_SZ);
|
||||
|
||||
if (port->vport != NULL)
|
||||
port_attr->port_type = BFA_PPORT_TYPE_VPORT;
|
||||
|
||||
} else {
|
||||
port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
|
||||
port_attr->state = BFA_PORT_UNINIT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
68
drivers/scsi/bfa/bfa_fcs_port.c
Normal file
68
drivers/scsi/bfa/bfa_fcs_port.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_fcs_pport.c BFA FCS PPORT ( physical port)
|
||||
*/
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <fcs/bfa_fcs_fabric.h>
|
||||
#include "fcs_trcmod.h"
|
||||
#include "fcs.h"
|
||||
#include "fcs_fabric.h"
|
||||
#include "fcs_port.h"
|
||||
|
||||
BFA_TRC_FILE(FCS, PPORT);
|
||||
|
||||
static void
|
||||
bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event)
|
||||
{
|
||||
struct bfa_fcs_s *fcs = cbarg;
|
||||
|
||||
bfa_trc(fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_PPORT_LINKUP:
|
||||
bfa_fcs_fabric_link_up(&fcs->fabric);
|
||||
break;
|
||||
|
||||
case BFA_PPORT_LINKDOWN:
|
||||
bfa_fcs_fabric_link_down(&fcs->fabric);
|
||||
break;
|
||||
|
||||
case BFA_PPORT_TRUNK_LINKDOWN:
|
||||
bfa_assert(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_pport_event_register(fcs->bfa, bfa_fcs_pport_event_handler,
|
||||
fcs);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_fcs_modexit_comp(fcs);
|
||||
}
|
105
drivers/scsi/bfa/bfa_fcs_uf.c
Normal file
105
drivers/scsi/bfa/bfa_fcs_uf.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames)
|
||||
*/
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <fcs/bfa_fcs_fabric.h>
|
||||
#include "fcs.h"
|
||||
#include "fcs_trcmod.h"
|
||||
#include "fcs_fabric.h"
|
||||
#include "fcs_uf.h"
|
||||
|
||||
BFA_TRC_FILE(FCS, UF);
|
||||
|
||||
/**
|
||||
* BFA callback for unsolicited frame receive handler.
|
||||
*
|
||||
* @param[in] cbarg callback arg for receive handler
|
||||
* @param[in] uf unsolicited frame descriptor
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
|
||||
{
|
||||
struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;
|
||||
struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);
|
||||
u16 len = bfa_uf_get_frmlen(uf);
|
||||
struct fc_vft_s *vft;
|
||||
struct bfa_fcs_fabric_s *fabric;
|
||||
|
||||
/**
|
||||
* check for VFT header
|
||||
*/
|
||||
if (fchs->routing == FC_RTG_EXT_HDR &&
|
||||
fchs->cat_info == FC_CAT_VFT_HDR) {
|
||||
bfa_stats(fcs, uf.tagged);
|
||||
vft = bfa_uf_get_frmbuf(uf);
|
||||
if (fcs->port_vfid == vft->vf_id)
|
||||
fabric = &fcs->fabric;
|
||||
else
|
||||
fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
|
||||
|
||||
/**
|
||||
* drop frame if vfid is unknown
|
||||
*/
|
||||
if (!fabric) {
|
||||
bfa_assert(0);
|
||||
bfa_stats(fcs, uf.vfid_unknown);
|
||||
bfa_uf_free(uf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* skip vft header
|
||||
*/
|
||||
fchs = (struct fchs_s *) (vft + 1);
|
||||
len -= sizeof(struct fc_vft_s);
|
||||
|
||||
bfa_trc(fcs, vft->vf_id);
|
||||
} else {
|
||||
bfa_stats(fcs, uf.untagged);
|
||||
fabric = &fcs->fabric;
|
||||
}
|
||||
|
||||
bfa_trc(fcs, ((u32 *) fchs)[0]);
|
||||
bfa_trc(fcs, ((u32 *) fchs)[1]);
|
||||
bfa_trc(fcs, ((u32 *) fchs)[2]);
|
||||
bfa_trc(fcs, ((u32 *) fchs)[3]);
|
||||
bfa_trc(fcs, ((u32 *) fchs)[4]);
|
||||
bfa_trc(fcs, ((u32 *) fchs)[5]);
|
||||
bfa_trc(fcs, len);
|
||||
|
||||
bfa_fcs_fabric_uf_recv(fabric, fchs, len);
|
||||
bfa_uf_free(uf);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_fcs_modexit_comp(fcs);
|
||||
}
|
782
drivers/scsi/bfa/bfa_fcxp.c
Normal file
782
drivers/scsi/bfa/bfa_fcxp.c
Normal file
@ -0,0 +1,782 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfi/bfi_uf.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, FCXP);
|
||||
BFA_MODULE(fcxp);
|
||||
|
||||
/**
|
||||
* forward declarations
|
||||
*/
|
||||
static void __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
|
||||
static void hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
|
||||
struct bfi_fcxp_send_rsp_s *fcxp_rsp);
|
||||
static void hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
|
||||
struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
|
||||
static void bfa_fcxp_qresume(void *cbarg);
|
||||
static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
|
||||
struct bfi_fcxp_send_req_s *send_req);
|
||||
|
||||
/**
|
||||
* fcxp_pvt BFA FCXP private functions
|
||||
*/
|
||||
|
||||
static void
|
||||
claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
u8 *dm_kva = NULL;
|
||||
u64 dm_pa;
|
||||
u32 buf_pool_sz;
|
||||
|
||||
dm_kva = bfa_meminfo_dma_virt(mi);
|
||||
dm_pa = bfa_meminfo_dma_phys(mi);
|
||||
|
||||
buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
|
||||
|
||||
/*
|
||||
* Initialize the fcxp req payload list
|
||||
*/
|
||||
mod->req_pld_list_kva = dm_kva;
|
||||
mod->req_pld_list_pa = dm_pa;
|
||||
dm_kva += buf_pool_sz;
|
||||
dm_pa += buf_pool_sz;
|
||||
bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
|
||||
|
||||
/*
|
||||
* Initialize the fcxp rsp payload list
|
||||
*/
|
||||
buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
|
||||
mod->rsp_pld_list_kva = dm_kva;
|
||||
mod->rsp_pld_list_pa = dm_pa;
|
||||
dm_kva += buf_pool_sz;
|
||||
dm_pa += buf_pool_sz;
|
||||
bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
|
||||
|
||||
bfa_meminfo_dma_virt(mi) = dm_kva;
|
||||
bfa_meminfo_dma_phys(mi) = dm_pa;
|
||||
}
|
||||
|
||||
static void
|
||||
claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
u16 i;
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
|
||||
fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
|
||||
bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
|
||||
|
||||
INIT_LIST_HEAD(&mod->fcxp_free_q);
|
||||
INIT_LIST_HEAD(&mod->fcxp_active_q);
|
||||
|
||||
mod->fcxp_list = fcxp;
|
||||
|
||||
for (i = 0; i < mod->num_fcxps; i++) {
|
||||
fcxp->fcxp_mod = mod;
|
||||
fcxp->fcxp_tag = i;
|
||||
|
||||
list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
|
||||
bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
|
||||
fcxp->reqq_waiting = BFA_FALSE;
|
||||
|
||||
fcxp = fcxp + 1;
|
||||
}
|
||||
|
||||
bfa_meminfo_kva(mi) = (void *)fcxp;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
|
||||
u32 *dm_len)
|
||||
{
|
||||
u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
|
||||
|
||||
if (num_fcxp_reqs == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Account for req/rsp payload
|
||||
*/
|
||||
*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
|
||||
if (cfg->drvcfg.min_cfg)
|
||||
*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
|
||||
else
|
||||
*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
|
||||
|
||||
/*
|
||||
* Account for fcxp structs
|
||||
*/
|
||||
*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
|
||||
bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
|
||||
mod->bfa = bfa;
|
||||
mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
|
||||
|
||||
/**
|
||||
* Initialize FCXP request and response payload sizes.
|
||||
*/
|
||||
mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
|
||||
if (!cfg->drvcfg.min_cfg)
|
||||
mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
|
||||
|
||||
INIT_LIST_HEAD(&mod->wait_q);
|
||||
|
||||
claim_fcxp_req_rsp_mem(mod, meminfo);
|
||||
claim_fcxps_mem(mod, meminfo);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
|
||||
fcxp = (struct bfa_fcxp_s *) qe;
|
||||
if (fcxp->caller == NULL) {
|
||||
fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
|
||||
BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
|
||||
bfa_fcxp_free(fcxp);
|
||||
} else {
|
||||
fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
|
||||
bfa_cb_queue(bfa, &fcxp->hcb_qe,
|
||||
__bfa_fcxp_send_cbfn, fcxp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct bfa_fcxp_s *
|
||||
bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
|
||||
{
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
|
||||
bfa_q_deq(&fm->fcxp_free_q, &fcxp);
|
||||
|
||||
if (fcxp)
|
||||
list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
|
||||
|
||||
return (fcxp);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
|
||||
struct bfa_fcxp_wqe_s *wqe;
|
||||
|
||||
bfa_q_deq(&mod->wait_q, &wqe);
|
||||
if (wqe) {
|
||||
bfa_trc(mod->bfa, fcxp->fcxp_tag);
|
||||
wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
|
||||
list_del(&fcxp->qe);
|
||||
list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_null_comp(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)
|
||||
{
|
||||
/**discarded fcxp completion */
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_fcxp_s *fcxp = cbarg;
|
||||
|
||||
if (complete) {
|
||||
fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
|
||||
fcxp->rsp_status, fcxp->rsp_len,
|
||||
fcxp->residue_len, &fcxp->rsp_fchs);
|
||||
} else {
|
||||
bfa_fcxp_free(fcxp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
u16 fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
|
||||
|
||||
bfa_trc(bfa, fcxp_tag);
|
||||
|
||||
fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
|
||||
|
||||
/**
|
||||
* @todo f/w should not set residue to non-0 when everything
|
||||
* is received.
|
||||
*/
|
||||
if (fcxp_rsp->req_status == BFA_STATUS_OK)
|
||||
fcxp_rsp->residue_len = 0;
|
||||
else
|
||||
fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
|
||||
|
||||
fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
|
||||
|
||||
bfa_assert(fcxp->send_cbfn != NULL);
|
||||
|
||||
hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
|
||||
|
||||
if (fcxp->send_cbfn != NULL) {
|
||||
if (fcxp->caller == NULL) {
|
||||
bfa_trc(mod->bfa, fcxp->fcxp_tag);
|
||||
|
||||
fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
|
||||
fcxp_rsp->req_status, fcxp_rsp->rsp_len,
|
||||
fcxp_rsp->residue_len, &fcxp_rsp->fchs);
|
||||
/*
|
||||
* fcxp automatically freed on return from the callback
|
||||
*/
|
||||
bfa_fcxp_free(fcxp);
|
||||
} else {
|
||||
bfa_trc(mod->bfa, fcxp->fcxp_tag);
|
||||
fcxp->rsp_status = fcxp_rsp->req_status;
|
||||
fcxp->rsp_len = fcxp_rsp->rsp_len;
|
||||
fcxp->residue_len = fcxp_rsp->residue_len;
|
||||
fcxp->rsp_fchs = fcxp_rsp->fchs;
|
||||
|
||||
bfa_cb_queue(bfa, &fcxp->hcb_qe,
|
||||
__bfa_fcxp_send_cbfn, fcxp);
|
||||
}
|
||||
} else {
|
||||
bfa_trc(bfa, fcxp_tag);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
|
||||
{
|
||||
union bfi_addr_u sga_zero = { {0} };
|
||||
|
||||
sge->sg_len = reqlen;
|
||||
sge->flags = BFI_SGE_DATA_LAST;
|
||||
bfa_dma_addr_set(sge[0].sga, req_pa);
|
||||
bfa_sge_to_be(sge);
|
||||
sge++;
|
||||
|
||||
sge->sga = sga_zero;
|
||||
sge->sg_len = reqlen;
|
||||
sge->flags = BFI_SGE_PGDLEN;
|
||||
bfa_sge_to_be(sge);
|
||||
}
|
||||
|
||||
static void
|
||||
hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
|
||||
struct fchs_s *fchs)
|
||||
{
|
||||
/*
|
||||
* TODO: TX ox_id
|
||||
*/
|
||||
if (reqlen > 0) {
|
||||
if (fcxp->use_ireqbuf) {
|
||||
u32 pld_w0 =
|
||||
*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
|
||||
|
||||
bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
|
||||
BFA_PL_EID_TX,
|
||||
reqlen + sizeof(struct fchs_s), fchs, pld_w0);
|
||||
} else {
|
||||
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
|
||||
BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
|
||||
fchs);
|
||||
}
|
||||
} else {
|
||||
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
|
||||
reqlen + sizeof(struct fchs_s), fchs);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
|
||||
struct bfi_fcxp_send_rsp_s *fcxp_rsp)
|
||||
{
|
||||
if (fcxp_rsp->rsp_len > 0) {
|
||||
if (fcxp->use_irspbuf) {
|
||||
u32 pld_w0 =
|
||||
*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
|
||||
|
||||
bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
|
||||
BFA_PL_EID_RX,
|
||||
(u16) fcxp_rsp->rsp_len,
|
||||
&fcxp_rsp->fchs, pld_w0);
|
||||
} else {
|
||||
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
|
||||
BFA_PL_EID_RX,
|
||||
(u16) fcxp_rsp->rsp_len,
|
||||
&fcxp_rsp->fchs);
|
||||
}
|
||||
} else {
|
||||
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
|
||||
(u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler to resume sending fcxp when space in available in cpe queue.
|
||||
*/
|
||||
static void
|
||||
bfa_fcxp_qresume(void *cbarg)
|
||||
{
|
||||
struct bfa_fcxp_s *fcxp = cbarg;
|
||||
struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
|
||||
struct bfi_fcxp_send_req_s *send_req;
|
||||
|
||||
fcxp->reqq_waiting = BFA_FALSE;
|
||||
send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
|
||||
bfa_fcxp_queue(fcxp, send_req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue fcxp send request to foimrware.
|
||||
*/
|
||||
static void
|
||||
bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
|
||||
{
|
||||
struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
|
||||
struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
|
||||
struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
|
||||
struct bfa_rport_s *rport = reqi->bfa_rport;
|
||||
|
||||
bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
|
||||
send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
|
||||
if (rport) {
|
||||
send_req->rport_fw_hndl = rport->fw_handle;
|
||||
send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
|
||||
if (send_req->max_frmsz == 0)
|
||||
send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
|
||||
} else {
|
||||
send_req->rport_fw_hndl = 0;
|
||||
send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
|
||||
}
|
||||
|
||||
send_req->vf_id = bfa_os_htons(reqi->vf_id);
|
||||
send_req->lp_tag = reqi->lp_tag;
|
||||
send_req->class = reqi->class;
|
||||
send_req->rsp_timeout = rspi->rsp_timeout;
|
||||
send_req->cts = reqi->cts;
|
||||
send_req->fchs = reqi->fchs;
|
||||
|
||||
send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
|
||||
send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
|
||||
|
||||
/*
|
||||
* setup req sgles
|
||||
*/
|
||||
if (fcxp->use_ireqbuf == 1) {
|
||||
hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
|
||||
BFA_FCXP_REQ_PLD_PA(fcxp));
|
||||
} else {
|
||||
if (fcxp->nreq_sgles > 0) {
|
||||
bfa_assert(fcxp->nreq_sgles == 1);
|
||||
hal_fcxp_set_local_sges(send_req->req_sge,
|
||||
reqi->req_tot_len,
|
||||
fcxp->req_sga_cbfn(fcxp->caller,
|
||||
0));
|
||||
} else {
|
||||
bfa_assert(reqi->req_tot_len == 0);
|
||||
hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* setup rsp sgles
|
||||
*/
|
||||
if (fcxp->use_irspbuf == 1) {
|
||||
bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
|
||||
|
||||
hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
|
||||
BFA_FCXP_RSP_PLD_PA(fcxp));
|
||||
|
||||
} else {
|
||||
if (fcxp->nrsp_sgles > 0) {
|
||||
bfa_assert(fcxp->nrsp_sgles == 1);
|
||||
hal_fcxp_set_local_sges(send_req->rsp_sge,
|
||||
rspi->rsp_maxlen,
|
||||
fcxp->rsp_sga_cbfn(fcxp->caller,
|
||||
0));
|
||||
} else {
|
||||
bfa_assert(rspi->rsp_maxlen == 0);
|
||||
hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
|
||||
|
||||
bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
|
||||
|
||||
bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
|
||||
bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hal_fcxp_api BFA FCXP API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate an FCXP instance to send a response or to send a request
|
||||
* that has a response. Request/response buffers are allocated by caller.
|
||||
*
|
||||
* @param[in] bfa BFA bfa instance
|
||||
* @param[in] nreq_sgles Number of SG elements required for request
|
||||
* buffer. 0, if fcxp internal buffers are used.
|
||||
* Use bfa_fcxp_get_reqbuf() to get the
|
||||
* internal req buffer.
|
||||
* @param[in] req_sgles SG elements describing request buffer. Will be
|
||||
* copied in by BFA and hence can be freed on
|
||||
* return from this function.
|
||||
* @param[in] get_req_sga function ptr to be called to get a request SG
|
||||
* Address (given the sge index).
|
||||
* @param[in] get_req_sglen function ptr to be called to get a request SG
|
||||
* len (given the sge index).
|
||||
* @param[in] get_rsp_sga function ptr to be called to get a response SG
|
||||
* Address (given the sge index).
|
||||
* @param[in] get_rsp_sglen function ptr to be called to get a response SG
|
||||
* len (given the sge index).
|
||||
*
|
||||
* @return FCXP instance. NULL on failure.
|
||||
*/
|
||||
struct bfa_fcxp_s *
|
||||
bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
|
||||
int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
|
||||
bfa_fcxp_get_sglen_t req_sglen_cbfn,
|
||||
bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
|
||||
bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
|
||||
{
|
||||
struct bfa_fcxp_s *fcxp = NULL;
|
||||
u32 nreq_sgpg, nrsp_sgpg;
|
||||
|
||||
bfa_assert(bfa != NULL);
|
||||
|
||||
fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
|
||||
if (fcxp == NULL)
|
||||
return (NULL);
|
||||
|
||||
bfa_trc(bfa, fcxp->fcxp_tag);
|
||||
|
||||
fcxp->caller = caller;
|
||||
|
||||
if (nreq_sgles == 0) {
|
||||
fcxp->use_ireqbuf = 1;
|
||||
} else {
|
||||
bfa_assert(req_sga_cbfn != NULL);
|
||||
bfa_assert(req_sglen_cbfn != NULL);
|
||||
|
||||
fcxp->use_ireqbuf = 0;
|
||||
fcxp->req_sga_cbfn = req_sga_cbfn;
|
||||
fcxp->req_sglen_cbfn = req_sglen_cbfn;
|
||||
|
||||
fcxp->nreq_sgles = nreq_sgles;
|
||||
|
||||
/*
|
||||
* alloc required sgpgs
|
||||
*/
|
||||
if (nreq_sgles > BFI_SGE_INLINE) {
|
||||
nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
|
||||
|
||||
if (bfa_sgpg_malloc
|
||||
(bfa, &fcxp->req_sgpg_q, nreq_sgpg)
|
||||
!= BFA_STATUS_OK) {
|
||||
/* bfa_sgpg_wait(bfa, &fcxp->req_sgpg_wqe,
|
||||
nreq_sgpg); */
|
||||
/*
|
||||
* TODO
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nrsp_sgles == 0) {
|
||||
fcxp->use_irspbuf = 1;
|
||||
} else {
|
||||
bfa_assert(rsp_sga_cbfn != NULL);
|
||||
bfa_assert(rsp_sglen_cbfn != NULL);
|
||||
|
||||
fcxp->use_irspbuf = 0;
|
||||
fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
|
||||
fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
|
||||
|
||||
fcxp->nrsp_sgles = nrsp_sgles;
|
||||
/*
|
||||
* alloc required sgpgs
|
||||
*/
|
||||
if (nrsp_sgles > BFI_SGE_INLINE) {
|
||||
nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
|
||||
|
||||
if (bfa_sgpg_malloc
|
||||
(bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
|
||||
!= BFA_STATUS_OK) {
|
||||
/* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
|
||||
nrsp_sgpg); */
|
||||
/*
|
||||
* TODO
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (fcxp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal request buffer pointer
|
||||
*
|
||||
* @param[in] fcxp BFA fcxp pointer
|
||||
*
|
||||
* @return pointer to the internal request buffer
|
||||
*/
|
||||
void *
|
||||
bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
|
||||
void *reqbuf;
|
||||
|
||||
bfa_assert(fcxp->use_ireqbuf == 1);
|
||||
reqbuf = ((u8 *)mod->req_pld_list_kva) +
|
||||
fcxp->fcxp_tag * mod->req_pld_sz;
|
||||
return reqbuf;
|
||||
}
|
||||
|
||||
u32
|
||||
bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
|
||||
|
||||
return mod->req_pld_sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal response buffer pointer
|
||||
*
|
||||
* @param[in] fcxp BFA fcxp pointer
|
||||
*
|
||||
* @return pointer to the internal request buffer
|
||||
*/
|
||||
void *
|
||||
bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
|
||||
void *rspbuf;
|
||||
|
||||
bfa_assert(fcxp->use_irspbuf == 1);
|
||||
|
||||
rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
|
||||
fcxp->fcxp_tag * mod->rsp_pld_sz;
|
||||
return rspbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the BFA FCXP
|
||||
*
|
||||
* @param[in] fcxp BFA fcxp pointer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
|
||||
|
||||
bfa_assert(fcxp != NULL);
|
||||
bfa_trc(mod->bfa, fcxp->fcxp_tag);
|
||||
bfa_fcxp_put(fcxp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a FCXP request
|
||||
*
|
||||
* @param[in] fcxp BFA fcxp pointer
|
||||
* @param[in] rport BFA rport pointer. Could be left NULL for WKA rports
|
||||
* @param[in] vf_id virtual Fabric ID
|
||||
* @param[in] lp_tag lport tag
|
||||
* @param[in] cts use Continous sequence
|
||||
* @param[in] cos fc Class of Service
|
||||
* @param[in] reqlen request length, does not include FCHS length
|
||||
* @param[in] fchs fc Header Pointer. The header content will be copied
|
||||
* in by BFA.
|
||||
*
|
||||
* @param[in] cbfn call back function to be called on receiving
|
||||
* the response
|
||||
* @param[in] cbarg arg for cbfn
|
||||
* @param[in] rsp_timeout
|
||||
* response timeout
|
||||
*
|
||||
* @return bfa_status_t
|
||||
*/
|
||||
void
|
||||
bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
|
||||
u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
|
||||
u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
|
||||
void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
|
||||
{
|
||||
struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
|
||||
struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
|
||||
struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
|
||||
struct bfi_fcxp_send_req_s *send_req;
|
||||
|
||||
bfa_trc(bfa, fcxp->fcxp_tag);
|
||||
|
||||
/**
|
||||
* setup request/response info
|
||||
*/
|
||||
reqi->bfa_rport = rport;
|
||||
reqi->vf_id = vf_id;
|
||||
reqi->lp_tag = lp_tag;
|
||||
reqi->class = cos;
|
||||
rspi->rsp_timeout = rsp_timeout;
|
||||
reqi->cts = cts;
|
||||
reqi->fchs = *fchs;
|
||||
reqi->req_tot_len = reqlen;
|
||||
rspi->rsp_maxlen = rsp_maxlen;
|
||||
fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
|
||||
fcxp->send_cbarg = cbarg;
|
||||
|
||||
/**
|
||||
* If no room in CPE queue, wait for
|
||||
*/
|
||||
send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
|
||||
if (!send_req) {
|
||||
bfa_trc(bfa, fcxp->fcxp_tag);
|
||||
fcxp->reqq_waiting = BFA_TRUE;
|
||||
bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_fcxp_queue(fcxp, send_req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort a BFA FCXP
|
||||
*
|
||||
* @param[in] fcxp BFA fcxp pointer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
bfa_assert(0);
|
||||
return (BFA_STATUS_OK);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
|
||||
bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
|
||||
bfa_assert(list_empty(&mod->fcxp_free_q));
|
||||
|
||||
wqe->alloc_cbfn = alloc_cbfn;
|
||||
wqe->alloc_cbarg = alloc_cbarg;
|
||||
list_add_tail(&wqe->qe, &mod->wait_q);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
|
||||
bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
|
||||
list_del(&wqe->qe);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
|
||||
{
|
||||
/**
|
||||
* If waiting for room in request queue, cancel reqq wait
|
||||
* and free fcxp.
|
||||
*/
|
||||
if (fcxp->reqq_waiting) {
|
||||
fcxp->reqq_waiting = BFA_FALSE;
|
||||
bfa_reqq_wcancel(&fcxp->reqq_wqe);
|
||||
bfa_fcxp_free(fcxp);
|
||||
return;
|
||||
}
|
||||
|
||||
fcxp->send_cbfn = bfa_fcxp_null_comp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* hal_fcxp_public BFA FCXP public functions
|
||||
*/
|
||||
|
||||
void
|
||||
bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
|
||||
{
|
||||
switch (msg->mhdr.msg_id) {
|
||||
case BFI_FCXP_I2H_SEND_RSP:
|
||||
hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_trc(bfa, msg->mhdr.msg_id);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
u32
|
||||
bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
|
||||
return mod->rsp_pld_sz;
|
||||
}
|
||||
|
||||
|
138
drivers/scsi/bfa/bfa_fcxp_priv.h
Normal file
138
drivers/scsi/bfa/bfa_fcxp_priv.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_FCXP_PRIV_H__
|
||||
#define __BFA_FCXP_PRIV_H__
|
||||
|
||||
#include <cs/bfa_sm.h>
|
||||
#include <protocol/fc.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <bfi/bfi_fcxp.h>
|
||||
|
||||
#define BFA_FCXP_MIN (1)
|
||||
#define BFA_FCXP_MAX_IBUF_SZ (2 * 1024 + 256)
|
||||
#define BFA_FCXP_MAX_LBUF_SZ (4 * 1024 + 256)
|
||||
|
||||
struct bfa_fcxp_mod_s {
|
||||
struct bfa_s *bfa; /* backpointer to BFA */
|
||||
struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
|
||||
u16 num_fcxps; /* max num FCXP requests */
|
||||
struct list_head fcxp_free_q; /* free FCXPs */
|
||||
struct list_head fcxp_active_q; /* active FCXPs */
|
||||
void *req_pld_list_kva; /* list of FCXP req pld */
|
||||
u64 req_pld_list_pa; /* list of FCXP req pld */
|
||||
void *rsp_pld_list_kva; /* list of FCXP resp pld */
|
||||
u64 rsp_pld_list_pa; /* list of FCXP resp pld */
|
||||
struct list_head wait_q; /* wait queue for free fcxp */
|
||||
u32 req_pld_sz;
|
||||
u32 rsp_pld_sz;
|
||||
};
|
||||
|
||||
#define BFA_FCXP_MOD(__bfa) (&(__bfa)->modules.fcxp_mod)
|
||||
#define BFA_FCXP_FROM_TAG(__mod, __tag) (&(__mod)->fcxp_list[__tag])
|
||||
|
||||
typedef void (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
|
||||
void *cb_arg, bfa_status_t req_status,
|
||||
u32 rsp_len, u32 resid_len,
|
||||
struct fchs_s *rsp_fchs);
|
||||
|
||||
/**
|
||||
* Information needed for a FCXP request
|
||||
*/
|
||||
struct bfa_fcxp_req_info_s {
|
||||
struct bfa_rport_s *bfa_rport; /* Pointer to the bfa rport that was
|
||||
*returned from bfa_rport_create().
|
||||
*This could be left NULL for WKA or for
|
||||
*FCXP interactions before the rport
|
||||
*nexus is established
|
||||
*/
|
||||
struct fchs_s fchs; /* request FC header structure */
|
||||
u8 cts; /* continous sequence */
|
||||
u8 class; /* FC class for the request/response */
|
||||
u16 max_frmsz; /* max send frame size */
|
||||
u16 vf_id; /* vsan tag if applicable */
|
||||
u8 lp_tag; /* lport tag */
|
||||
u32 req_tot_len; /* request payload total length */
|
||||
};
|
||||
|
||||
struct bfa_fcxp_rsp_info_s {
|
||||
struct fchs_s rsp_fchs; /* Response frame's FC header will
|
||||
* be *sent back in this field */
|
||||
u8 rsp_timeout; /* timeout in seconds, 0-no response
|
||||
*/
|
||||
u8 rsvd2[3];
|
||||
u32 rsp_maxlen; /* max response length expected */
|
||||
};
|
||||
|
||||
struct bfa_fcxp_s {
|
||||
struct list_head qe; /* fcxp queue element */
|
||||
bfa_sm_t sm; /* state machine */
|
||||
void *caller; /* driver or fcs */
|
||||
struct bfa_fcxp_mod_s *fcxp_mod;
|
||||
/* back pointer to fcxp mod */
|
||||
u16 fcxp_tag; /* internal tag */
|
||||
struct bfa_fcxp_req_info_s req_info;
|
||||
/* request info */
|
||||
struct bfa_fcxp_rsp_info_s rsp_info;
|
||||
/* response info */
|
||||
u8 use_ireqbuf; /* use internal req buf */
|
||||
u8 use_irspbuf; /* use internal rsp buf */
|
||||
u32 nreq_sgles; /* num request SGLEs */
|
||||
u32 nrsp_sgles; /* num response SGLEs */
|
||||
struct list_head req_sgpg_q; /* SG pages for request buf */
|
||||
struct list_head req_sgpg_wqe; /* wait queue for req SG page */
|
||||
struct list_head rsp_sgpg_q; /* SG pages for response buf */
|
||||
struct list_head rsp_sgpg_wqe; /* wait queue for rsp SG page */
|
||||
|
||||
bfa_fcxp_get_sgaddr_t req_sga_cbfn;
|
||||
/* SG elem addr user function */
|
||||
bfa_fcxp_get_sglen_t req_sglen_cbfn;
|
||||
/* SG elem len user function */
|
||||
bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
|
||||
/* SG elem addr user function */
|
||||
bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
|
||||
/* SG elem len user function */
|
||||
bfa_cb_fcxp_send_t send_cbfn; /* send completion callback */
|
||||
void *send_cbarg; /* callback arg */
|
||||
struct bfa_sge_s req_sge[BFA_FCXP_MAX_SGES];
|
||||
/* req SG elems */
|
||||
struct bfa_sge_s rsp_sge[BFA_FCXP_MAX_SGES];
|
||||
/* rsp SG elems */
|
||||
u8 rsp_status; /* comp: rsp status */
|
||||
u32 rsp_len; /* comp: actual response len */
|
||||
u32 residue_len; /* comp: residual rsp length */
|
||||
struct fchs_s rsp_fchs; /* comp: response fchs */
|
||||
struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
|
||||
struct bfa_reqq_wait_s reqq_wqe;
|
||||
bfa_boolean_t reqq_waiting;
|
||||
};
|
||||
|
||||
#define BFA_FCXP_REQ_PLD(_fcxp) (bfa_fcxp_get_reqbuf(_fcxp))
|
||||
|
||||
#define BFA_FCXP_RSP_FCHS(_fcxp) (&((_fcxp)->rsp_info.fchs))
|
||||
#define BFA_FCXP_RSP_PLD(_fcxp) (bfa_fcxp_get_rspbuf(_fcxp))
|
||||
|
||||
#define BFA_FCXP_REQ_PLD_PA(_fcxp) \
|
||||
((_fcxp)->fcxp_mod->req_pld_list_pa + \
|
||||
((_fcxp)->fcxp_mod->req_pld_sz * (_fcxp)->fcxp_tag))
|
||||
|
||||
#define BFA_FCXP_RSP_PLD_PA(_fcxp) \
|
||||
((_fcxp)->fcxp_mod->rsp_pld_list_pa + \
|
||||
((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
|
||||
|
||||
void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
#endif /* __BFA_FCXP_PRIV_H__ */
|
31
drivers/scsi/bfa/bfa_fwimg_priv.h
Normal file
31
drivers/scsi/bfa/bfa_fwimg_priv.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_FWIMG_PRIV_H__
|
||||
#define __BFA_FWIMG_PRIV_H__
|
||||
|
||||
#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
|
||||
#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
|
||||
|
||||
extern u32 *bfi_image_ct_get_chunk(u32 off);
|
||||
extern u32 bfi_image_ct_size;
|
||||
extern u32 *bfi_image_cb_get_chunk(u32 off);
|
||||
extern u32 bfi_image_cb_size;
|
||||
extern u32 *bfi_image_cb;
|
||||
extern u32 *bfi_image_ct;
|
||||
|
||||
#endif /* __BFA_FWIMG_PRIV_H__ */
|
142
drivers/scsi/bfa/bfa_hw_cb.c
Normal file
142
drivers/scsi/bfa/bfa_hw_cb.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa_priv.h>
|
||||
#include <bfi/bfi_cbreg.h>
|
||||
|
||||
void
|
||||
bfa_hwcb_reginit(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
|
||||
bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
|
||||
int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
|
||||
|
||||
if (fn == 0) {
|
||||
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
|
||||
bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
|
||||
} else {
|
||||
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
|
||||
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
|
||||
}
|
||||
|
||||
for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
|
||||
/*
|
||||
* CPE registers
|
||||
*/
|
||||
q = CPE_Q_NUM(fn, i);
|
||||
bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q));
|
||||
bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q));
|
||||
bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q));
|
||||
|
||||
/*
|
||||
* RME registers
|
||||
*/
|
||||
q = CPE_Q_NUM(fn, i);
|
||||
bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q));
|
||||
bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q));
|
||||
bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
|
||||
{
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_status,
|
||||
__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq));
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
|
||||
u32 *num_vecs, u32 *max_vec_bit)
|
||||
{
|
||||
#define __HFN_NUMINTS 13
|
||||
if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
|
||||
*msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
|
||||
__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
|
||||
__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
|
||||
__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
|
||||
__HFN_INT_MBOX_LPU0);
|
||||
*max_vec_bit = __HFN_INT_MBOX_LPU0;
|
||||
} else {
|
||||
*msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
|
||||
__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
|
||||
__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
|
||||
__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
|
||||
__HFN_INT_MBOX_LPU1);
|
||||
*max_vec_bit = __HFN_INT_MBOX_LPU1;
|
||||
}
|
||||
|
||||
*msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
|
||||
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
|
||||
*num_vecs = __HFN_NUMINTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* No special setup required for crossbow -- vector assignments are implicit.
|
||||
*/
|
||||
void
|
||||
bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
|
||||
{
|
||||
int i;
|
||||
|
||||
bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS));
|
||||
|
||||
bfa->msix.nvecs = nvecs;
|
||||
if (nvecs == 1) {
|
||||
for (i = 0; i < BFA_MSIX_CB_MAX; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_all;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_reqq;
|
||||
|
||||
for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_rspq;
|
||||
|
||||
for (; i < BFA_MSIX_CB_MAX; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_lpu_err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crossbow -- dummy, interrupts are masked
|
||||
*/
|
||||
void
|
||||
bfa_hwcb_msix_install(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* No special enable/disable -- vector assignments are implicit.
|
||||
*/
|
||||
void
|
||||
bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
|
||||
{
|
||||
bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
|
||||
}
|
||||
|
||||
|
162
drivers/scsi/bfa/bfa_hw_ct.c
Normal file
162
drivers/scsi/bfa/bfa_hw_ct.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa_priv.h>
|
||||
#include <bfi/bfi_ctreg.h>
|
||||
#include <bfa_ioc.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, IOCFC_CT);
|
||||
|
||||
static u32 __ct_msix_err_vec_reg[] = {
|
||||
HOST_MSIX_ERR_INDEX_FN0,
|
||||
HOST_MSIX_ERR_INDEX_FN1,
|
||||
HOST_MSIX_ERR_INDEX_FN2,
|
||||
HOST_MSIX_ERR_INDEX_FN3,
|
||||
};
|
||||
|
||||
static void
|
||||
bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec)
|
||||
{
|
||||
int fn = bfa_ioc_pcifn(&bfa->ioc);
|
||||
bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
|
||||
|
||||
if (msix)
|
||||
bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], vec);
|
||||
else
|
||||
bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy interrupt handler for handling spurious interrupt during chip-reinit.
|
||||
*/
|
||||
static void
|
||||
bfa_hwct_msix_dummy(struct bfa_s *bfa, int vec)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwct_reginit(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
|
||||
bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
|
||||
int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
|
||||
|
||||
if (fn == 0) {
|
||||
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
|
||||
bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
|
||||
} else {
|
||||
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
|
||||
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
|
||||
}
|
||||
|
||||
for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
|
||||
/*
|
||||
* CPE registers
|
||||
*/
|
||||
q = CPE_Q_NUM(fn, i);
|
||||
bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5));
|
||||
bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5));
|
||||
bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5));
|
||||
bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5));
|
||||
|
||||
/*
|
||||
* RME registers
|
||||
*/
|
||||
q = CPE_Q_NUM(fn, i);
|
||||
bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5));
|
||||
bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5));
|
||||
bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5));
|
||||
bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq)
|
||||
{
|
||||
u32 r32;
|
||||
|
||||
r32 = bfa_reg_read(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]);
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq], r32);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
|
||||
u32 *num_vecs, u32 *max_vec_bit)
|
||||
{
|
||||
*msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1;
|
||||
*max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1));
|
||||
*num_vecs = BFA_MSIX_CT_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup MSI-X vector for catapult
|
||||
*/
|
||||
void
|
||||
bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
|
||||
{
|
||||
bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX));
|
||||
bfa_trc(bfa, nvecs);
|
||||
|
||||
bfa->msix.nvecs = nvecs;
|
||||
bfa_hwct_msix_uninstall(bfa);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwct_msix_install(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bfa->msix.nvecs == 0)
|
||||
return;
|
||||
|
||||
if (bfa->msix.nvecs == 1) {
|
||||
for (i = 0; i < BFA_MSIX_CT_MAX; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_all;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_reqq;
|
||||
|
||||
for (; i <= BFA_MSIX_RME_Q3; i++)
|
||||
bfa->msix.handler[i] = bfa_msix_rspq;
|
||||
|
||||
bfa_assert(i == BFA_MSIX_LPU_ERR);
|
||||
bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_hwct_msix_uninstall(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BFA_MSIX_CT_MAX; i++)
|
||||
bfa->msix.handler[i] = bfa_hwct_msix_dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable MSI-X vectors
|
||||
*/
|
||||
void
|
||||
bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
|
||||
{
|
||||
bfa_trc(bfa, 0);
|
||||
bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);
|
||||
bfa_ioc_isr_mode_set(&bfa->ioc, msix);
|
||||
}
|
||||
|
||||
|
218
drivers/scsi/bfa/bfa_intr.c
Normal file
218
drivers/scsi/bfa/bfa_intr.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfi/bfi_cbreg.h>
|
||||
#include <bfa_port_priv.h>
|
||||
#include <bfa_intr_priv.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, INTR);
|
||||
|
||||
static void
|
||||
bfa_msix_errint(struct bfa_s *bfa, u32 intr)
|
||||
{
|
||||
bfa_ioc_error_isr(&bfa->ioc);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_msix_lpu(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_ioc_mbox_isr(&bfa->ioc);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_msix_all(struct bfa_s *bfa, int vec)
|
||||
{
|
||||
bfa_intx(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_intr_api
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_intx(struct bfa_s *bfa)
|
||||
{
|
||||
u32 intr, qintr;
|
||||
int queue;
|
||||
|
||||
intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
|
||||
if (!intr)
|
||||
return BFA_FALSE;
|
||||
|
||||
/**
|
||||
* RME completion queue interrupt
|
||||
*/
|
||||
qintr = intr & __HFN_INT_RME_MASK;
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
|
||||
|
||||
for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue ++) {
|
||||
if (intr & (__HFN_INT_RME_Q0 << queue))
|
||||
bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
|
||||
}
|
||||
intr &= ~qintr;
|
||||
if (!intr)
|
||||
return BFA_TRUE;
|
||||
|
||||
/**
|
||||
* CPE completion queue interrupt
|
||||
*/
|
||||
qintr = intr & __HFN_INT_CPE_MASK;
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
|
||||
|
||||
for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
|
||||
if (intr & (__HFN_INT_CPE_Q0 << queue))
|
||||
bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
|
||||
}
|
||||
intr &= ~qintr;
|
||||
if (!intr)
|
||||
return BFA_TRUE;
|
||||
|
||||
bfa_msix_lpu_err(bfa, intr);
|
||||
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_isr_enable(struct bfa_s *bfa)
|
||||
{
|
||||
u32 intr_unmask;
|
||||
int pci_func = bfa_ioc_pcifn(&bfa->ioc);
|
||||
|
||||
bfa_trc(bfa, pci_func);
|
||||
|
||||
bfa_msix_install(bfa);
|
||||
intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
|
||||
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
|
||||
|
||||
if (pci_func == 0)
|
||||
intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
|
||||
__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
|
||||
__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
|
||||
__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
|
||||
__HFN_INT_MBOX_LPU0);
|
||||
else
|
||||
intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
|
||||
__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
|
||||
__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
|
||||
__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
|
||||
__HFN_INT_MBOX_LPU1);
|
||||
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
|
||||
bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_isr_disable(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_isr_mode_set(bfa, BFA_FALSE);
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
|
||||
bfa_msix_uninstall(bfa);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_msix_reqq(struct bfa_s *bfa, int qid)
|
||||
{
|
||||
struct list_head *waitq, *qe, *qen;
|
||||
struct bfa_reqq_wait_s *wqe;
|
||||
|
||||
qid &= (BFI_IOC_MAX_CQS - 1);
|
||||
|
||||
waitq = bfa_reqq(bfa, qid);
|
||||
list_for_each_safe(qe, qen, waitq) {
|
||||
/**
|
||||
* Callback only as long as there is room in request queue
|
||||
*/
|
||||
if (bfa_reqq_full(bfa, qid))
|
||||
break;
|
||||
|
||||
list_del(qe);
|
||||
wqe = (struct bfa_reqq_wait_s *) qe;
|
||||
wqe->qresume(wqe->cbarg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
|
||||
{
|
||||
bfa_trc(bfa, m->mhdr.msg_class);
|
||||
bfa_trc(bfa, m->mhdr.msg_id);
|
||||
bfa_trc(bfa, m->mhdr.mtag.i2htok);
|
||||
bfa_assert(0);
|
||||
bfa_trc_stop(bfa->trcmod);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid)
|
||||
{
|
||||
struct bfi_msg_s *m;
|
||||
u32 pi, ci;
|
||||
|
||||
bfa_trc_fp(bfa, rsp_qid);
|
||||
|
||||
rsp_qid &= (BFI_IOC_MAX_CQS - 1);
|
||||
|
||||
bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid);
|
||||
|
||||
ci = bfa_rspq_ci(bfa, rsp_qid);
|
||||
pi = bfa_rspq_pi(bfa, rsp_qid);
|
||||
|
||||
bfa_trc_fp(bfa, ci);
|
||||
bfa_trc_fp(bfa, pi);
|
||||
|
||||
if (bfa->rme_process) {
|
||||
while (ci != pi) {
|
||||
m = bfa_rspq_elem(bfa, rsp_qid, ci);
|
||||
bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
|
||||
|
||||
bfa_isrs[m->mhdr.msg_class] (bfa, m);
|
||||
|
||||
CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update CI
|
||||
*/
|
||||
bfa_rspq_ci(bfa, rsp_qid) = pi;
|
||||
bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi);
|
||||
bfa_os_mmiowb();
|
||||
}
|
||||
|
||||
void
|
||||
bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
|
||||
{
|
||||
u32 intr;
|
||||
|
||||
intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
|
||||
|
||||
if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
|
||||
bfa_msix_lpu(bfa);
|
||||
|
||||
if (intr & (__HFN_INT_ERR_EMC |
|
||||
__HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 |
|
||||
__HFN_INT_ERR_PSS))
|
||||
bfa_msix_errint(bfa, intr);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
|
||||
{
|
||||
bfa_isrs[mc] = isr_func;
|
||||
}
|
||||
|
||||
|
115
drivers/scsi/bfa/bfa_intr_priv.h
Normal file
115
drivers/scsi/bfa/bfa_intr_priv.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_INTR_PRIV_H__
|
||||
#define __BFA_INTR_PRIV_H__
|
||||
|
||||
/**
|
||||
* Message handler
|
||||
*/
|
||||
typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
|
||||
void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
|
||||
void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
|
||||
|
||||
|
||||
#define bfa_reqq_pi(__bfa, __reqq) (__bfa)->iocfc.req_cq_pi[__reqq]
|
||||
#define bfa_reqq_ci(__bfa, __reqq) \
|
||||
*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva)
|
||||
|
||||
#define bfa_reqq_full(__bfa, __reqq) \
|
||||
(((bfa_reqq_pi(__bfa, __reqq) + 1) & \
|
||||
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \
|
||||
bfa_reqq_ci(__bfa, __reqq))
|
||||
|
||||
#define bfa_reqq_next(__bfa, __reqq) \
|
||||
(bfa_reqq_full(__bfa, __reqq) ? NULL : \
|
||||
((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
|
||||
+ bfa_reqq_pi((__bfa), (__reqq)))))
|
||||
|
||||
#define bfa_reqq_produce(__bfa, __reqq) do { \
|
||||
(__bfa)->iocfc.req_cq_pi[__reqq]++; \
|
||||
(__bfa)->iocfc.req_cq_pi[__reqq] &= \
|
||||
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
|
||||
bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq], \
|
||||
(__bfa)->iocfc.req_cq_pi[__reqq]); \
|
||||
bfa_os_mmiowb(); \
|
||||
} while (0)
|
||||
|
||||
#define bfa_rspq_pi(__bfa, __rspq) \
|
||||
*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva)
|
||||
|
||||
#define bfa_rspq_ci(__bfa, __rspq) (__bfa)->iocfc.rsp_cq_ci[__rspq]
|
||||
#define bfa_rspq_elem(__bfa, __rspq, __ci) \
|
||||
&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci]
|
||||
|
||||
#define CQ_INCR(__index, __size) \
|
||||
(__index)++; (__index) &= ((__size) - 1)
|
||||
|
||||
/**
|
||||
* Queue element to wait for room in request queue. FIFO order is
|
||||
* maintained when fullfilling requests.
|
||||
*/
|
||||
struct bfa_reqq_wait_s {
|
||||
struct list_head qe;
|
||||
void (*qresume) (void *cbarg);
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Circular queue usage assignments
|
||||
*/
|
||||
enum {
|
||||
BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */
|
||||
BFA_REQQ_FCXP = 0, /* all FCXP messages */
|
||||
BFA_REQQ_LPS = 0, /* all lport service msgs */
|
||||
BFA_REQQ_PORT = 0, /* all port messages */
|
||||
BFA_REQQ_FLASH = 0, /* for flash module */
|
||||
BFA_REQQ_DIAG = 0, /* for diag module */
|
||||
BFA_REQQ_RPORT = 0, /* all port messages */
|
||||
BFA_REQQ_SBOOT = 0, /* all san boot messages */
|
||||
BFA_REQQ_QOS_LO = 1, /* all low priority IO */
|
||||
BFA_REQQ_QOS_MD = 2, /* all medium priority IO */
|
||||
BFA_REQQ_QOS_HI = 3, /* all high priority IO */
|
||||
};
|
||||
|
||||
static inline void
|
||||
bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
|
||||
void *cbarg)
|
||||
{
|
||||
wqe->qresume = qresume;
|
||||
wqe->cbarg = cbarg;
|
||||
}
|
||||
|
||||
#define bfa_reqq(__bfa, __reqq) &(__bfa)->reqq_waitq[__reqq]
|
||||
|
||||
/**
|
||||
* static inline void
|
||||
* bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
|
||||
*/
|
||||
#define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \
|
||||
\
|
||||
struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
|
||||
\
|
||||
bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \
|
||||
bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \
|
||||
\
|
||||
list_add_tail(&(__wqe)->qe, waitq); \
|
||||
} while (0)
|
||||
|
||||
#define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe)
|
||||
|
||||
#endif /* __BFA_INTR_PRIV_H__ */
|
2382
drivers/scsi/bfa/bfa_ioc.c
Normal file
2382
drivers/scsi/bfa/bfa_ioc.c
Normal file
File diff suppressed because it is too large
Load Diff
259
drivers/scsi/bfa/bfa_ioc.h
Normal file
259
drivers/scsi/bfa/bfa_ioc.h
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_IOC_H__
|
||||
#define __BFA_IOC_H__
|
||||
|
||||
#include <cs/bfa_sm.h>
|
||||
#include <bfi/bfi.h>
|
||||
#include <bfi/bfi_ioc.h>
|
||||
#include <bfi/bfi_boot.h>
|
||||
#include <bfa_timer.h>
|
||||
|
||||
/**
|
||||
* PCI device information required by IOC
|
||||
*/
|
||||
struct bfa_pcidev_s {
|
||||
int pci_slot;
|
||||
u8 pci_func;
|
||||
u16 device_id;
|
||||
bfa_os_addr_t pci_bar_kva;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure used to remember the DMA-able memory block's KVA and Physical
|
||||
* Address
|
||||
*/
|
||||
struct bfa_dma_s {
|
||||
void *kva; /*! Kernel virtual address */
|
||||
u64 pa; /*! Physical address */
|
||||
};
|
||||
|
||||
#define BFA_DMA_ALIGN_SZ 256
|
||||
#define BFA_ROUNDUP(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
|
||||
|
||||
|
||||
|
||||
#define bfa_dma_addr_set(dma_addr, pa) \
|
||||
__bfa_dma_addr_set(&dma_addr, (u64)pa)
|
||||
|
||||
static inline void
|
||||
__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
|
||||
{
|
||||
dma_addr->a32.addr_lo = (u32) pa;
|
||||
dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa));
|
||||
}
|
||||
|
||||
|
||||
#define bfa_dma_be_addr_set(dma_addr, pa) \
|
||||
__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
|
||||
static inline void
|
||||
__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
|
||||
{
|
||||
dma_addr->a32.addr_lo = (u32) bfa_os_htonl(pa);
|
||||
dma_addr->a32.addr_hi = (u32) bfa_os_htonl(bfa_os_u32(pa));
|
||||
}
|
||||
|
||||
struct bfa_ioc_regs_s {
|
||||
bfa_os_addr_t hfn_mbox_cmd;
|
||||
bfa_os_addr_t hfn_mbox;
|
||||
bfa_os_addr_t lpu_mbox_cmd;
|
||||
bfa_os_addr_t lpu_mbox;
|
||||
bfa_os_addr_t pss_ctl_reg;
|
||||
bfa_os_addr_t app_pll_fast_ctl_reg;
|
||||
bfa_os_addr_t app_pll_slow_ctl_reg;
|
||||
bfa_os_addr_t ioc_sem_reg;
|
||||
bfa_os_addr_t ioc_usage_sem_reg;
|
||||
bfa_os_addr_t ioc_usage_reg;
|
||||
bfa_os_addr_t host_page_num_fn;
|
||||
bfa_os_addr_t heartbeat;
|
||||
bfa_os_addr_t ioc_fwstate;
|
||||
bfa_os_addr_t ll_halt;
|
||||
bfa_os_addr_t shirq_isr_next;
|
||||
bfa_os_addr_t shirq_msk_next;
|
||||
bfa_os_addr_t smem_page_start;
|
||||
u32 smem_pg0;
|
||||
};
|
||||
|
||||
#define bfa_reg_read(_raddr) bfa_os_reg_read(_raddr)
|
||||
#define bfa_reg_write(_raddr, _val) bfa_os_reg_write(_raddr, _val)
|
||||
#define bfa_mem_read(_raddr, _off) bfa_os_mem_read(_raddr, _off)
|
||||
#define bfa_mem_write(_raddr, _off, _val) \
|
||||
bfa_os_mem_write(_raddr, _off, _val)
|
||||
/**
|
||||
* IOC Mailbox structures
|
||||
*/
|
||||
struct bfa_mbox_cmd_s {
|
||||
struct list_head qe;
|
||||
u32 msg[BFI_IOC_MSGSZ];
|
||||
};
|
||||
|
||||
/**
|
||||
* IOC mailbox module
|
||||
*/
|
||||
typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
|
||||
struct bfa_ioc_mbox_mod_s {
|
||||
struct list_head cmd_q; /* pending mbox queue */
|
||||
int nmclass; /* number of handlers */
|
||||
struct {
|
||||
bfa_ioc_mbox_mcfunc_t cbfn; /* message handlers */
|
||||
void *cbarg;
|
||||
} mbhdlr[BFI_MC_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* IOC callback function interfaces
|
||||
*/
|
||||
typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
|
||||
typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
|
||||
typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
|
||||
typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
|
||||
struct bfa_ioc_cbfn_s {
|
||||
bfa_ioc_enable_cbfn_t enable_cbfn;
|
||||
bfa_ioc_disable_cbfn_t disable_cbfn;
|
||||
bfa_ioc_hbfail_cbfn_t hbfail_cbfn;
|
||||
bfa_ioc_reset_cbfn_t reset_cbfn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Heartbeat failure notification queue element.
|
||||
*/
|
||||
struct bfa_ioc_hbfail_notify_s {
|
||||
struct list_head qe;
|
||||
bfa_ioc_hbfail_cbfn_t cbfn;
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a heartbeat failure notification structure
|
||||
*/
|
||||
#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \
|
||||
(__notify)->cbfn = (__cbfn); \
|
||||
(__notify)->cbarg = (__cbarg); \
|
||||
} while (0)
|
||||
|
||||
struct bfa_ioc_s {
|
||||
bfa_fsm_t fsm;
|
||||
struct bfa_s *bfa;
|
||||
struct bfa_pcidev_s pcidev;
|
||||
struct bfa_timer_mod_s *timer_mod;
|
||||
struct bfa_timer_s ioc_timer;
|
||||
struct bfa_timer_s sem_timer;
|
||||
u32 hb_count;
|
||||
u32 hb_fail;
|
||||
u32 retry_count;
|
||||
struct list_head hb_notify_q;
|
||||
void *dbg_fwsave;
|
||||
int dbg_fwsave_len;
|
||||
bfa_boolean_t dbg_fwsave_once;
|
||||
enum bfi_mclass ioc_mc;
|
||||
struct bfa_ioc_regs_s ioc_regs;
|
||||
struct bfa_trc_mod_s *trcmod;
|
||||
struct bfa_aen_s *aen;
|
||||
struct bfa_log_mod_s *logm;
|
||||
struct bfa_ioc_drv_stats_s stats;
|
||||
bfa_boolean_t auto_recover;
|
||||
bfa_boolean_t fcmode;
|
||||
bfa_boolean_t ctdev;
|
||||
bfa_boolean_t cna;
|
||||
bfa_boolean_t pllinit;
|
||||
u8 port_id;
|
||||
|
||||
struct bfa_dma_s attr_dma;
|
||||
struct bfi_ioc_attr_s *attr;
|
||||
struct bfa_ioc_cbfn_s *cbfn;
|
||||
struct bfa_ioc_mbox_mod_s mbox_mod;
|
||||
};
|
||||
|
||||
#define bfa_ioc_pcifn(__ioc) (__ioc)->pcidev.pci_func
|
||||
#define bfa_ioc_devid(__ioc) (__ioc)->pcidev.device_id
|
||||
#define bfa_ioc_bar0(__ioc) (__ioc)->pcidev.pci_bar_kva
|
||||
#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
|
||||
#define bfa_ioc_fetch_stats(__ioc, __stats) \
|
||||
((__stats)->drv_stats) = (__ioc)->stats
|
||||
#define bfa_ioc_clr_stats(__ioc) \
|
||||
bfa_os_memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
|
||||
#define bfa_ioc_maxfrsize(__ioc) (__ioc)->attr->maxfrsize
|
||||
#define bfa_ioc_rx_bbcredit(__ioc) (__ioc)->attr->rx_bbcredit
|
||||
#define bfa_ioc_speed_sup(__ioc) \
|
||||
BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
|
||||
|
||||
/**
|
||||
* IOC mailbox interface
|
||||
*/
|
||||
void bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd);
|
||||
void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,
|
||||
bfa_ioc_mbox_mcfunc_t *mcfuncs);
|
||||
void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len);
|
||||
void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
|
||||
void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
|
||||
bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
|
||||
|
||||
/**
|
||||
* IOC interfaces
|
||||
*/
|
||||
void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
|
||||
struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
|
||||
struct bfa_trc_mod_s *trcmod,
|
||||
struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
|
||||
void bfa_ioc_detach(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
|
||||
enum bfi_mclass mc);
|
||||
u32 bfa_ioc_meminfo(void);
|
||||
void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa);
|
||||
void bfa_ioc_enable(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_disable(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
|
||||
|
||||
void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
|
||||
void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
|
||||
void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t intx);
|
||||
bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);
|
||||
void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
|
||||
struct bfa_adapter_attr_s *ad_attr);
|
||||
int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);
|
||||
void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);
|
||||
bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
|
||||
int *trclen);
|
||||
bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
|
||||
int *trclen);
|
||||
u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
|
||||
u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
|
||||
void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
|
||||
bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
|
||||
void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
|
||||
struct bfa_ioc_hbfail_notify_s *notify);
|
||||
|
||||
/*
|
||||
* bfa mfg wwn API functions
|
||||
*/
|
||||
wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc);
|
||||
wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc);
|
||||
wwn_t bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst);
|
||||
mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
|
||||
u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
|
||||
|
||||
#endif /* __BFA_IOC_H__ */
|
||||
|
872
drivers/scsi/bfa/bfa_iocfc.c
Normal file
872
drivers/scsi/bfa/bfa_iocfc.c
Normal file
@ -0,0 +1,872 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <cs/bfa_debug.h>
|
||||
#include <bfa_priv.h>
|
||||
#include <log/bfa_log_hal.h>
|
||||
#include <bfi/bfi_boot.h>
|
||||
#include <bfi/bfi_cbreg.h>
|
||||
#include <aen/bfa_aen_ioc.h>
|
||||
#include <defs/bfa_defs_iocfc.h>
|
||||
#include <defs/bfa_defs_pci.h>
|
||||
#include "bfa_callback_priv.h"
|
||||
#include "bfad_drv.h"
|
||||
|
||||
BFA_TRC_FILE(HAL, IOCFC);
|
||||
|
||||
/**
|
||||
* IOC local definitions
|
||||
*/
|
||||
#define BFA_IOCFC_TOV 5000 /* msecs */
|
||||
|
||||
enum {
|
||||
BFA_IOCFC_ACT_NONE = 0,
|
||||
BFA_IOCFC_ACT_INIT = 1,
|
||||
BFA_IOCFC_ACT_STOP = 2,
|
||||
BFA_IOCFC_ACT_DISABLE = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* forward declarations
|
||||
*/
|
||||
static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
|
||||
static void bfa_iocfc_disable_cbfn(void *bfa_arg);
|
||||
static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
|
||||
static void bfa_iocfc_reset_cbfn(void *bfa_arg);
|
||||
static void bfa_iocfc_stats_clear(void *bfa_arg);
|
||||
static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d,
|
||||
struct bfa_fw_stats_s *s);
|
||||
static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete);
|
||||
static void bfa_iocfc_stats_clr_timeout(void *bfa_arg);
|
||||
static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete);
|
||||
static void bfa_iocfc_stats_timeout(void *bfa_arg);
|
||||
|
||||
static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
|
||||
|
||||
/**
|
||||
* bfa_ioc_pvt BFA IOC private functions
|
||||
*/
|
||||
|
||||
static void
|
||||
bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
|
||||
{
|
||||
int i, per_reqq_sz, per_rspq_sz;
|
||||
|
||||
per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
|
||||
/*
|
||||
* Calculate CQ size
|
||||
*/
|
||||
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
|
||||
*dm_len = *dm_len + per_reqq_sz;
|
||||
*dm_len = *dm_len + per_rspq_sz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate Shadow CI/PI size
|
||||
*/
|
||||
for (i = 0; i < cfg->fwcfg.num_cqs; i++)
|
||||
*dm_len += (2 * BFA_CACHELINE_SZ);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
|
||||
{
|
||||
*dm_len +=
|
||||
BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
|
||||
*dm_len +=
|
||||
BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
|
||||
BFA_CACHELINE_SZ);
|
||||
*dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_send_cfg(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_cfg_req_s cfg_req;
|
||||
struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
|
||||
struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg;
|
||||
int i;
|
||||
|
||||
bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
|
||||
bfa_trc(bfa, cfg->fwcfg.num_cqs);
|
||||
|
||||
iocfc->cfgdone = BFA_FALSE;
|
||||
bfa_iocfc_reset_queues(bfa);
|
||||
|
||||
/**
|
||||
* initialize IOC configuration info
|
||||
*/
|
||||
cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
|
||||
cfg_info->num_cqs = cfg->fwcfg.num_cqs;
|
||||
|
||||
bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
|
||||
bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa);
|
||||
|
||||
/**
|
||||
* dma map REQ and RSP circular queues and shadow pointers
|
||||
*/
|
||||
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
|
||||
bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
|
||||
iocfc->req_cq_ba[i].pa);
|
||||
bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
|
||||
iocfc->req_cq_shadow_ci[i].pa);
|
||||
cfg_info->req_cq_elems[i] =
|
||||
bfa_os_htons(cfg->drvcfg.num_reqq_elems);
|
||||
|
||||
bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
|
||||
iocfc->rsp_cq_ba[i].pa);
|
||||
bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
|
||||
iocfc->rsp_cq_shadow_pi[i].pa);
|
||||
cfg_info->rsp_cq_elems[i] =
|
||||
bfa_os_htons(cfg->drvcfg.num_rspq_elems);
|
||||
}
|
||||
|
||||
/**
|
||||
* dma map IOC configuration itself
|
||||
*/
|
||||
bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
|
||||
|
||||
bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
|
||||
sizeof(struct bfi_iocfc_cfg_req_s));
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
bfa->bfad = bfad;
|
||||
iocfc->bfa = bfa;
|
||||
iocfc->action = BFA_IOCFC_ACT_NONE;
|
||||
|
||||
bfa_os_assign(iocfc->cfg, *cfg);
|
||||
|
||||
/**
|
||||
* Initialize chip specific handlers.
|
||||
*/
|
||||
if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) {
|
||||
iocfc->hwif.hw_reginit = bfa_hwct_reginit;
|
||||
iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
|
||||
iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
|
||||
iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
|
||||
iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
|
||||
iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
|
||||
iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
|
||||
} else {
|
||||
iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
|
||||
iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
|
||||
iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
|
||||
iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
|
||||
iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
|
||||
iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
|
||||
iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
|
||||
}
|
||||
|
||||
iocfc->hwif.hw_reginit(bfa);
|
||||
bfa->msix.nvecs = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo)
|
||||
{
|
||||
u8 *dm_kva;
|
||||
u64 dm_pa;
|
||||
int i, per_reqq_sz, per_rspq_sz;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
int dbgsz;
|
||||
|
||||
dm_kva = bfa_meminfo_dma_virt(meminfo);
|
||||
dm_pa = bfa_meminfo_dma_phys(meminfo);
|
||||
|
||||
/*
|
||||
* First allocate dma memory for IOC.
|
||||
*/
|
||||
bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
|
||||
dm_kva += bfa_ioc_meminfo();
|
||||
dm_pa += bfa_ioc_meminfo();
|
||||
|
||||
/*
|
||||
* Claim DMA-able memory for the request/response queues and for shadow
|
||||
* ci/pi registers
|
||||
*/
|
||||
per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
|
||||
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
|
||||
iocfc->req_cq_ba[i].kva = dm_kva;
|
||||
iocfc->req_cq_ba[i].pa = dm_pa;
|
||||
bfa_os_memset(dm_kva, 0, per_reqq_sz);
|
||||
dm_kva += per_reqq_sz;
|
||||
dm_pa += per_reqq_sz;
|
||||
|
||||
iocfc->rsp_cq_ba[i].kva = dm_kva;
|
||||
iocfc->rsp_cq_ba[i].pa = dm_pa;
|
||||
bfa_os_memset(dm_kva, 0, per_rspq_sz);
|
||||
dm_kva += per_rspq_sz;
|
||||
dm_pa += per_rspq_sz;
|
||||
}
|
||||
|
||||
for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
|
||||
iocfc->req_cq_shadow_ci[i].kva = dm_kva;
|
||||
iocfc->req_cq_shadow_ci[i].pa = dm_pa;
|
||||
dm_kva += BFA_CACHELINE_SZ;
|
||||
dm_pa += BFA_CACHELINE_SZ;
|
||||
|
||||
iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
|
||||
iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
|
||||
dm_kva += BFA_CACHELINE_SZ;
|
||||
dm_pa += BFA_CACHELINE_SZ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Claim DMA-able memory for the config info page
|
||||
*/
|
||||
bfa->iocfc.cfg_info.kva = dm_kva;
|
||||
bfa->iocfc.cfg_info.pa = dm_pa;
|
||||
bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
|
||||
dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
|
||||
dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
|
||||
|
||||
/*
|
||||
* Claim DMA-able memory for the config response
|
||||
*/
|
||||
bfa->iocfc.cfgrsp_dma.kva = dm_kva;
|
||||
bfa->iocfc.cfgrsp_dma.pa = dm_pa;
|
||||
bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
|
||||
|
||||
dm_kva +=
|
||||
BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
|
||||
BFA_CACHELINE_SZ);
|
||||
dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
|
||||
BFA_CACHELINE_SZ);
|
||||
|
||||
/*
|
||||
* Claim DMA-able memory for iocfc stats
|
||||
*/
|
||||
bfa->iocfc.stats_kva = dm_kva;
|
||||
bfa->iocfc.stats_pa = dm_pa;
|
||||
bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva;
|
||||
dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
|
||||
dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
|
||||
|
||||
bfa_meminfo_dma_virt(meminfo) = dm_kva;
|
||||
bfa_meminfo_dma_phys(meminfo) = dm_pa;
|
||||
|
||||
dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
|
||||
if (dbgsz > 0) {
|
||||
bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
|
||||
bfa_meminfo_kva(meminfo) += dbgsz;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA submodules initialization completion notification.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_initdone_submod(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->initdone(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start BFA submodules.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_start_submod(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
bfa->rme_process = BFA_TRUE;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->start(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable BFA submodules.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_disable_submod(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->iocdisable(bfa);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
|
||||
if (complete) {
|
||||
if (bfa->iocfc.cfgdone)
|
||||
bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
|
||||
else
|
||||
bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
|
||||
} else
|
||||
bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfad_s *bfad = bfa->bfad;
|
||||
|
||||
if (compl)
|
||||
complete(&bfad->comp);
|
||||
|
||||
else
|
||||
bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfad_s *bfad = bfa->bfad;
|
||||
|
||||
if (compl)
|
||||
complete(&bfad->disable_comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update BFA configuration from firmware configuration.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_cfgrsp(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
|
||||
struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg;
|
||||
struct bfi_iocfc_cfg_s *cfginfo = iocfc->cfginfo;
|
||||
|
||||
fwcfg->num_cqs = fwcfg->num_cqs;
|
||||
fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs);
|
||||
fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
|
||||
fwcfg->num_fcxp_reqs = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
|
||||
fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs);
|
||||
fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports);
|
||||
|
||||
cfginfo->intr_attr.coalesce = cfgrsp->intr_attr.coalesce;
|
||||
cfginfo->intr_attr.delay = bfa_os_ntohs(cfgrsp->intr_attr.delay);
|
||||
cfginfo->intr_attr.latency = bfa_os_ntohs(cfgrsp->intr_attr.latency);
|
||||
|
||||
iocfc->cfgdone = BFA_TRUE;
|
||||
|
||||
/**
|
||||
* Configuration is complete - initialize/start submodules
|
||||
*/
|
||||
if (iocfc->action == BFA_IOCFC_ACT_INIT)
|
||||
bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
|
||||
else
|
||||
bfa_iocfc_start_submod(bfa);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_clear(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_stats_req_s stats_req;
|
||||
|
||||
bfa_timer_start(bfa, &iocfc->stats_timer,
|
||||
bfa_iocfc_stats_clr_timeout, bfa,
|
||||
BFA_IOCFC_TOV);
|
||||
|
||||
bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
|
||||
sizeof(struct bfi_iocfc_stats_req_s));
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s)
|
||||
{
|
||||
u32 *dip = (u32 *) d;
|
||||
u32 *sip = (u32 *) s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++)
|
||||
dip[i] = bfa_os_ntohl(sip[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
if (complete) {
|
||||
bfa_ioc_clr_stats(&bfa->ioc);
|
||||
iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
|
||||
} else {
|
||||
iocfc->stats_busy = BFA_FALSE;
|
||||
iocfc->stats_status = BFA_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_clr_timeout(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
bfa_trc(bfa, 0);
|
||||
|
||||
iocfc->stats_status = BFA_STATUS_ETIMER;
|
||||
bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
if (complete) {
|
||||
if (iocfc->stats_status == BFA_STATUS_OK) {
|
||||
bfa_os_memset(iocfc->stats_ret, 0,
|
||||
sizeof(*iocfc->stats_ret));
|
||||
bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats,
|
||||
iocfc->fw_stats);
|
||||
}
|
||||
iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
|
||||
} else {
|
||||
iocfc->stats_busy = BFA_FALSE;
|
||||
iocfc->stats_status = BFA_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_timeout(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
bfa_trc(bfa, 0);
|
||||
|
||||
iocfc->stats_status = BFA_STATUS_ETIMER;
|
||||
bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_iocfc_stats_query(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_stats_req_s stats_req;
|
||||
|
||||
bfa_timer_start(bfa, &iocfc->stats_timer,
|
||||
bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV);
|
||||
|
||||
bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
|
||||
sizeof(struct bfi_iocfc_stats_req_s));
|
||||
}
|
||||
|
||||
void
|
||||
bfa_iocfc_reset_queues(struct bfa_s *bfa)
|
||||
{
|
||||
int q;
|
||||
|
||||
for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
|
||||
bfa_reqq_ci(bfa, q) = 0;
|
||||
bfa_reqq_pi(bfa, q) = 0;
|
||||
bfa_rspq_ci(bfa, q) = 0;
|
||||
bfa_rspq_pi(bfa, q) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC enable request is complete
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
|
||||
if (status != BFA_STATUS_OK) {
|
||||
bfa_isr_disable(bfa);
|
||||
if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
|
||||
bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
|
||||
bfa_iocfc_init_cb, bfa);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_iocfc_initdone_submod(bfa);
|
||||
bfa_iocfc_send_cfg(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC disable request is complete
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_disable_cbfn(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
|
||||
bfa_isr_disable(bfa);
|
||||
bfa_iocfc_disable_submod(bfa);
|
||||
|
||||
if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
|
||||
bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
|
||||
bfa);
|
||||
else {
|
||||
bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
|
||||
bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
|
||||
bfa);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify sub-modules of hardware failure.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_hbfail_cbfn(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
|
||||
bfa->rme_process = BFA_FALSE;
|
||||
|
||||
bfa_isr_disable(bfa);
|
||||
bfa_iocfc_disable_submod(bfa);
|
||||
|
||||
if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
|
||||
bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
|
||||
bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions on chip-reset completion.
|
||||
*/
|
||||
static void
|
||||
bfa_iocfc_reset_cbfn(void *bfa_arg)
|
||||
{
|
||||
struct bfa_s *bfa = bfa_arg;
|
||||
|
||||
bfa_iocfc_reset_queues(bfa);
|
||||
bfa_isr_enable(bfa);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_ioc_public
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query IOC memory requirement information.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len)
|
||||
{
|
||||
/* dma memory for IOC */
|
||||
*dm_len += bfa_ioc_meminfo();
|
||||
|
||||
bfa_iocfc_fw_cfg_sz(cfg, dm_len);
|
||||
bfa_iocfc_cqs_sz(cfg, dm_len);
|
||||
*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query IOC memory requirement information.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
int i;
|
||||
|
||||
bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
|
||||
bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
|
||||
bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
|
||||
bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
|
||||
|
||||
bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod,
|
||||
bfa->trcmod, bfa->aen, bfa->logm);
|
||||
bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
|
||||
bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
|
||||
|
||||
/**
|
||||
* Choose FC (ssid: 0x1C) v/s FCoE (ssid: 0x14) mode.
|
||||
*/
|
||||
if (0)
|
||||
bfa_ioc_set_fcmode(&bfa->ioc);
|
||||
|
||||
bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
|
||||
bfa_iocfc_mem_claim(bfa, cfg, meminfo);
|
||||
bfa_timer_init(&bfa->timer_mod);
|
||||
|
||||
INIT_LIST_HEAD(&bfa->comp_q);
|
||||
for (i = 0; i < BFI_IOC_MAX_CQS; i++)
|
||||
INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query IOC memory requirement information.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_detach(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_ioc_detach(&bfa->ioc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query IOC memory requirement information.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_init(struct bfa_s *bfa)
|
||||
{
|
||||
bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
|
||||
bfa_ioc_enable(&bfa->ioc);
|
||||
bfa_msix_install(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC start called from bfa_start(). Called to start IOC operations
|
||||
* at driver instantiation for this instance.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_start(struct bfa_s *bfa)
|
||||
{
|
||||
if (bfa->iocfc.cfgdone)
|
||||
bfa_iocfc_start_submod(bfa);
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC stop called from bfa_stop(). Called only when driver is unloaded
|
||||
* for this instance.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_stop(struct bfa_s *bfa)
|
||||
{
|
||||
bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
|
||||
|
||||
bfa->rme_process = BFA_FALSE;
|
||||
bfa_ioc_disable(&bfa->ioc);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
|
||||
{
|
||||
struct bfa_s *bfa = bfaarg;
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
union bfi_iocfc_i2h_msg_u *msg;
|
||||
|
||||
msg = (union bfi_iocfc_i2h_msg_u *) m;
|
||||
bfa_trc(bfa, msg->mh.msg_id);
|
||||
|
||||
switch (msg->mh.msg_id) {
|
||||
case BFI_IOCFC_I2H_CFG_REPLY:
|
||||
iocfc->cfg_reply = &msg->cfg_reply;
|
||||
bfa_iocfc_cfgrsp(bfa);
|
||||
break;
|
||||
|
||||
case BFI_IOCFC_I2H_GET_STATS_RSP:
|
||||
if (iocfc->stats_busy == BFA_FALSE
|
||||
|| iocfc->stats_status == BFA_STATUS_ETIMER)
|
||||
break;
|
||||
|
||||
bfa_timer_stop(&iocfc->stats_timer);
|
||||
iocfc->stats_status = BFA_STATUS_OK;
|
||||
bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb,
|
||||
bfa);
|
||||
break;
|
||||
case BFI_IOCFC_I2H_CLEAR_STATS_RSP:
|
||||
/*
|
||||
* check for timer pop before processing the rsp
|
||||
*/
|
||||
if (iocfc->stats_busy == BFA_FALSE
|
||||
|| iocfc->stats_status == BFA_STATUS_ETIMER)
|
||||
break;
|
||||
|
||||
bfa_timer_stop(&iocfc->stats_timer);
|
||||
iocfc->stats_status = BFA_STATUS_OK;
|
||||
bfa_cb_queue(bfa, &iocfc->stats_hcb_qe,
|
||||
bfa_iocfc_stats_clr_cb, bfa);
|
||||
break;
|
||||
case BFI_IOCFC_I2H_UPDATEQ_RSP:
|
||||
iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
|
||||
break;
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BFA_BIOS_BUILD
|
||||
void
|
||||
bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
|
||||
{
|
||||
bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
|
||||
}
|
||||
|
||||
u64
|
||||
bfa_adapter_get_id(struct bfa_s *bfa)
|
||||
{
|
||||
return bfa_ioc_get_adid(&bfa->ioc);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
attr->intr_attr = iocfc->cfginfo->intr_attr;
|
||||
attr->config = iocfc->cfg;
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_set_intr_req_s *m;
|
||||
|
||||
iocfc->cfginfo->intr_attr = *attr;
|
||||
if (!bfa_iocfc_is_operational(bfa))
|
||||
return BFA_STATUS_OK;
|
||||
|
||||
m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
|
||||
if (!m)
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
m->coalesce = attr->coalesce;
|
||||
m->delay = bfa_os_htons(attr->delay);
|
||||
m->latency = bfa_os_htons(attr->latency);
|
||||
|
||||
bfa_trc(bfa, attr->delay);
|
||||
bfa_trc(bfa, attr->latency);
|
||||
|
||||
bfa_reqq_produce(bfa, BFA_REQQ_IOC);
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
|
||||
bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
|
||||
bfa_cb_ioc_t cbfn, void *cbarg)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
if (iocfc->stats_busy) {
|
||||
bfa_trc(bfa, iocfc->stats_busy);
|
||||
return (BFA_STATUS_DEVBUSY);
|
||||
}
|
||||
|
||||
iocfc->stats_busy = BFA_TRUE;
|
||||
iocfc->stats_ret = stats;
|
||||
iocfc->stats_cbfn = cbfn;
|
||||
iocfc->stats_cbarg = cbarg;
|
||||
|
||||
bfa_iocfc_stats_query(bfa);
|
||||
|
||||
return (BFA_STATUS_OK);
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
|
||||
if (iocfc->stats_busy) {
|
||||
bfa_trc(bfa, iocfc->stats_busy);
|
||||
return (BFA_STATUS_DEVBUSY);
|
||||
}
|
||||
|
||||
iocfc->stats_busy = BFA_TRUE;
|
||||
iocfc->stats_cbfn = cbfn;
|
||||
iocfc->stats_cbarg = cbarg;
|
||||
|
||||
bfa_iocfc_stats_clear(bfa);
|
||||
return (BFA_STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable IOC after it is disabled.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_enable(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
|
||||
"IOC Enable");
|
||||
bfa_ioc_enable(&bfa->ioc);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_iocfc_disable(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
|
||||
"IOC Disable");
|
||||
bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
|
||||
|
||||
bfa->rme_process = BFA_FALSE;
|
||||
bfa_ioc_disable(&bfa->ioc);
|
||||
}
|
||||
|
||||
|
||||
bfa_boolean_t
|
||||
bfa_iocfc_is_operational(struct bfa_s *bfa)
|
||||
{
|
||||
return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return boot target port wwns -- read from boot information in flash.
|
||||
*/
|
||||
void
|
||||
bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
|
||||
|
||||
*nwwns = cfgrsp->bootwwns.nwwns;
|
||||
*wwns = cfgrsp->bootwwns.wwn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
168
drivers/scsi/bfa/bfa_iocfc.h
Normal file
168
drivers/scsi/bfa/bfa_iocfc.h
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_IOCFC_H__
|
||||
#define __BFA_IOCFC_H__
|
||||
|
||||
#include <bfa_ioc.h>
|
||||
#include <bfa.h>
|
||||
#include <bfi/bfi_iocfc.h>
|
||||
#include <bfa_callback_priv.h>
|
||||
|
||||
#define BFA_REQQ_NELEMS_MIN (4)
|
||||
#define BFA_RSPQ_NELEMS_MIN (4)
|
||||
|
||||
struct bfa_iocfc_regs_s {
|
||||
bfa_os_addr_t intr_status;
|
||||
bfa_os_addr_t intr_mask;
|
||||
bfa_os_addr_t cpe_q_pi[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t cpe_q_ci[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t cpe_q_depth[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t cpe_q_ctrl[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t rme_q_ci[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t rme_q_pi[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t rme_q_depth[BFI_IOC_MAX_CQS];
|
||||
bfa_os_addr_t rme_q_ctrl[BFI_IOC_MAX_CQS];
|
||||
};
|
||||
|
||||
/**
|
||||
* MSIX vector handlers
|
||||
*/
|
||||
#define BFA_MSIX_MAX_VECTORS 22
|
||||
typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
|
||||
struct bfa_msix_s {
|
||||
int nvecs;
|
||||
bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
|
||||
};
|
||||
|
||||
/**
|
||||
* Chip specific interfaces
|
||||
*/
|
||||
struct bfa_hwif_s {
|
||||
void (*hw_reginit)(struct bfa_s *bfa);
|
||||
void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
|
||||
void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
|
||||
void (*hw_msix_install)(struct bfa_s *bfa);
|
||||
void (*hw_msix_uninstall)(struct bfa_s *bfa);
|
||||
void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
|
||||
void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
|
||||
u32 *nvecs, u32 *maxvec);
|
||||
};
|
||||
typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
|
||||
|
||||
struct bfa_iocfc_s {
|
||||
struct bfa_s *bfa;
|
||||
struct bfa_iocfc_cfg_s cfg;
|
||||
int action;
|
||||
|
||||
u32 req_cq_pi[BFI_IOC_MAX_CQS];
|
||||
u32 rsp_cq_ci[BFI_IOC_MAX_CQS];
|
||||
|
||||
struct bfa_cb_qe_s init_hcb_qe;
|
||||
struct bfa_cb_qe_s stop_hcb_qe;
|
||||
struct bfa_cb_qe_s dis_hcb_qe;
|
||||
struct bfa_cb_qe_s stats_hcb_qe;
|
||||
bfa_boolean_t cfgdone;
|
||||
|
||||
struct bfa_dma_s cfg_info;
|
||||
struct bfi_iocfc_cfg_s *cfginfo;
|
||||
struct bfa_dma_s cfgrsp_dma;
|
||||
struct bfi_iocfc_cfgrsp_s *cfgrsp;
|
||||
struct bfi_iocfc_cfg_reply_s *cfg_reply;
|
||||
|
||||
u8 *stats_kva;
|
||||
u64 stats_pa;
|
||||
struct bfa_fw_stats_s *fw_stats;
|
||||
struct bfa_timer_s stats_timer; /* timer */
|
||||
struct bfa_iocfc_stats_s *stats_ret; /* driver stats location */
|
||||
bfa_status_t stats_status; /* stats/statsclr status */
|
||||
bfa_boolean_t stats_busy; /* outstanding stats */
|
||||
bfa_cb_ioc_t stats_cbfn; /* driver callback function */
|
||||
void *stats_cbarg; /* user callback arg */
|
||||
|
||||
struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
|
||||
struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
|
||||
struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
|
||||
struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
|
||||
struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */
|
||||
struct bfa_hwif_s hwif;
|
||||
|
||||
bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */
|
||||
void *updateq_cbarg; /* bios callback arg */
|
||||
};
|
||||
|
||||
#define bfa_lpuid(__bfa) bfa_ioc_portid(&(__bfa)->ioc)
|
||||
#define bfa_msix_init(__bfa, __nvecs) \
|
||||
(__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs)
|
||||
#define bfa_msix_install(__bfa) \
|
||||
(__bfa)->iocfc.hwif.hw_msix_install(__bfa)
|
||||
#define bfa_msix_uninstall(__bfa) \
|
||||
(__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa)
|
||||
#define bfa_isr_mode_set(__bfa, __msix) \
|
||||
(__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix)
|
||||
#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
|
||||
(__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)
|
||||
|
||||
/*
|
||||
* FC specific IOC functions.
|
||||
*/
|
||||
void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len);
|
||||
void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
|
||||
struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_pcidev_s *pcidev);
|
||||
void bfa_iocfc_detach(struct bfa_s *bfa);
|
||||
void bfa_iocfc_init(struct bfa_s *bfa);
|
||||
void bfa_iocfc_start(struct bfa_s *bfa);
|
||||
void bfa_iocfc_stop(struct bfa_s *bfa);
|
||||
void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
|
||||
void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
|
||||
bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
|
||||
void bfa_iocfc_reset_queues(struct bfa_s *bfa);
|
||||
void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
|
||||
u32 reqq_sci, u32 rspq_spi,
|
||||
bfa_cb_iocfc_t cbfn, void *cbarg);
|
||||
|
||||
void bfa_msix_all(struct bfa_s *bfa, int vec);
|
||||
void bfa_msix_reqq(struct bfa_s *bfa, int vec);
|
||||
void bfa_msix_rspq(struct bfa_s *bfa, int vec);
|
||||
void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
|
||||
|
||||
void bfa_hwcb_reginit(struct bfa_s *bfa);
|
||||
void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
|
||||
void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
|
||||
void bfa_hwcb_msix_install(struct bfa_s *bfa);
|
||||
void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
|
||||
void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
|
||||
void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
|
||||
u32 *nvecs, u32 *maxvec);
|
||||
void bfa_hwct_reginit(struct bfa_s *bfa);
|
||||
void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
|
||||
void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
|
||||
void bfa_hwct_msix_install(struct bfa_s *bfa);
|
||||
void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
|
||||
void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
|
||||
void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
|
||||
u32 *nvecs, u32 *maxvec);
|
||||
|
||||
void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len);
|
||||
void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi,
|
||||
bfa_boolean_t mincfg);
|
||||
void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns);
|
||||
|
||||
#endif /* __BFA_IOCFC_H__ */
|
||||
|
44
drivers/scsi/bfa/bfa_iocfc_q.c
Normal file
44
drivers/scsi/bfa/bfa_iocfc_q.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include "bfa_intr_priv.h"
|
||||
|
||||
BFA_TRC_FILE(HAL, IOCFC_Q);
|
||||
|
||||
void
|
||||
bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
|
||||
u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn,
|
||||
void *cbarg)
|
||||
{
|
||||
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
|
||||
struct bfi_iocfc_updateq_req_s updateq_req;
|
||||
|
||||
iocfc->updateq_cbfn = cbfn;
|
||||
iocfc->updateq_cbarg = cbarg;
|
||||
|
||||
bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ,
|
||||
bfa_lpuid(bfa));
|
||||
|
||||
updateq_req.reqq_ba = bfa_os_htonl(reqq_ba);
|
||||
updateq_req.rspq_ba = bfa_os_htonl(rspq_ba);
|
||||
updateq_req.reqq_sci = bfa_os_htonl(reqq_sci);
|
||||
updateq_req.rspq_spi = bfa_os_htonl(rspq_spi);
|
||||
|
||||
bfa_ioc_mbox_send(&bfa->ioc, &updateq_req,
|
||||
sizeof(struct bfi_iocfc_updateq_req_s));
|
||||
}
|
1311
drivers/scsi/bfa/bfa_ioim.c
Normal file
1311
drivers/scsi/bfa/bfa_ioim.c
Normal file
File diff suppressed because it is too large
Load Diff
1088
drivers/scsi/bfa/bfa_itnim.c
Normal file
1088
drivers/scsi/bfa/bfa_itnim.c
Normal file
File diff suppressed because it is too large
Load Diff
346
drivers/scsi/bfa/bfa_log.c
Normal file
346
drivers/scsi/bfa/bfa_log.c
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_log.c BFA log library
|
||||
*/
|
||||
|
||||
#include <bfa_os_inc.h>
|
||||
#include <cs/bfa_log.h>
|
||||
|
||||
/*
|
||||
* global log info structure
|
||||
*/
|
||||
struct bfa_log_info_s {
|
||||
u32 start_idx; /* start index for a module */
|
||||
u32 total_count; /* total count for a module */
|
||||
enum bfa_log_severity level; /* global log level */
|
||||
bfa_log_cb_t cbfn; /* callback function */
|
||||
};
|
||||
|
||||
static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1];
|
||||
static u32 bfa_log_msg_total_count;
|
||||
static int bfa_log_initialized;
|
||||
|
||||
static char *bfa_log_severity[] =
|
||||
{ "[none]", "[critical]", "[error]", "[warn]", "[info]", "" };
|
||||
|
||||
/**
|
||||
* BFA log library initialization
|
||||
*
|
||||
* The log library initialization includes the following,
|
||||
* - set log instance name and callback function
|
||||
* - read the message array generated from xml files
|
||||
* - calculate start index for each module
|
||||
* - calculate message count for each module
|
||||
* - perform error checking
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] instance_name - instance name
|
||||
* @param[in] cbfn - callback function
|
||||
*
|
||||
* It return 0 on success, or -1 on failure
|
||||
*/
|
||||
int
|
||||
bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name,
|
||||
bfa_log_cb_t cbfn)
|
||||
{
|
||||
struct bfa_log_msgdef_s *msg;
|
||||
u32 pre_mod_id = 0;
|
||||
u32 cur_mod_id = 0;
|
||||
u32 i, pre_idx, idx, msg_id;
|
||||
|
||||
/*
|
||||
* set instance name
|
||||
*/
|
||||
if (log_mod) {
|
||||
strncpy(log_mod->instance_info, instance_name,
|
||||
sizeof(log_mod->instance_info));
|
||||
log_mod->cbfn = cbfn;
|
||||
for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++)
|
||||
log_mod->log_level[i] = BFA_LOG_WARNING;
|
||||
}
|
||||
|
||||
if (bfa_log_initialized)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) {
|
||||
bfa_log_info[i].start_idx = 0;
|
||||
bfa_log_info[i].total_count = 0;
|
||||
bfa_log_info[i].level = BFA_LOG_WARNING;
|
||||
bfa_log_info[i].cbfn = cbfn;
|
||||
}
|
||||
|
||||
pre_idx = 0;
|
||||
idx = 0;
|
||||
msg = bfa_log_msg_array;
|
||||
msg_id = BFA_LOG_GET_MSG_ID(msg);
|
||||
pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
|
||||
while (msg_id != 0) {
|
||||
cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
|
||||
|
||||
if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) {
|
||||
cbfn(log_mod, msg_id,
|
||||
"%s%s log: module id %u out of range\n",
|
||||
BFA_LOG_CAT_NAME,
|
||||
bfa_log_severity[BFA_LOG_ERROR],
|
||||
cur_mod_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) {
|
||||
cbfn(log_mod, msg_id,
|
||||
"%s%s log: module id %u out of range\n",
|
||||
BFA_LOG_CAT_NAME,
|
||||
bfa_log_severity[BFA_LOG_ERROR],
|
||||
pre_mod_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cur_mod_id != pre_mod_id) {
|
||||
bfa_log_info[pre_mod_id].start_idx = pre_idx;
|
||||
bfa_log_info[pre_mod_id].total_count = idx - pre_idx;
|
||||
pre_mod_id = cur_mod_id;
|
||||
pre_idx = idx;
|
||||
}
|
||||
|
||||
idx++;
|
||||
msg++;
|
||||
msg_id = BFA_LOG_GET_MSG_ID(msg);
|
||||
}
|
||||
|
||||
bfa_log_info[cur_mod_id].start_idx = pre_idx;
|
||||
bfa_log_info[cur_mod_id].total_count = idx - pre_idx;
|
||||
bfa_log_msg_total_count = idx;
|
||||
|
||||
cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n",
|
||||
BFA_LOG_CAT_NAME,
|
||||
bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count);
|
||||
|
||||
bfa_log_initialized = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA log set log level for a module
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] mod_id - module id
|
||||
* @param[in] log_level - log severity level
|
||||
*
|
||||
* It return BFA_STATUS_OK on success, or > 0 on failure
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id,
|
||||
enum bfa_log_severity log_level)
|
||||
{
|
||||
if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
|
||||
return BFA_STATUS_EINVAL;
|
||||
|
||||
if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
|
||||
return BFA_STATUS_EINVAL;
|
||||
|
||||
if (log_mod)
|
||||
log_mod->log_level[mod_id] = log_level;
|
||||
else
|
||||
bfa_log_info[mod_id].level = log_level;
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA log set log level for all modules
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] log_level - log severity level
|
||||
*
|
||||
* It return BFA_STATUS_OK on success, or > 0 on failure
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
|
||||
enum bfa_log_severity log_level)
|
||||
{
|
||||
int mod_id = BFA_LOG_UNUSED_ID + 1;
|
||||
|
||||
if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
|
||||
return BFA_STATUS_EINVAL;
|
||||
|
||||
if (log_mod) {
|
||||
for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
|
||||
log_mod->log_level[mod_id] = log_level;
|
||||
} else {
|
||||
for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
|
||||
bfa_log_info[mod_id].level = log_level;
|
||||
}
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA log set log level for all aen sub-modules
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] log_level - log severity level
|
||||
*
|
||||
* It return BFA_STATUS_OK on success, or > 0 on failure
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
|
||||
enum bfa_log_severity log_level)
|
||||
{
|
||||
int mod_id = BFA_LOG_AEN_MIN + 1;
|
||||
|
||||
if (log_mod) {
|
||||
for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
|
||||
log_mod->log_level[mod_id] = log_level;
|
||||
} else {
|
||||
for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
|
||||
bfa_log_info[mod_id].level = log_level;
|
||||
}
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA log get log level for a module
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] mod_id - module id
|
||||
*
|
||||
* It returns log level or -1 on error
|
||||
*/
|
||||
enum bfa_log_severity
|
||||
bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
|
||||
{
|
||||
if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
|
||||
return BFA_LOG_INVALID;
|
||||
|
||||
if (log_mod)
|
||||
return (log_mod->log_level[mod_id]);
|
||||
else
|
||||
return (bfa_log_info[mod_id].level);
|
||||
}
|
||||
|
||||
enum bfa_log_severity
|
||||
bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id)
|
||||
{
|
||||
struct bfa_log_msgdef_s *msg;
|
||||
u32 mod = BFA_LOG_GET_MOD_ID(msg_id);
|
||||
u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
|
||||
|
||||
if (!bfa_log_initialized)
|
||||
return BFA_LOG_INVALID;
|
||||
|
||||
if (mod > BFA_LOG_MODULE_ID_MAX)
|
||||
return BFA_LOG_INVALID;
|
||||
|
||||
if (idx >= bfa_log_info[mod].total_count) {
|
||||
bfa_log_info[mod].cbfn(log_mod, msg_id,
|
||||
"%s%s log: inconsistent idx %u vs. total count %u\n",
|
||||
BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
|
||||
bfa_log_info[mod].total_count);
|
||||
return BFA_LOG_INVALID;
|
||||
}
|
||||
|
||||
msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
|
||||
if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
|
||||
bfa_log_info[mod].cbfn(log_mod, msg_id,
|
||||
"%s%s log: inconsistent msg id %u array msg id %u\n",
|
||||
BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
|
||||
msg_id, BFA_LOG_GET_MSG_ID(msg));
|
||||
return BFA_LOG_INVALID;
|
||||
}
|
||||
|
||||
return BFA_LOG_GET_SEVERITY(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA log message handling
|
||||
*
|
||||
* BFA log message handling finds the message based on message id and prints
|
||||
* out the message based on its format and arguments. It also does prefix
|
||||
* the severity etc.
|
||||
*
|
||||
* @param[in] log_mod - log module info
|
||||
* @param[in] msg_id - message id
|
||||
* @param[in] ... - message arguments
|
||||
*
|
||||
* It return 0 on success, or -1 on errors
|
||||
*/
|
||||
int
|
||||
bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[256];
|
||||
struct bfa_log_msgdef_s *msg;
|
||||
int log_level;
|
||||
u32 mod = BFA_LOG_GET_MOD_ID(msg_id);
|
||||
u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
|
||||
|
||||
if (!bfa_log_initialized)
|
||||
return -1;
|
||||
|
||||
if (mod > BFA_LOG_MODULE_ID_MAX)
|
||||
return -1;
|
||||
|
||||
if (idx >= bfa_log_info[mod].total_count) {
|
||||
bfa_log_info[mod].
|
||||
cbfn
|
||||
(log_mod, msg_id,
|
||||
"%s%s log: inconsistent idx %u vs. total count %u\n",
|
||||
BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
|
||||
bfa_log_info[mod].total_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
|
||||
if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
|
||||
bfa_log_info[mod].
|
||||
cbfn
|
||||
(log_mod, msg_id,
|
||||
"%s%s log: inconsistent msg id %u array msg id %u\n",
|
||||
BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
|
||||
msg_id, BFA_LOG_GET_MSG_ID(msg));
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level;
|
||||
if ((BFA_LOG_GET_SEVERITY(msg) > log_level) &&
|
||||
(msg->attributes != BFA_LOG_ATTR_NONE))
|
||||
return 0;
|
||||
|
||||
va_start(ap, msg_id);
|
||||
bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap);
|
||||
va_end(ap);
|
||||
|
||||
if (log_mod)
|
||||
log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n",
|
||||
BFA_LOG_CAT_NAME, log_mod->instance_info,
|
||||
bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
|
||||
(msg->attributes & BFA_LOG_ATTR_AUDIT)
|
||||
? " (audit) " : "", msg->msg_value, buf);
|
||||
else
|
||||
bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n",
|
||||
BFA_LOG_CAT_NAME,
|
||||
bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
|
||||
(msg->attributes & BFA_LOG_ATTR_AUDIT) ?
|
||||
" (audit) " : "", msg->msg_value, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
451
drivers/scsi/bfa/bfa_log_module.c
Normal file
451
drivers/scsi/bfa/bfa_log_module.c
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <cs/bfa_log.h>
|
||||
#include <aen/bfa_aen_adapter.h>
|
||||
#include <aen/bfa_aen_audit.h>
|
||||
#include <aen/bfa_aen_ethport.h>
|
||||
#include <aen/bfa_aen_ioc.h>
|
||||
#include <aen/bfa_aen_itnim.h>
|
||||
#include <aen/bfa_aen_lport.h>
|
||||
#include <aen/bfa_aen_port.h>
|
||||
#include <aen/bfa_aen_rport.h>
|
||||
#include <log/bfa_log_fcs.h>
|
||||
#include <log/bfa_log_hal.h>
|
||||
#include <log/bfa_log_linux.h>
|
||||
#include <log/bfa_log_wdrv.h>
|
||||
|
||||
struct bfa_log_msgdef_s bfa_log_msg_array[] = {
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_ADAPTER Module */
|
||||
{BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ADAPTER_ADD",
|
||||
"New adapter found: SN = %s, base port WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE",
|
||||
"Adapter removed: SN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_AUDIT Module */
|
||||
{BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE",
|
||||
"Authentication enabled for base port: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE",
|
||||
"Authentication disabled for base port: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_ETHPORT Module */
|
||||
{BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ETHPORT_LINKUP",
|
||||
"Base port ethernet linkup: mac = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ETHPORT_LINKDOWN",
|
||||
"Base port ethernet linkdown: mac = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ETHPORT_ENABLE",
|
||||
"Base port ethernet interface enabled: mac = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ETHPORT_DISABLE",
|
||||
"Base port ethernet interface disabled: mac = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_IOC Module */
|
||||
{BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_IOC_HBGOOD",
|
||||
"Heart Beat of IOC %d is good.",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL,
|
||||
"BFA_AEN_IOC_HBFAIL",
|
||||
"Heart Beat of IOC %d has failed.",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_IOC_ENABLE",
|
||||
"IOC %d is enabled.",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_IOC_DISABLE",
|
||||
"IOC %d is disabled.",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH",
|
||||
"Running firmware version is incompatible with the driver version.",
|
||||
(0), 0},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_ITNIM Module */
|
||||
{BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ITNIM_ONLINE",
|
||||
"Target (WWN = %s) is online for initiator (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_ITNIM_OFFLINE",
|
||||
"Target (WWN = %s) offlined by initiator (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT",
|
||||
"Target (WWN = %s) connectivity lost for initiator (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_LPORT Module */
|
||||
{BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_LPORT_NEW",
|
||||
"New logical port created: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_LPORT_DELETE",
|
||||
"Logical port deleted: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_LPORT_ONLINE",
|
||||
"Logical port online: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_LPORT_OFFLINE",
|
||||
"Logical port taken offline: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT",
|
||||
"Logical port lost fabric connectivity: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_LPORT_NEW_PROP",
|
||||
"New virtual port created using proprietary interface: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP",
|
||||
"Virtual port deleted using proprietary interface: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD",
|
||||
"New virtual port created using standard interface: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD",
|
||||
"Virtual port deleted using standard interface: WWN = %s, Role = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN",
|
||||
"Virtual port login failed. Duplicate WWN = %s reported by fabric.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX",
|
||||
"Virtual port (WWN = %s) login failed. Max NPIV ports already exist in"
|
||||
" fabric/fport.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN",
|
||||
"Virtual port (WWN = %s) login failed.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_PORT Module */
|
||||
{BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE",
|
||||
"Base port online: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
|
||||
"BFA_AEN_PORT_OFFLINE",
|
||||
"Base port offline: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_PORT_RLIR",
|
||||
"RLIR event not supported.",
|
||||
(0), 0},
|
||||
|
||||
{BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_PORT_SFP_INSERT",
|
||||
"New SFP found: WWN/MAC = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE",
|
||||
"SFP removed: WWN/MAC = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
|
||||
"BFA_AEN_PORT_SFP_POM",
|
||||
"SFP POM level to %s: WWN/MAC = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_PORT_ENABLE",
|
||||
"Base port enabled: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_PORT_DISABLE",
|
||||
"Base port disabled: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_PORT_AUTH_ON",
|
||||
"Authentication successful for base port: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
|
||||
"BFA_AEN_PORT_AUTH_OFF",
|
||||
"Authentication unsuccessful for base port: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
|
||||
"BFA_AEN_PORT_DISCONNECT",
|
||||
"Base port (WWN = %s) lost fabric connectivity.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
|
||||
"BFA_AEN_PORT_QOS_NEG",
|
||||
"QOS negotiation failed for base port: WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE",
|
||||
"Base port WWN = %s, Fabric WWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR",
|
||||
"SFP access error: WWN/MAC = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT",
|
||||
"Unsupported SFP found: WWN/MAC = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for BFA_AEN_CAT_RPORT Module */
|
||||
{BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_RPORT_ONLINE",
|
||||
"Remote port (WWN = %s) online for logical port (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_RPORT_OFFLINE",
|
||||
"Remote port (WWN = %s) offlined by logical port (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT",
|
||||
"Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
|
||||
|
||||
{BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_RPORT_QOS_PRIO",
|
||||
"QOS priority changed to %s: RPWWN = %s and LPWWN = %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
{BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"BFA_AEN_RPORT_QOS_FLOWID",
|
||||
"QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for FCS Module */
|
||||
{BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH",
|
||||
"No switched fabric presence is detected.",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "FCS_FABRIC_ISOLATED",
|
||||
"Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and"
|
||||
" switch port VF_ID: %04x.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for HAL Module */
|
||||
{BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
|
||||
"HAL_ASSERT",
|
||||
"Assertion failure: %s:%d: %s",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
{BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE",
|
||||
"Firmware heartbeat failure at %d",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID",
|
||||
"Driver configuration %s value %d is invalid. Value should be within"
|
||||
" %d and %d.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4},
|
||||
|
||||
{BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
|
||||
"HAL_SM_ASSERT",
|
||||
"SM Assertion failure: %s:%d: event = %d",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_D << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for LINUX Module */
|
||||
{BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED",
|
||||
"bfa device at %s claimed.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED",
|
||||
"Hash table initialization failure for the port %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_SYSFS_FAILED",
|
||||
"sysfs file creation failure for the port %s.",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED",
|
||||
"Memory allocation failed: %s. ",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED,
|
||||
BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"LINUX_DRIVER_REGISTRATION_FAILED",
|
||||
"%s. ",
|
||||
((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"LINUX_ITNIM_FREE",
|
||||
"scsi%d: FCID: %s WWPN: %s",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
{BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_ITNIM_ONLINE",
|
||||
"Target: %d:0:%d FCID: %s WWPN: %s",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
|
||||
|
||||
{BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE",
|
||||
"Target: %d:0:%d FCID: %s WWPN: %s",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
|
||||
|
||||
{BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE",
|
||||
"Free scsi%d",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
|
||||
|
||||
{BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
|
||||
"LINUX_SCSI_ABORT",
|
||||
"scsi%d: abort cmnd %p, iotag %x",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
{BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP",
|
||||
"scsi%d: complete abort 0x%p, iotag 0x%x",
|
||||
((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
|
||||
(BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
|
||||
|
||||
|
||||
|
||||
|
||||
/* messages define for WDRV Module */
|
||||
{BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR",
|
||||
"IOC initialization has failed.",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR",
|
||||
"IOC internal error. ",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_IOC_START_ERROR",
|
||||
"IOC could not be started. ",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR",
|
||||
"IOC could not be stopped. ",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES",
|
||||
"Insufficient memory. ",
|
||||
(0), 0},
|
||||
|
||||
{BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
|
||||
BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR",
|
||||
"Unable to map the IOC onto the system address space. ",
|
||||
(0), 0},
|
||||
|
||||
|
||||
{0, 0, 0, "", "", 0, 0},
|
||||
};
|
782
drivers/scsi/bfa/bfa_lps.c
Normal file
782
drivers/scsi/bfa/bfa_lps.c
Normal file
@ -0,0 +1,782 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfi/bfi_lps.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, LPS);
|
||||
BFA_MODULE(lps);
|
||||
|
||||
#define BFA_LPS_MIN_LPORTS (1)
|
||||
#define BFA_LPS_MAX_LPORTS (256)
|
||||
|
||||
/**
|
||||
* forward declarations
|
||||
*/
|
||||
static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
|
||||
u32 *dm_len);
|
||||
static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
|
||||
struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_pcidev_s *pcidev);
|
||||
static void bfa_lps_initdone(struct bfa_s *bfa);
|
||||
static void bfa_lps_detach(struct bfa_s *bfa);
|
||||
static void bfa_lps_start(struct bfa_s *bfa);
|
||||
static void bfa_lps_stop(struct bfa_s *bfa);
|
||||
static void bfa_lps_iocdisable(struct bfa_s *bfa);
|
||||
static void bfa_lps_login_rsp(struct bfa_s *bfa,
|
||||
struct bfi_lps_login_rsp_s *rsp);
|
||||
static void bfa_lps_logout_rsp(struct bfa_s *bfa,
|
||||
struct bfi_lps_logout_rsp_s *rsp);
|
||||
static void bfa_lps_reqq_resume(void *lps_arg);
|
||||
static void bfa_lps_free(struct bfa_lps_s *lps);
|
||||
static void bfa_lps_send_login(struct bfa_lps_s *lps);
|
||||
static void bfa_lps_send_logout(struct bfa_lps_s *lps);
|
||||
static void bfa_lps_login_comp(struct bfa_lps_s *lps);
|
||||
static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
|
||||
|
||||
|
||||
/**
|
||||
* lps_pvt BFA LPS private functions
|
||||
*/
|
||||
|
||||
enum bfa_lps_event {
|
||||
BFA_LPS_SM_LOGIN = 1, /* login request from user */
|
||||
BFA_LPS_SM_LOGOUT = 2, /* logout request from user */
|
||||
BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */
|
||||
BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */
|
||||
BFA_LPS_SM_DELETE = 5, /* lps delete from user */
|
||||
BFA_LPS_SM_OFFLINE = 6, /* Link is offline */
|
||||
};
|
||||
|
||||
static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
|
||||
static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
|
||||
static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
|
||||
enum bfa_lps_event event);
|
||||
static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
|
||||
static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
|
||||
static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
|
||||
enum bfa_lps_event event);
|
||||
|
||||
/**
|
||||
* Init state -- no login
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_LOGIN:
|
||||
if (bfa_reqq_full(lps->bfa, lps->reqq)) {
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
|
||||
bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
|
||||
} else {
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_login);
|
||||
bfa_lps_send_login(lps);
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_LOGOUT:
|
||||
bfa_lps_logout_comp(lps);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_DELETE:
|
||||
bfa_lps_free(lps);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_FWRSP:
|
||||
/* Could happen when fabric detects loopback and discards
|
||||
* the lps request. Fw will eventually sent out the timeout
|
||||
* Just ignore
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* login is in progress -- awaiting response from firmware
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_FWRSP:
|
||||
if (lps->status == BFA_STATUS_OK)
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_online);
|
||||
else
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
bfa_lps_login_comp(lps);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* login pending - awaiting space in request queue
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_RESUME:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_login);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
bfa_reqq_wcancel(&lps->wqe);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* login complete
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_LOGOUT:
|
||||
if (bfa_reqq_full(lps->bfa, lps->reqq)) {
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_logowait);
|
||||
bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
|
||||
} else {
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_logout);
|
||||
bfa_lps_send_logout(lps);
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
case BFA_LPS_SM_DELETE:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* logout in progress - awaiting firmware response
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_FWRSP:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
bfa_lps_logout_comp(lps);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* logout pending -- awaiting space in request queue
|
||||
*/
|
||||
static void
|
||||
bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
||||
{
|
||||
bfa_trc(lps->bfa, lps->lp_tag);
|
||||
bfa_trc(lps->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_LPS_SM_RESUME:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_logout);
|
||||
bfa_lps_send_logout(lps);
|
||||
break;
|
||||
|
||||
case BFA_LPS_SM_OFFLINE:
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
bfa_reqq_wcancel(&lps->wqe);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* lps_pvt BFA LPS private functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* return memory requirement
|
||||
*/
|
||||
static void
|
||||
bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
|
||||
{
|
||||
if (cfg->drvcfg.min_cfg)
|
||||
*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
|
||||
else
|
||||
*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa module attach at initialization time
|
||||
*/
|
||||
static void
|
||||
bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps;
|
||||
int i;
|
||||
|
||||
bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
|
||||
mod->num_lps = BFA_LPS_MAX_LPORTS;
|
||||
if (cfg->drvcfg.min_cfg)
|
||||
mod->num_lps = BFA_LPS_MIN_LPORTS;
|
||||
else
|
||||
mod->num_lps = BFA_LPS_MAX_LPORTS;
|
||||
mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
|
||||
|
||||
bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
|
||||
|
||||
INIT_LIST_HEAD(&mod->lps_free_q);
|
||||
INIT_LIST_HEAD(&mod->lps_active_q);
|
||||
|
||||
for (i = 0; i < mod->num_lps; i++, lps++) {
|
||||
lps->bfa = bfa;
|
||||
lps->lp_tag = (u8) i;
|
||||
lps->reqq = BFA_REQQ_LPS;
|
||||
bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
|
||||
list_add_tail(&lps->qe, &mod->lps_free_q);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC in disabled state -- consider all lps offline
|
||||
*/
|
||||
static void
|
||||
bfa_lps_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &mod->lps_active_q) {
|
||||
lps = (struct bfa_lps_s *) qe;
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Firmware login response
|
||||
*/
|
||||
static void
|
||||
bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps;
|
||||
|
||||
bfa_assert(rsp->lp_tag < mod->num_lps);
|
||||
lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
|
||||
|
||||
lps->status = rsp->status;
|
||||
switch (rsp->status) {
|
||||
case BFA_STATUS_OK:
|
||||
lps->fport = rsp->f_port;
|
||||
lps->npiv_en = rsp->npiv_en;
|
||||
lps->lp_pid = rsp->lp_pid;
|
||||
lps->pr_bbcred = bfa_os_ntohs(rsp->bb_credit);
|
||||
lps->pr_pwwn = rsp->port_name;
|
||||
lps->pr_nwwn = rsp->node_name;
|
||||
lps->auth_req = rsp->auth_req;
|
||||
lps->lp_mac = rsp->lp_mac;
|
||||
lps->brcd_switch = rsp->brcd_switch;
|
||||
lps->fcf_mac = rsp->fcf_mac;
|
||||
|
||||
break;
|
||||
|
||||
case BFA_STATUS_FABRIC_RJT:
|
||||
lps->lsrjt_rsn = rsp->lsrjt_rsn;
|
||||
lps->lsrjt_expl = rsp->lsrjt_expl;
|
||||
|
||||
break;
|
||||
|
||||
case BFA_STATUS_EPROTOCOL:
|
||||
lps->ext_status = rsp->ext_status;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do with other status */
|
||||
break;
|
||||
}
|
||||
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Firmware logout response
|
||||
*/
|
||||
static void
|
||||
bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps;
|
||||
|
||||
bfa_assert(rsp->lp_tag < mod->num_lps);
|
||||
lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
|
||||
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Space is available in request queue, resume queueing request to firmware.
|
||||
*/
|
||||
static void
|
||||
bfa_lps_reqq_resume(void *lps_arg)
|
||||
{
|
||||
struct bfa_lps_s *lps = lps_arg;
|
||||
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
|
||||
}
|
||||
|
||||
/**
|
||||
* lps is freed -- triggered by vport delete
|
||||
*/
|
||||
static void
|
||||
bfa_lps_free(struct bfa_lps_s *lps)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
|
||||
|
||||
list_del(&lps->qe);
|
||||
list_add_tail(&lps->qe, &mod->lps_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* send login request to firmware
|
||||
*/
|
||||
static void
|
||||
bfa_lps_send_login(struct bfa_lps_s *lps)
|
||||
{
|
||||
struct bfi_lps_login_req_s *m;
|
||||
|
||||
m = bfa_reqq_next(lps->bfa, lps->reqq);
|
||||
bfa_assert(m);
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
|
||||
bfa_lpuid(lps->bfa));
|
||||
|
||||
m->lp_tag = lps->lp_tag;
|
||||
m->alpa = lps->alpa;
|
||||
m->pdu_size = bfa_os_htons(lps->pdusz);
|
||||
m->pwwn = lps->pwwn;
|
||||
m->nwwn = lps->nwwn;
|
||||
m->fdisc = lps->fdisc;
|
||||
m->auth_en = lps->auth_en;
|
||||
|
||||
bfa_reqq_produce(lps->bfa, lps->reqq);
|
||||
}
|
||||
|
||||
/**
|
||||
* send logout request to firmware
|
||||
*/
|
||||
static void
|
||||
bfa_lps_send_logout(struct bfa_lps_s *lps)
|
||||
{
|
||||
struct bfi_lps_logout_req_s *m;
|
||||
|
||||
m = bfa_reqq_next(lps->bfa, lps->reqq);
|
||||
bfa_assert(m);
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
|
||||
bfa_lpuid(lps->bfa));
|
||||
|
||||
m->lp_tag = lps->lp_tag;
|
||||
m->port_name = lps->pwwn;
|
||||
bfa_reqq_produce(lps->bfa, lps->reqq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indirect login completion handler for non-fcs
|
||||
*/
|
||||
static void
|
||||
bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_lps_s *lps = arg;
|
||||
|
||||
if (!complete)
|
||||
return;
|
||||
|
||||
if (lps->fdisc)
|
||||
bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
|
||||
else
|
||||
bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Login completion handler -- direct call for fcs, queue for others
|
||||
*/
|
||||
static void
|
||||
bfa_lps_login_comp(struct bfa_lps_s *lps)
|
||||
{
|
||||
if (!lps->bfa->fcs) {
|
||||
bfa_cb_queue(lps->bfa, &lps->hcb_qe,
|
||||
bfa_lps_login_comp_cb, lps);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lps->fdisc)
|
||||
bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
|
||||
else
|
||||
bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indirect logout completion handler for non-fcs
|
||||
*/
|
||||
static void
|
||||
bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_lps_s *lps = arg;
|
||||
|
||||
if (!complete)
|
||||
return;
|
||||
|
||||
if (lps->fdisc)
|
||||
bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
|
||||
else
|
||||
bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout completion handler -- direct call for fcs, queue for others
|
||||
*/
|
||||
static void
|
||||
bfa_lps_logout_comp(struct bfa_lps_s *lps)
|
||||
{
|
||||
if (!lps->bfa->fcs) {
|
||||
bfa_cb_queue(lps->bfa, &lps->hcb_qe,
|
||||
bfa_lps_logout_comp_cb, lps);
|
||||
return;
|
||||
}
|
||||
if (lps->fdisc)
|
||||
bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
|
||||
else
|
||||
bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* lps_public BFA LPS public functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate a lport srvice tag.
|
||||
*/
|
||||
struct bfa_lps_s *
|
||||
bfa_lps_alloc(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps = NULL;
|
||||
|
||||
bfa_q_deq(&mod->lps_free_q, &lps);
|
||||
|
||||
if (lps == NULL)
|
||||
return NULL;
|
||||
|
||||
list_add_tail(&lps->qe, &mod->lps_active_q);
|
||||
|
||||
bfa_sm_set_state(lps, bfa_lps_sm_init);
|
||||
return lps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free lport service tag. This can be called anytime after an alloc.
|
||||
* No need to wait for any pending login/logout completions.
|
||||
*/
|
||||
void
|
||||
bfa_lps_delete(struct bfa_lps_s *lps)
|
||||
{
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a lport login.
|
||||
*/
|
||||
void
|
||||
bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
|
||||
wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
|
||||
{
|
||||
lps->uarg = uarg;
|
||||
lps->alpa = alpa;
|
||||
lps->pdusz = pdusz;
|
||||
lps->pwwn = pwwn;
|
||||
lps->nwwn = nwwn;
|
||||
lps->fdisc = BFA_FALSE;
|
||||
lps->auth_en = auth_en;
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a lport fdisc login.
|
||||
*/
|
||||
void
|
||||
bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
|
||||
wwn_t nwwn)
|
||||
{
|
||||
lps->uarg = uarg;
|
||||
lps->alpa = 0;
|
||||
lps->pdusz = pdusz;
|
||||
lps->pwwn = pwwn;
|
||||
lps->nwwn = nwwn;
|
||||
lps->fdisc = BFA_TRUE;
|
||||
lps->auth_en = BFA_FALSE;
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a lport logout (flogi).
|
||||
*/
|
||||
void
|
||||
bfa_lps_flogo(struct bfa_lps_s *lps)
|
||||
{
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a lport FDSIC logout.
|
||||
*/
|
||||
void
|
||||
bfa_lps_fdisclogo(struct bfa_lps_s *lps)
|
||||
{
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard a pending login request -- should be called only for
|
||||
* link down handling.
|
||||
*/
|
||||
void
|
||||
bfa_lps_discard(struct bfa_lps_s *lps)
|
||||
{
|
||||
bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return lport services tag
|
||||
*/
|
||||
u8
|
||||
bfa_lps_get_tag(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->lp_tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return lport services tag given the pid
|
||||
*/
|
||||
u8
|
||||
bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
struct bfa_lps_s *lps;
|
||||
int i;
|
||||
|
||||
for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
|
||||
if (lps->lp_pid == pid)
|
||||
return lps->lp_tag;
|
||||
}
|
||||
|
||||
/* Return base port tag anyway */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* return if fabric login indicates support for NPIV
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->npiv_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return TRUE if attached to F-Port, else return FALSE
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_lps_is_fport(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->fport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return TRUE if attached to a Brocade Fabric
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->brcd_switch;
|
||||
}
|
||||
/**
|
||||
* return TRUE if authentication is required
|
||||
*/
|
||||
bfa_boolean_t
|
||||
bfa_lps_is_authreq(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->auth_req;
|
||||
}
|
||||
|
||||
bfa_eproto_status_t
|
||||
bfa_lps_get_extstatus(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->ext_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* return port id assigned to the lport
|
||||
*/
|
||||
u32
|
||||
bfa_lps_get_pid(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->lp_pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bb_credit assigned in FLOGI response
|
||||
*/
|
||||
u16
|
||||
bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->pr_bbcred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return peer port name
|
||||
*/
|
||||
wwn_t
|
||||
bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->pr_pwwn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return peer node name
|
||||
*/
|
||||
wwn_t
|
||||
bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->pr_nwwn;
|
||||
}
|
||||
|
||||
/**
|
||||
* return reason code if login request is rejected
|
||||
*/
|
||||
u8
|
||||
bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->lsrjt_rsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* return explanation code if login request is rejected
|
||||
*/
|
||||
u8
|
||||
bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
|
||||
{
|
||||
return lps->lsrjt_expl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* LPS firmware message class handler.
|
||||
*/
|
||||
void
|
||||
bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
||||
{
|
||||
union bfi_lps_i2h_msg_u msg;
|
||||
|
||||
bfa_trc(bfa, m->mhdr.msg_id);
|
||||
msg.msg = m;
|
||||
|
||||
switch (m->mhdr.msg_id) {
|
||||
case BFI_LPS_H2I_LOGIN_RSP:
|
||||
bfa_lps_login_rsp(bfa, msg.login_rsp);
|
||||
break;
|
||||
|
||||
case BFI_LPS_H2I_LOGOUT_RSP:
|
||||
bfa_lps_logout_rsp(bfa, msg.logout_rsp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_trc(bfa, m->mhdr.msg_id);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
38
drivers/scsi/bfa/bfa_lps_priv.h
Normal file
38
drivers/scsi/bfa/bfa_lps_priv.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_LPS_PRIV_H__
|
||||
#define __BFA_LPS_PRIV_H__
|
||||
|
||||
#include <bfa_svc.h>
|
||||
|
||||
struct bfa_lps_mod_s {
|
||||
struct list_head lps_free_q;
|
||||
struct list_head lps_active_q;
|
||||
struct bfa_lps_s *lps_arr;
|
||||
int num_lps;
|
||||
};
|
||||
|
||||
#define BFA_LPS_MOD(__bfa) (&(__bfa)->modules.lps_mod)
|
||||
#define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag])
|
||||
|
||||
/*
|
||||
* external functions
|
||||
*/
|
||||
void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
|
||||
#endif /* __BFA_LPS_PRIV_H__ */
|
90
drivers/scsi/bfa/bfa_module.c
Normal file
90
drivers/scsi/bfa/bfa_module.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <defs/bfa_defs_pci.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
#include <bfa_iocfc.h>
|
||||
|
||||
/**
|
||||
* BFA module list terminated by NULL
|
||||
*/
|
||||
struct bfa_module_s *hal_mods[] = {
|
||||
&hal_mod_sgpg,
|
||||
&hal_mod_pport,
|
||||
&hal_mod_fcxp,
|
||||
&hal_mod_lps,
|
||||
&hal_mod_uf,
|
||||
&hal_mod_rport,
|
||||
&hal_mod_fcpim,
|
||||
#ifdef BFA_CFG_PBIND
|
||||
&hal_mod_pbind,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* Message handlers for various modules.
|
||||
*/
|
||||
bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
|
||||
bfa_isr_unhandled, /* NONE */
|
||||
bfa_isr_unhandled, /* BFI_MC_IOC */
|
||||
bfa_isr_unhandled, /* BFI_MC_DIAG */
|
||||
bfa_isr_unhandled, /* BFI_MC_FLASH */
|
||||
bfa_isr_unhandled, /* BFI_MC_CEE */
|
||||
bfa_pport_isr, /* BFI_MC_PORT */
|
||||
bfa_isr_unhandled, /* BFI_MC_IOCFC */
|
||||
bfa_isr_unhandled, /* BFI_MC_LL */
|
||||
bfa_uf_isr, /* BFI_MC_UF */
|
||||
bfa_fcxp_isr, /* BFI_MC_FCXP */
|
||||
bfa_lps_isr, /* BFI_MC_LPS */
|
||||
bfa_rport_isr, /* BFI_MC_RPORT */
|
||||
bfa_itnim_isr, /* BFI_MC_ITNIM */
|
||||
bfa_isr_unhandled, /* BFI_MC_IOIM_READ */
|
||||
bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */
|
||||
bfa_isr_unhandled, /* BFI_MC_IOIM_IO */
|
||||
bfa_ioim_isr, /* BFI_MC_IOIM */
|
||||
bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */
|
||||
bfa_tskim_isr, /* BFI_MC_TSKIM */
|
||||
bfa_isr_unhandled, /* BFI_MC_SBOOT */
|
||||
bfa_isr_unhandled, /* BFI_MC_IPFC */
|
||||
bfa_isr_unhandled, /* BFI_MC_PORT */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
bfa_isr_unhandled, /* --------- */
|
||||
};
|
||||
|
||||
/**
|
||||
* Message handlers for mailbox command classes
|
||||
*/
|
||||
bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
|
||||
NULL,
|
||||
NULL, /* BFI_MC_IOC */
|
||||
NULL, /* BFI_MC_DIAG */
|
||||
NULL, /* BFI_MC_FLASH */
|
||||
NULL, /* BFI_MC_CEE */
|
||||
NULL, /* BFI_MC_PORT */
|
||||
bfa_iocfc_isr, /* BFI_MC_IOCFC */
|
||||
NULL,
|
||||
};
|
||||
|
43
drivers/scsi/bfa/bfa_modules_priv.h
Normal file
43
drivers/scsi/bfa/bfa_modules_priv.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_MODULES_PRIV_H__
|
||||
#define __BFA_MODULES_PRIV_H__
|
||||
|
||||
#include "bfa_uf_priv.h"
|
||||
#include "bfa_port_priv.h"
|
||||
#include "bfa_rport_priv.h"
|
||||
#include "bfa_fcxp_priv.h"
|
||||
#include "bfa_lps_priv.h"
|
||||
#include "bfa_fcpim_priv.h"
|
||||
#include <cee/bfa_cee.h>
|
||||
#include <port/bfa_port.h>
|
||||
|
||||
|
||||
struct bfa_modules_s {
|
||||
struct bfa_pport_s pport; /* physical port module */
|
||||
struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */
|
||||
struct bfa_lps_mod_s lps_mod; /* fcxp module */
|
||||
struct bfa_uf_mod_s uf_mod; /* unsolicited frame module */
|
||||
struct bfa_rport_mod_s rport_mod; /* remote port module */
|
||||
struct bfa_fcpim_mod_s fcpim_mod; /* FCP initiator module */
|
||||
struct bfa_sgpg_mod_s sgpg_mod; /* SG page module */
|
||||
struct bfa_cee_s cee; /* CEE Module */
|
||||
struct bfa_port_s port; /* Physical port module */
|
||||
};
|
||||
|
||||
#endif /* __BFA_MODULES_PRIV_H__ */
|
222
drivers/scsi/bfa/bfa_os_inc.h
Normal file
222
drivers/scsi/bfa/bfa_os_inc.h
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains declarations all OS Specific files needed for BFA layer
|
||||
*/
|
||||
|
||||
#ifndef __BFA_OS_INC_H__
|
||||
#define __BFA_OS_INC_H__
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#define SET_MODULE_VERSION(VER)
|
||||
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
|
||||
#define BFA_ERR KERN_ERR
|
||||
#define BFA_WARNING KERN_WARNING
|
||||
#define BFA_NOTICE KERN_NOTICE
|
||||
#define BFA_INFO KERN_INFO
|
||||
#define BFA_DEBUG KERN_DEBUG
|
||||
|
||||
#define LOG_BFAD_INIT 0x00000001
|
||||
#define LOG_FCP_IO 0x00000002
|
||||
|
||||
#ifdef DEBUG
|
||||
#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...) \
|
||||
BFA_LOG(bfad, level, mask, fmt, ## arg)
|
||||
#define BFA_DEV_TRACE(bfad, level, fmt, arg...) \
|
||||
BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
|
||||
#define BFA_TRACE(level, fmt, arg...) \
|
||||
BFA_PRINTF(level, fmt, ## arg)
|
||||
#else
|
||||
#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)
|
||||
#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
|
||||
#define BFA_TRACE(level, fmt, arg...)
|
||||
#endif
|
||||
|
||||
#define BFA_ASSERT(p) do { \
|
||||
if (!(p)) { \
|
||||
printk(KERN_ERR "assert(%s) failed at %s:%d\n", \
|
||||
#p, __FILE__, __LINE__); \
|
||||
BUG(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define BFA_LOG(bfad, level, mask, fmt, arg...) \
|
||||
do { \
|
||||
if (((mask) & (((struct bfad_s *)(bfad))-> \
|
||||
cfg_data[cfg_log_mask])) || (level[1] <= '3')) \
|
||||
dev_printk(level, &(((struct bfad_s *) \
|
||||
(bfad))->pcidev->dev), fmt, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#ifndef BFA_DEV_PRINTF
|
||||
#define BFA_DEV_PRINTF(bfad, level, fmt, arg...) \
|
||||
dev_printk(level, &(((struct bfad_s *) \
|
||||
(bfad))->pcidev->dev), fmt, ##arg);
|
||||
#endif
|
||||
|
||||
#define BFA_PRINTF(level, fmt, arg...) \
|
||||
printk(level fmt, ##arg);
|
||||
|
||||
int bfa_os_MWB(void *);
|
||||
|
||||
#define bfa_os_mmiowb() mmiowb()
|
||||
|
||||
#define bfa_swap_3b(_x) \
|
||||
((((_x) & 0xff) << 16) | \
|
||||
((_x) & 0x00ff00) | \
|
||||
(((_x) & 0xff0000) >> 16))
|
||||
|
||||
#define bfa_swap_8b(_x) \
|
||||
((((_x) & 0xff00000000000000ull) >> 56) \
|
||||
| (((_x) & 0x00ff000000000000ull) >> 40) \
|
||||
| (((_x) & 0x0000ff0000000000ull) >> 24) \
|
||||
| (((_x) & 0x000000ff00000000ull) >> 8) \
|
||||
| (((_x) & 0x00000000ff000000ull) << 8) \
|
||||
| (((_x) & 0x0000000000ff0000ull) << 24) \
|
||||
| (((_x) & 0x000000000000ff00ull) << 40) \
|
||||
| (((_x) & 0x00000000000000ffull) << 56))
|
||||
|
||||
#define bfa_os_swap32(_x) \
|
||||
((((_x) & 0xff) << 24) | \
|
||||
(((_x) & 0x0000ff00) << 8) | \
|
||||
(((_x) & 0x00ff0000) >> 8) | \
|
||||
(((_x) & 0xff000000) >> 24))
|
||||
|
||||
|
||||
#ifndef __BIGENDIAN
|
||||
#define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
|
||||
(((_x) & 0x00ff) << 8)))
|
||||
|
||||
#define bfa_os_htonl(_x) bfa_os_swap32(_x)
|
||||
#define bfa_os_htonll(_x) bfa_swap_8b(_x)
|
||||
#define bfa_os_hton3b(_x) bfa_swap_3b(_x)
|
||||
|
||||
#define bfa_os_wtole(_x) (_x)
|
||||
|
||||
#else
|
||||
|
||||
#define bfa_os_htons(_x) (_x)
|
||||
#define bfa_os_htonl(_x) (_x)
|
||||
#define bfa_os_hton3b(_x) (_x)
|
||||
#define bfa_os_htonll(_x) (_x)
|
||||
#define bfa_os_wtole(_x) bfa_os_swap32(_x)
|
||||
|
||||
#endif
|
||||
|
||||
#define bfa_os_ntohs(_x) bfa_os_htons(_x)
|
||||
#define bfa_os_ntohl(_x) bfa_os_htonl(_x)
|
||||
#define bfa_os_ntohll(_x) bfa_os_htonll(_x)
|
||||
#define bfa_os_ntoh3b(_x) bfa_os_hton3b(_x)
|
||||
|
||||
#define bfa_os_u32(__pa64) ((__pa64) >> 32)
|
||||
|
||||
#define bfa_os_memset memset
|
||||
#define bfa_os_memcpy memcpy
|
||||
#define bfa_os_udelay udelay
|
||||
#define bfa_os_vsprintf vsprintf
|
||||
|
||||
#define bfa_os_assign(__t, __s) __t = __s
|
||||
|
||||
#define bfa_os_addr_t char __iomem *
|
||||
#define bfa_os_panic()
|
||||
|
||||
#define bfa_os_reg_read(_raddr) bfa_os_wtole(readl(_raddr))
|
||||
#define bfa_os_reg_write(_raddr, _val) writel(bfa_os_wtole((_val)), (_raddr))
|
||||
#define bfa_os_mem_read(_raddr, _off) \
|
||||
bfa_os_ntohl(readl(((_raddr) + (_off))))
|
||||
#define bfa_os_mem_write(_raddr, _off, _val) \
|
||||
writel(bfa_os_htonl((_val)), ((_raddr) + (_off)))
|
||||
|
||||
#define BFA_TRC_TS(_trcm) \
|
||||
({ \
|
||||
struct timeval tv; \
|
||||
\
|
||||
do_gettimeofday(&tv); \
|
||||
(tv.tv_sec*1000000+tv.tv_usec); \
|
||||
})
|
||||
|
||||
struct bfa_log_mod_s;
|
||||
void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#define boolean_t int
|
||||
|
||||
/**
|
||||
* For current time stamp, OS API will fill-in
|
||||
*/
|
||||
struct bfa_timeval_s {
|
||||
u32 tv_sec; /* seconds */
|
||||
u32 tv_usec; /* microseconds */
|
||||
};
|
||||
|
||||
void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
|
||||
|
||||
static inline void
|
||||
wwn2str(char *wwn_str, u64 wwn)
|
||||
{
|
||||
union {
|
||||
u64 wwn;
|
||||
u8 byte[8];
|
||||
} w;
|
||||
|
||||
w.wwn = wwn;
|
||||
sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
|
||||
w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
|
||||
w.byte[6], w.byte[7]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fcid2str(char *fcid_str, u32 fcid)
|
||||
{
|
||||
union {
|
||||
u32 fcid;
|
||||
u8 byte[4];
|
||||
} f;
|
||||
|
||||
f.fcid = fcid;
|
||||
sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
|
||||
}
|
||||
|
||||
#endif /* __BFA_OS_INC_H__ */
|
460
drivers/scsi/bfa/bfa_port.c
Normal file
460
drivers/scsi/bfa/bfa_port.c
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <defs/bfa_defs_port.h>
|
||||
#include <cs/bfa_trc.h>
|
||||
#include <cs/bfa_log.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
#include <port/bfa_port.h>
|
||||
#include <bfi/bfi.h>
|
||||
#include <bfi/bfi_port.h>
|
||||
#include <bfa_ioc.h>
|
||||
#include <cna/bfa_cna_trcmod.h>
|
||||
|
||||
BFA_TRC_FILE(CNA, PORT);
|
||||
|
||||
#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
|
||||
#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
|
||||
|
||||
static void
|
||||
bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
|
||||
{
|
||||
u32 *dip = (u32 *) stats;
|
||||
u32 t0, t1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32);
|
||||
i += 2) {
|
||||
t0 = dip[i];
|
||||
t1 = dip[i + 1];
|
||||
#ifdef __BIGENDIAN
|
||||
dip[i] = bfa_os_ntohl(t0);
|
||||
dip[i + 1] = bfa_os_ntohl(t1);
|
||||
#else
|
||||
dip[i] = bfa_os_ntohl(t1);
|
||||
dip[i + 1] = bfa_os_ntohl(t0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** todo
|
||||
* QoS stats r also swapped as 64bit; that structure also
|
||||
* has to use 64 bit counters
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_enable_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the port module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
|
||||
{
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_disable_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the port module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
|
||||
{
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_get_stats_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the Port module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)
|
||||
{
|
||||
port->stats_status = status;
|
||||
port->stats_busy = BFA_FALSE;
|
||||
|
||||
if (status == BFA_STATUS_OK) {
|
||||
memcpy(port->stats, port->stats_dma.kva,
|
||||
sizeof(union bfa_pport_stats_u));
|
||||
bfa_port_stats_swap(port, port->stats);
|
||||
}
|
||||
|
||||
if (port->stats_cbfn) {
|
||||
port->stats_cbfn(port->stats_cbarg, status);
|
||||
port->stats_cbfn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_clear_stats_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the Port module
|
||||
* status - Return status from the f/w
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
|
||||
{
|
||||
port->stats_status = status;
|
||||
port->stats_busy = BFA_FALSE;
|
||||
|
||||
if (port->stats_cbfn) {
|
||||
port->stats_cbfn(port->stats_cbarg, status);
|
||||
port->stats_cbfn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_isr()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void
|
||||
bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
|
||||
{
|
||||
struct bfa_port_s *port = (struct bfa_port_s *)cbarg;
|
||||
union bfi_port_i2h_msg_u *i2hmsg;
|
||||
|
||||
i2hmsg = (union bfi_port_i2h_msg_u *)m;
|
||||
bfa_trc(port, m->mh.msg_id);
|
||||
|
||||
switch (m->mh.msg_id) {
|
||||
case BFI_PORT_I2H_ENABLE_RSP:
|
||||
if (port->endis_pending == BFA_FALSE)
|
||||
break;
|
||||
bfa_port_enable_isr(port, i2hmsg->enable_rsp.status);
|
||||
break;
|
||||
|
||||
case BFI_PORT_I2H_DISABLE_RSP:
|
||||
if (port->endis_pending == BFA_FALSE)
|
||||
break;
|
||||
bfa_port_disable_isr(port, i2hmsg->disable_rsp.status);
|
||||
break;
|
||||
|
||||
case BFI_PORT_I2H_GET_STATS_RSP:
|
||||
/*
|
||||
* Stats busy flag is still set? (may be cmd timed out)
|
||||
*/
|
||||
if (port->stats_busy == BFA_FALSE)
|
||||
break;
|
||||
bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
|
||||
break;
|
||||
|
||||
case BFI_PORT_I2H_CLEAR_STATS_RSP:
|
||||
if (port->stats_busy == BFA_FALSE)
|
||||
break;
|
||||
bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_meminfo()
|
||||
*
|
||||
*
|
||||
* @param[in] void
|
||||
*
|
||||
* @return Size of DMA region
|
||||
*/
|
||||
u32
|
||||
bfa_port_meminfo(void)
|
||||
{
|
||||
return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_mem_claim()
|
||||
*
|
||||
*
|
||||
* @param[in] port Port module pointer
|
||||
* dma_kva Kernel Virtual Address of Port DMA Memory
|
||||
* dma_pa Physical Address of Port DMA Memory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
|
||||
{
|
||||
port->stats_dma.kva = dma_kva;
|
||||
port->stats_dma.pa = dma_pa;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_enable()
|
||||
*
|
||||
* Send the Port enable request to the f/w
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
|
||||
void *cbarg)
|
||||
{
|
||||
struct bfi_port_generic_req_s *m;
|
||||
|
||||
/** todo Not implemented */
|
||||
bfa_assert(0);
|
||||
|
||||
if (!bfa_ioc_is_operational(port->ioc)) {
|
||||
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
|
||||
if (port->endis_pending) {
|
||||
bfa_trc(port, BFA_STATUS_DEVBUSY);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
|
||||
m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
|
||||
|
||||
port->msgtag++;
|
||||
port->endis_cbfn = cbfn;
|
||||
port->endis_cbarg = cbarg;
|
||||
port->endis_pending = BFA_TRUE;
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
|
||||
bfa_ioc_portid(port->ioc));
|
||||
bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_disable()
|
||||
*
|
||||
* Send the Port disable request to the f/w
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
|
||||
void *cbarg)
|
||||
{
|
||||
struct bfi_port_generic_req_s *m;
|
||||
|
||||
/** todo Not implemented */
|
||||
bfa_assert(0);
|
||||
|
||||
if (!bfa_ioc_is_operational(port->ioc)) {
|
||||
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
|
||||
if (port->endis_pending) {
|
||||
bfa_trc(port, BFA_STATUS_DEVBUSY);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
|
||||
m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
|
||||
|
||||
port->msgtag++;
|
||||
port->endis_cbfn = cbfn;
|
||||
port->endis_cbarg = cbarg;
|
||||
port->endis_pending = BFA_TRUE;
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
|
||||
bfa_ioc_portid(port->ioc));
|
||||
bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_get_stats()
|
||||
*
|
||||
* Send the request to the f/w to fetch Port statistics.
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
|
||||
bfa_port_stats_cbfn_t cbfn, void *cbarg)
|
||||
{
|
||||
struct bfi_port_get_stats_req_s *m;
|
||||
|
||||
if (!bfa_ioc_is_operational(port->ioc)) {
|
||||
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
|
||||
if (port->stats_busy) {
|
||||
bfa_trc(port, BFA_STATUS_DEVBUSY);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
|
||||
m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg;
|
||||
|
||||
port->stats = stats;
|
||||
port->stats_cbfn = cbfn;
|
||||
port->stats_cbarg = cbarg;
|
||||
port->stats_busy = BFA_TRUE;
|
||||
bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
|
||||
bfa_ioc_portid(port->ioc));
|
||||
bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_clear_stats()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
|
||||
void *cbarg)
|
||||
{
|
||||
struct bfi_port_generic_req_s *m;
|
||||
|
||||
if (!bfa_ioc_is_operational(port->ioc)) {
|
||||
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
|
||||
return BFA_STATUS_IOC_FAILURE;
|
||||
}
|
||||
|
||||
if (port->stats_busy) {
|
||||
bfa_trc(port, BFA_STATUS_DEVBUSY);
|
||||
return BFA_STATUS_DEVBUSY;
|
||||
}
|
||||
|
||||
m = (struct bfi_port_generic_req_s *)port->stats_mb.msg;
|
||||
|
||||
port->stats_cbfn = cbfn;
|
||||
port->stats_cbarg = cbarg;
|
||||
port->stats_busy = BFA_TRUE;
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
|
||||
bfa_ioc_portid(port->ioc));
|
||||
bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_hbfail()
|
||||
*
|
||||
*
|
||||
* @param[in] Pointer to the Port module data structure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_port_hbfail(void *arg)
|
||||
{
|
||||
struct bfa_port_s *port = (struct bfa_port_s *)arg;
|
||||
|
||||
/*
|
||||
* Fail any pending get_stats/clear_stats requests
|
||||
*/
|
||||
if (port->stats_busy) {
|
||||
if (port->stats_cbfn)
|
||||
port->stats_cbfn(port->dev, BFA_STATUS_FAILED);
|
||||
port->stats_cbfn = NULL;
|
||||
port->stats_busy = BFA_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear any enable/disable is pending
|
||||
*/
|
||||
if (port->endis_pending) {
|
||||
if (port->endis_cbfn)
|
||||
port->endis_cbfn(port->dev, BFA_STATUS_FAILED);
|
||||
port->endis_cbfn = NULL;
|
||||
port->endis_pending = BFA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_attach()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the Port module data structure
|
||||
* ioc - Pointer to the ioc module data structure
|
||||
* dev - Pointer to the device driver module data structure
|
||||
* The device driver specific mbox ISR functions have
|
||||
* this pointer as one of the parameters.
|
||||
* trcmod -
|
||||
* logmod -
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev,
|
||||
struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
|
||||
{
|
||||
bfa_assert(port);
|
||||
|
||||
port->dev = dev;
|
||||
port->ioc = ioc;
|
||||
port->trcmod = trcmod;
|
||||
port->logmod = logmod;
|
||||
|
||||
port->stats_busy = port->endis_pending = BFA_FALSE;
|
||||
port->stats_cbfn = port->endis_cbfn = NULL;
|
||||
|
||||
bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
|
||||
bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port);
|
||||
bfa_ioc_hbfail_register(port->ioc, &port->hbfail);
|
||||
|
||||
bfa_trc(port, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfa_port_detach()
|
||||
*
|
||||
*
|
||||
* @param[in] port - Pointer to the Port module data structure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void
|
||||
bfa_port_detach(struct bfa_port_s *port)
|
||||
{
|
||||
bfa_trc(port, 0);
|
||||
}
|
90
drivers/scsi/bfa/bfa_port_priv.h
Normal file
90
drivers/scsi/bfa/bfa_port_priv.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_PORT_PRIV_H__
|
||||
#define __BFA_PORT_PRIV_H__
|
||||
|
||||
#include <defs/bfa_defs_pport.h>
|
||||
#include <bfi/bfi_pport.h>
|
||||
#include "bfa_intr_priv.h"
|
||||
|
||||
/**
|
||||
* BFA physical port data structure
|
||||
*/
|
||||
struct bfa_pport_s {
|
||||
struct bfa_s *bfa; /* parent BFA instance */
|
||||
bfa_sm_t sm; /* port state machine */
|
||||
wwn_t nwwn; /* node wwn of physical port */
|
||||
wwn_t pwwn; /* port wwn of physical oprt */
|
||||
enum bfa_pport_speed speed_sup;
|
||||
/* supported speeds */
|
||||
enum bfa_pport_speed speed; /* current speed */
|
||||
enum bfa_pport_topology topology; /* current topology */
|
||||
u8 myalpa; /* my ALPA in LOOP topology */
|
||||
u8 rsvd[3];
|
||||
struct bfa_pport_cfg_s cfg; /* current port configuration */
|
||||
struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
|
||||
struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
|
||||
struct bfa_reqq_wait_s reqq_wait;
|
||||
/* to wait for room in reqq */
|
||||
struct bfa_reqq_wait_s svcreq_wait;
|
||||
/* to wait for room in reqq */
|
||||
struct bfa_reqq_wait_s stats_reqq_wait;
|
||||
/* to wait for room in reqq (stats) */
|
||||
void *event_cbarg;
|
||||
void (*event_cbfn) (void *cbarg,
|
||||
bfa_pport_event_t event);
|
||||
union {
|
||||
union bfi_pport_i2h_msg_u i2hmsg;
|
||||
} event_arg;
|
||||
void *bfad; /* BFA driver handle */
|
||||
struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */
|
||||
enum bfa_pport_linkstate hcb_event;
|
||||
/* link event for callback */
|
||||
u32 msgtag; /* fimrware msg tag for reply */
|
||||
u8 *stats_kva;
|
||||
u64 stats_pa;
|
||||
union bfa_pport_stats_u *stats; /* pport stats */
|
||||
u32 mypid : 24;
|
||||
u32 rsvd_b : 8;
|
||||
struct bfa_timer_s timer; /* timer */
|
||||
union bfa_pport_stats_u *stats_ret;
|
||||
/* driver stats location */
|
||||
bfa_status_t stats_status;
|
||||
/* stats/statsclr status */
|
||||
bfa_boolean_t stats_busy;
|
||||
/* outstanding stats/statsclr */
|
||||
bfa_boolean_t stats_qfull;
|
||||
bfa_boolean_t diag_busy;
|
||||
/* diag busy status */
|
||||
bfa_boolean_t beacon;
|
||||
/* port beacon status */
|
||||
bfa_boolean_t link_e2e_beacon;
|
||||
/* link beacon status */
|
||||
bfa_cb_pport_t stats_cbfn;
|
||||
/* driver callback function */
|
||||
void *stats_cbarg;
|
||||
/* *!< user callback arg */
|
||||
};
|
||||
|
||||
#define BFA_PORT_MOD(__bfa) (&(__bfa)->modules.pport)
|
||||
|
||||
/*
|
||||
* public functions
|
||||
*/
|
||||
void bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
#endif /* __BFA_PORT_PRIV_H__ */
|
113
drivers/scsi/bfa/bfa_priv.h
Normal file
113
drivers/scsi/bfa/bfa_priv.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_PRIV_H__
|
||||
#define __BFA_PRIV_H__
|
||||
|
||||
#include "bfa_iocfc.h"
|
||||
#include "bfa_intr_priv.h"
|
||||
#include "bfa_trcmod_priv.h"
|
||||
#include "bfa_modules_priv.h"
|
||||
#include "bfa_fwimg_priv.h"
|
||||
#include <cs/bfa_log.h>
|
||||
#include <bfa_timer.h>
|
||||
|
||||
/**
|
||||
* Macro to define a new BFA module
|
||||
*/
|
||||
#define BFA_MODULE(__mod) \
|
||||
static void bfa_ ## __mod ## _meminfo( \
|
||||
struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, \
|
||||
u32 *dm_len); \
|
||||
static void bfa_ ## __mod ## _attach(struct bfa_s *bfa, \
|
||||
void *bfad, struct bfa_iocfc_cfg_s *cfg, \
|
||||
struct bfa_meminfo_s *meminfo, \
|
||||
struct bfa_pcidev_s *pcidev); \
|
||||
static void bfa_ ## __mod ## _initdone(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _stop(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa); \
|
||||
\
|
||||
extern struct bfa_module_s hal_mod_ ## __mod; \
|
||||
struct bfa_module_s hal_mod_ ## __mod = { \
|
||||
bfa_ ## __mod ## _meminfo, \
|
||||
bfa_ ## __mod ## _attach, \
|
||||
bfa_ ## __mod ## _initdone, \
|
||||
bfa_ ## __mod ## _detach, \
|
||||
bfa_ ## __mod ## _start, \
|
||||
bfa_ ## __mod ## _stop, \
|
||||
bfa_ ## __mod ## _iocdisable, \
|
||||
}
|
||||
|
||||
#define BFA_CACHELINE_SZ (256)
|
||||
|
||||
/**
|
||||
* Structure used to interact between different BFA sub modules
|
||||
*
|
||||
* Each sub module needs to implement only the entry points relevant to it (and
|
||||
* can leave entry points as NULL)
|
||||
*/
|
||||
struct bfa_module_s {
|
||||
void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len);
|
||||
void (*attach) (struct bfa_s *bfa, void *bfad,
|
||||
struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_pcidev_s *pcidev);
|
||||
void (*initdone) (struct bfa_s *bfa);
|
||||
void (*detach) (struct bfa_s *bfa);
|
||||
void (*start) (struct bfa_s *bfa);
|
||||
void (*stop) (struct bfa_s *bfa);
|
||||
void (*iocdisable) (struct bfa_s *bfa);
|
||||
};
|
||||
|
||||
extern struct bfa_module_s *hal_mods[];
|
||||
|
||||
struct bfa_s {
|
||||
void *bfad; /* BFA driver instance */
|
||||
struct bfa_aen_s *aen; /* AEN module */
|
||||
struct bfa_plog_s *plog; /* portlog buffer */
|
||||
struct bfa_log_mod_s *logm; /* driver logging modulen */
|
||||
struct bfa_trc_mod_s *trcmod; /* driver tracing */
|
||||
struct bfa_ioc_s ioc; /* IOC module */
|
||||
struct bfa_iocfc_s iocfc; /* IOCFC module */
|
||||
struct bfa_timer_mod_s timer_mod; /* timer module */
|
||||
struct bfa_modules_s modules; /* BFA modules */
|
||||
struct list_head comp_q; /* pending completions */
|
||||
bfa_boolean_t rme_process; /* RME processing enabled */
|
||||
struct list_head reqq_waitq[BFI_IOC_MAX_CQS];
|
||||
bfa_boolean_t fcs; /* FCS is attached to BFA */
|
||||
struct bfa_msix_s msix;
|
||||
};
|
||||
|
||||
extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
|
||||
extern bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[];
|
||||
extern bfa_boolean_t bfa_auto_recover;
|
||||
extern struct bfa_module_s hal_mod_flash;
|
||||
extern struct bfa_module_s hal_mod_fcdiag;
|
||||
extern struct bfa_module_s hal_mod_sgpg;
|
||||
extern struct bfa_module_s hal_mod_pport;
|
||||
extern struct bfa_module_s hal_mod_fcxp;
|
||||
extern struct bfa_module_s hal_mod_lps;
|
||||
extern struct bfa_module_s hal_mod_uf;
|
||||
extern struct bfa_module_s hal_mod_rport;
|
||||
extern struct bfa_module_s hal_mod_fcpim;
|
||||
extern struct bfa_module_s hal_mod_pbind;
|
||||
|
||||
#endif /* __BFA_PRIV_H__ */
|
||||
|
911
drivers/scsi/bfa/bfa_rport.c
Normal file
911
drivers/scsi/bfa/bfa_rport.c
Normal file
@ -0,0 +1,911 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
#include <bfi/bfi_rport.h>
|
||||
#include "bfa_intr_priv.h"
|
||||
|
||||
BFA_TRC_FILE(HAL, RPORT);
|
||||
BFA_MODULE(rport);
|
||||
|
||||
#define bfa_rport_offline_cb(__rp) do { \
|
||||
if ((__rp)->bfa->fcs) \
|
||||
bfa_cb_rport_offline((__rp)->rport_drv); \
|
||||
else { \
|
||||
bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
|
||||
__bfa_cb_rport_offline, (__rp)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define bfa_rport_online_cb(__rp) do { \
|
||||
if ((__rp)->bfa->fcs) \
|
||||
bfa_cb_rport_online((__rp)->rport_drv); \
|
||||
else { \
|
||||
bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
|
||||
__bfa_cb_rport_online, (__rp)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* forward declarations
|
||||
*/
|
||||
static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
|
||||
static void bfa_rport_free(struct bfa_rport_s *rport);
|
||||
static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
|
||||
static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
|
||||
static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
|
||||
static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete);
|
||||
static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete);
|
||||
|
||||
/**
|
||||
* bfa_rport_sm BFA rport state machine
|
||||
*/
|
||||
|
||||
|
||||
enum bfa_rport_event {
|
||||
BFA_RPORT_SM_CREATE = 1, /* rport create event */
|
||||
BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */
|
||||
BFA_RPORT_SM_ONLINE = 3, /* rport is online */
|
||||
BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */
|
||||
BFA_RPORT_SM_FWRSP = 5, /* firmware response */
|
||||
BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */
|
||||
BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */
|
||||
BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */
|
||||
BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */
|
||||
};
|
||||
|
||||
static void bfa_rport_sm_uninit(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_created(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_online(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_offline(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_deleting(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
static void bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event);
|
||||
|
||||
/**
|
||||
* Beginning state, only online event expected.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_CREATE:
|
||||
bfa_stats(rp, sm_un_cr);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_created);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_un_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_ONLINE:
|
||||
bfa_stats(rp, sm_cr_on);
|
||||
if (bfa_rport_send_fwcreate(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_cr_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_cr_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_cr_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waiting for rport create response from firmware.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_FWRSP:
|
||||
bfa_stats(rp, sm_fwc_rsp);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_online);
|
||||
bfa_rport_online_cb(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_fwc_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_OFFLINE:
|
||||
bfa_stats(rp, sm_fwc_off);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_fwc_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_fwc_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request queue is full, awaiting queue resume to send create request.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_QRESUME:
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
|
||||
bfa_rport_send_fwcreate(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_fwc_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_reqq_wcancel(&rp->reqq_wait);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_OFFLINE:
|
||||
bfa_stats(rp, sm_fwc_off);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_offline);
|
||||
bfa_reqq_wcancel(&rp->reqq_wait);
|
||||
bfa_rport_offline_cb(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_fwc_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
bfa_reqq_wcancel(&rp->reqq_wait);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_fwc_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Online state - normal parking state.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
struct bfi_rport_qos_scn_s *qos_scn;
|
||||
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_OFFLINE:
|
||||
bfa_stats(rp, sm_on_off);
|
||||
if (bfa_rport_send_fwdelete(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_on_del);
|
||||
if (bfa_rport_send_fwdelete(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_on_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_SET_SPEED:
|
||||
bfa_rport_send_fwspeed(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_QOS_SCN:
|
||||
qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
|
||||
rp->qos_attr = qos_scn->new_qos_attr;
|
||||
bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
|
||||
bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
|
||||
bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
|
||||
bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
|
||||
|
||||
qos_scn->old_qos_attr.qos_flow_id =
|
||||
bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
|
||||
qos_scn->new_qos_attr.qos_flow_id =
|
||||
bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
|
||||
qos_scn->old_qos_attr.qos_priority =
|
||||
bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority);
|
||||
qos_scn->new_qos_attr.qos_priority =
|
||||
bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority);
|
||||
|
||||
if (qos_scn->old_qos_attr.qos_flow_id !=
|
||||
qos_scn->new_qos_attr.qos_flow_id)
|
||||
bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
|
||||
qos_scn->old_qos_attr,
|
||||
qos_scn->new_qos_attr);
|
||||
if (qos_scn->old_qos_attr.qos_priority !=
|
||||
qos_scn->new_qos_attr.qos_priority)
|
||||
bfa_cb_rport_qos_scn_prio(rp->rport_drv,
|
||||
qos_scn->old_qos_attr,
|
||||
qos_scn->new_qos_attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_on_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Firmware rport is being deleted - awaiting f/w response.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_FWRSP:
|
||||
bfa_stats(rp, sm_fwd_rsp);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_offline);
|
||||
bfa_rport_offline_cb(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_fwd_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_fwd_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
bfa_rport_offline_cb(rp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_fwd_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_QRESUME:
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
|
||||
bfa_rport_send_fwdelete(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_fwd_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_fwd_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
bfa_reqq_wcancel(&rp->reqq_wait);
|
||||
bfa_rport_offline_cb(rp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_fwd_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offline state.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_off_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_ONLINE:
|
||||
bfa_stats(rp, sm_off_on);
|
||||
if (bfa_rport_send_fwcreate(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_off_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_off_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rport is deleted, waiting for firmware response to delete.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_FWRSP:
|
||||
bfa_stats(rp, sm_del_fwrsp);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_del_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_QRESUME:
|
||||
bfa_stats(rp, sm_del_fwrsp);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting);
|
||||
bfa_rport_send_fwdelete(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_del_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_reqq_wcancel(&rp->reqq_wait);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waiting for rport create response from firmware. A delete is pending.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_FWRSP:
|
||||
bfa_stats(rp, sm_delp_fwrsp);
|
||||
if (bfa_rport_send_fwdelete(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_delp_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_delp_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waiting for rport create response from firmware. Rport offline is pending.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
|
||||
enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_FWRSP:
|
||||
bfa_stats(rp, sm_offp_fwrsp);
|
||||
if (bfa_rport_send_fwdelete(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_offp_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
bfa_stats(rp, sm_offp_hwf);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_offp_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IOC h/w failed.
|
||||
*/
|
||||
static void
|
||||
bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
|
||||
{
|
||||
bfa_trc(rp->bfa, rp->rport_tag);
|
||||
bfa_trc(rp->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_RPORT_SM_OFFLINE:
|
||||
bfa_stats(rp, sm_iocd_off);
|
||||
bfa_rport_offline_cb(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_DELETE:
|
||||
bfa_stats(rp, sm_iocd_del);
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
bfa_rport_free(rp);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_ONLINE:
|
||||
bfa_stats(rp, sm_iocd_on);
|
||||
if (bfa_rport_send_fwcreate(rp))
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
|
||||
else
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
|
||||
break;
|
||||
|
||||
case BFA_RPORT_SM_HWFAIL:
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_stats(rp, sm_iocd_unexp);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_rport_private BFA rport private functions
|
||||
*/
|
||||
|
||||
static void
|
||||
__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_rport_s *rp = cbarg;
|
||||
|
||||
if (complete)
|
||||
bfa_cb_rport_online(rp->rport_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_rport_s *rp = cbarg;
|
||||
|
||||
if (complete)
|
||||
bfa_cb_rport_offline(rp->rport_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_qresume(void *cbarg)
|
||||
{
|
||||
struct bfa_rport_s *rp = cbarg;
|
||||
|
||||
bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len)
|
||||
{
|
||||
if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
|
||||
cfg->fwcfg.num_rports = BFA_RPORT_MIN;
|
||||
|
||||
*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
|
||||
struct bfa_rport_s *rp;
|
||||
u16 i;
|
||||
|
||||
INIT_LIST_HEAD(&mod->rp_free_q);
|
||||
INIT_LIST_HEAD(&mod->rp_active_q);
|
||||
|
||||
rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
|
||||
mod->rps_list = rp;
|
||||
mod->num_rports = cfg->fwcfg.num_rports;
|
||||
|
||||
bfa_assert(mod->num_rports
|
||||
&& !(mod->num_rports & (mod->num_rports - 1)));
|
||||
|
||||
for (i = 0; i < mod->num_rports; i++, rp++) {
|
||||
bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
|
||||
rp->bfa = bfa;
|
||||
rp->rport_tag = i;
|
||||
bfa_sm_set_state(rp, bfa_rport_sm_uninit);
|
||||
|
||||
/**
|
||||
* - is unused
|
||||
*/
|
||||
if (i)
|
||||
list_add_tail(&rp->qe, &mod->rp_free_q);
|
||||
|
||||
bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
|
||||
}
|
||||
|
||||
/**
|
||||
* consume memory
|
||||
*/
|
||||
bfa_meminfo_kva(meminfo) = (u8 *) rp;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
|
||||
struct bfa_rport_s *rport;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &mod->rp_active_q) {
|
||||
rport = (struct bfa_rport_s *) qe;
|
||||
bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bfa_rport_s *
|
||||
bfa_rport_alloc(struct bfa_rport_mod_s *mod)
|
||||
{
|
||||
struct bfa_rport_s *rport;
|
||||
|
||||
bfa_q_deq(&mod->rp_free_q, &rport);
|
||||
if (rport)
|
||||
list_add_tail(&rport->qe, &mod->rp_active_q);
|
||||
|
||||
return (rport);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_free(struct bfa_rport_s *rport)
|
||||
{
|
||||
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
|
||||
|
||||
bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
|
||||
list_del(&rport->qe);
|
||||
list_add_tail(&rport->qe, &mod->rp_free_q);
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
|
||||
{
|
||||
struct bfi_rport_create_req_s *m;
|
||||
|
||||
/**
|
||||
* check for room in queue to send request now
|
||||
*/
|
||||
m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
|
||||
if (!m) {
|
||||
bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
|
||||
return BFA_FALSE;
|
||||
}
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
|
||||
bfa_lpuid(rp->bfa));
|
||||
m->bfa_handle = rp->rport_tag;
|
||||
m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
|
||||
m->pid = rp->rport_info.pid;
|
||||
m->lp_tag = rp->rport_info.lp_tag;
|
||||
m->local_pid = rp->rport_info.local_pid;
|
||||
m->fc_class = rp->rport_info.fc_class;
|
||||
m->vf_en = rp->rport_info.vf_en;
|
||||
m->vf_id = rp->rport_info.vf_id;
|
||||
m->cisc = rp->rport_info.cisc;
|
||||
|
||||
/**
|
||||
* queue I/O message to firmware
|
||||
*/
|
||||
bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
|
||||
{
|
||||
struct bfi_rport_delete_req_s *m;
|
||||
|
||||
/**
|
||||
* check for room in queue to send request now
|
||||
*/
|
||||
m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
|
||||
if (!m) {
|
||||
bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
|
||||
return BFA_FALSE;
|
||||
}
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
|
||||
bfa_lpuid(rp->bfa));
|
||||
m->fw_handle = rp->fw_handle;
|
||||
|
||||
/**
|
||||
* queue I/O message to firmware
|
||||
*/
|
||||
bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
|
||||
{
|
||||
struct bfa_rport_speed_req_s *m;
|
||||
|
||||
/**
|
||||
* check for room in queue to send request now
|
||||
*/
|
||||
m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
|
||||
if (!m) {
|
||||
bfa_trc(rp->bfa, rp->rport_info.speed);
|
||||
return BFA_FALSE;
|
||||
}
|
||||
|
||||
bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
|
||||
bfa_lpuid(rp->bfa));
|
||||
m->fw_handle = rp->fw_handle;
|
||||
m->speed = (u8)rp->rport_info.speed;
|
||||
|
||||
/**
|
||||
* queue I/O message to firmware
|
||||
*/
|
||||
bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_rport_public
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rport interrupt processing.
|
||||
*/
|
||||
void
|
||||
bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
||||
{
|
||||
union bfi_rport_i2h_msg_u msg;
|
||||
struct bfa_rport_s *rp;
|
||||
|
||||
bfa_trc(bfa, m->mhdr.msg_id);
|
||||
|
||||
msg.msg = m;
|
||||
|
||||
switch (m->mhdr.msg_id) {
|
||||
case BFI_RPORT_I2H_CREATE_RSP:
|
||||
rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
|
||||
rp->fw_handle = msg.create_rsp->fw_handle;
|
||||
rp->qos_attr = msg.create_rsp->qos_attr;
|
||||
bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
|
||||
bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
|
||||
break;
|
||||
|
||||
case BFI_RPORT_I2H_DELETE_RSP:
|
||||
rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
|
||||
bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
|
||||
bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
|
||||
break;
|
||||
|
||||
case BFI_RPORT_I2H_QOS_SCN:
|
||||
rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
|
||||
rp->event_arg.fw_msg = msg.qos_scn_evt;
|
||||
bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_trc(bfa, m->mhdr.msg_id);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_rport_api
|
||||
*/
|
||||
|
||||
struct bfa_rport_s *
|
||||
bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
|
||||
{
|
||||
struct bfa_rport_s *rp;
|
||||
|
||||
rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
|
||||
|
||||
if (rp == NULL)
|
||||
return (NULL);
|
||||
|
||||
rp->bfa = bfa;
|
||||
rp->rport_drv = rport_drv;
|
||||
bfa_rport_clear_stats(rp);
|
||||
|
||||
bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
|
||||
bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
|
||||
|
||||
return (rp);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_delete(struct bfa_rport_s *rport)
|
||||
{
|
||||
bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
|
||||
{
|
||||
bfa_assert(rport_info->max_frmsz != 0);
|
||||
|
||||
/**
|
||||
* Some JBODs are seen to be not setting PDU size correctly in PLOGI
|
||||
* responses. Default to minimum size.
|
||||
*/
|
||||
if (rport_info->max_frmsz == 0) {
|
||||
bfa_trc(rport->bfa, rport->rport_tag);
|
||||
rport_info->max_frmsz = FC_MIN_PDUSZ;
|
||||
}
|
||||
|
||||
bfa_os_assign(rport->rport_info, *rport_info);
|
||||
bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_offline(struct bfa_rport_s *rport)
|
||||
{
|
||||
bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed)
|
||||
{
|
||||
bfa_assert(speed != 0);
|
||||
bfa_assert(speed != BFA_PPORT_SPEED_AUTO);
|
||||
|
||||
rport->rport_info.speed = speed;
|
||||
bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_get_stats(struct bfa_rport_s *rport,
|
||||
struct bfa_rport_hal_stats_s *stats)
|
||||
{
|
||||
*stats = rport->stats;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
|
||||
struct bfa_rport_qos_attr_s *qos_attr)
|
||||
{
|
||||
qos_attr->qos_priority = bfa_os_ntohl(rport->qos_attr.qos_priority);
|
||||
qos_attr->qos_flow_id = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
bfa_rport_clear_stats(struct bfa_rport_s *rport)
|
||||
{
|
||||
bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
|
||||
}
|
||||
|
||||
|
45
drivers/scsi/bfa/bfa_rport_priv.h
Normal file
45
drivers/scsi/bfa/bfa_rport_priv.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_RPORT_PRIV_H__
|
||||
#define __BFA_RPORT_PRIV_H__
|
||||
|
||||
#include <bfa_svc.h>
|
||||
|
||||
#define BFA_RPORT_MIN 4
|
||||
|
||||
struct bfa_rport_mod_s {
|
||||
struct bfa_rport_s *rps_list; /* list of rports */
|
||||
struct list_head rp_free_q; /* free bfa_rports */
|
||||
struct list_head rp_active_q; /* free bfa_rports */
|
||||
u16 num_rports; /* number of rports */
|
||||
};
|
||||
|
||||
#define BFA_RPORT_MOD(__bfa) (&(__bfa)->modules.rport_mod)
|
||||
|
||||
/**
|
||||
* Convert rport tag to RPORT
|
||||
*/
|
||||
#define BFA_RPORT_FROM_TAG(__bfa, _tag) \
|
||||
(BFA_RPORT_MOD(__bfa)->rps_list + \
|
||||
((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
|
||||
|
||||
/*
|
||||
* external functions
|
||||
*/
|
||||
void bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
#endif /* __BFA_RPORT_PRIV_H__ */
|
231
drivers/scsi/bfa/bfa_sgpg.c
Normal file
231
drivers/scsi/bfa/bfa_sgpg.c
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, SGPG);
|
||||
BFA_MODULE(sgpg);
|
||||
|
||||
/**
|
||||
* bfa_sgpg_mod BFA SGPG Mode module
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compute and return memory needed by FCP(im) module.
|
||||
*/
|
||||
static void
|
||||
bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
|
||||
u32 *dm_len)
|
||||
{
|
||||
if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
|
||||
cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
|
||||
|
||||
*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
|
||||
*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
|
||||
int i;
|
||||
struct bfa_sgpg_s *hsgpg;
|
||||
struct bfi_sgpg_s *sgpg;
|
||||
u64 align_len;
|
||||
|
||||
union {
|
||||
u64 pa;
|
||||
union bfi_addr_u addr;
|
||||
} sgpg_pa;
|
||||
|
||||
INIT_LIST_HEAD(&mod->sgpg_q);
|
||||
INIT_LIST_HEAD(&mod->sgpg_wait_q);
|
||||
|
||||
bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
|
||||
|
||||
mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
|
||||
mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
|
||||
align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
|
||||
mod->sgpg_arr_pa += align_len;
|
||||
mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
|
||||
align_len);
|
||||
mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
|
||||
align_len);
|
||||
|
||||
hsgpg = mod->hsgpg_arr;
|
||||
sgpg = mod->sgpg_arr;
|
||||
sgpg_pa.pa = mod->sgpg_arr_pa;
|
||||
mod->free_sgpgs = mod->num_sgpgs;
|
||||
|
||||
bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
|
||||
|
||||
for (i = 0; i < mod->num_sgpgs; i++) {
|
||||
bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
|
||||
bfa_os_memset(sgpg, 0, sizeof(*sgpg));
|
||||
|
||||
hsgpg->sgpg = sgpg;
|
||||
hsgpg->sgpg_pa = sgpg_pa.addr;
|
||||
list_add_tail(&hsgpg->qe, &mod->sgpg_q);
|
||||
|
||||
hsgpg++;
|
||||
sgpg++;
|
||||
sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
|
||||
}
|
||||
|
||||
bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
|
||||
bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
|
||||
bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_sgpg_public BFA SGPG public functions
|
||||
*/
|
||||
|
||||
bfa_status_t
|
||||
bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
|
||||
{
|
||||
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
|
||||
struct bfa_sgpg_s *hsgpg;
|
||||
int i;
|
||||
|
||||
bfa_trc_fp(bfa, nsgpgs);
|
||||
|
||||
if (mod->free_sgpgs < nsgpgs)
|
||||
return BFA_STATUS_ENOMEM;
|
||||
|
||||
for (i = 0; i < nsgpgs; i++) {
|
||||
bfa_q_deq(&mod->sgpg_q, &hsgpg);
|
||||
bfa_assert(hsgpg);
|
||||
list_add_tail(&hsgpg->qe, sgpg_q);
|
||||
}
|
||||
|
||||
mod->free_sgpgs -= nsgpgs;
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
|
||||
{
|
||||
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
|
||||
struct bfa_sgpg_wqe_s *wqe;
|
||||
|
||||
bfa_trc_fp(bfa, nsgpg);
|
||||
|
||||
mod->free_sgpgs += nsgpg;
|
||||
bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
|
||||
|
||||
list_splice_tail_init(sgpg_q, &mod->sgpg_q);
|
||||
|
||||
if (list_empty(&mod->sgpg_wait_q))
|
||||
return;
|
||||
|
||||
/**
|
||||
* satisfy as many waiting requests as possible
|
||||
*/
|
||||
do {
|
||||
wqe = bfa_q_first(&mod->sgpg_wait_q);
|
||||
if (mod->free_sgpgs < wqe->nsgpg)
|
||||
nsgpg = mod->free_sgpgs;
|
||||
else
|
||||
nsgpg = wqe->nsgpg;
|
||||
bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
|
||||
wqe->nsgpg -= nsgpg;
|
||||
if (wqe->nsgpg == 0) {
|
||||
list_del(&wqe->qe);
|
||||
wqe->cbfn(wqe->cbarg);
|
||||
}
|
||||
} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
|
||||
}
|
||||
|
||||
void
|
||||
bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
|
||||
{
|
||||
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
|
||||
|
||||
bfa_assert(nsgpg > 0);
|
||||
bfa_assert(nsgpg > mod->free_sgpgs);
|
||||
|
||||
wqe->nsgpg_total = wqe->nsgpg = nsgpg;
|
||||
|
||||
/**
|
||||
* allocate any left to this one first
|
||||
*/
|
||||
if (mod->free_sgpgs) {
|
||||
/**
|
||||
* no one else is waiting for SGPG
|
||||
*/
|
||||
bfa_assert(list_empty(&mod->sgpg_wait_q));
|
||||
list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
|
||||
wqe->nsgpg -= mod->free_sgpgs;
|
||||
mod->free_sgpgs = 0;
|
||||
}
|
||||
|
||||
list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
|
||||
{
|
||||
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
|
||||
|
||||
bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
|
||||
list_del(&wqe->qe);
|
||||
|
||||
if (wqe->nsgpg_total != wqe->nsgpg)
|
||||
bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
|
||||
wqe->nsgpg_total - wqe->nsgpg);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
|
||||
void *cbarg)
|
||||
{
|
||||
INIT_LIST_HEAD(&wqe->sgpg_q);
|
||||
wqe->cbfn = cbfn;
|
||||
wqe->cbarg = cbarg;
|
||||
}
|
||||
|
||||
|
79
drivers/scsi/bfa/bfa_sgpg_priv.h
Normal file
79
drivers/scsi/bfa/bfa_sgpg_priv.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* hal_sgpg.h BFA SG page module
|
||||
*/
|
||||
|
||||
#ifndef __BFA_SGPG_PRIV_H__
|
||||
#define __BFA_SGPG_PRIV_H__
|
||||
|
||||
#include <cs/bfa_q.h>
|
||||
|
||||
#define BFA_SGPG_MIN (16)
|
||||
|
||||
/**
|
||||
* Alignment macro for SG page allocation
|
||||
*/
|
||||
#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
|
||||
& ~(sizeof(struct bfi_sgpg_s) - 1))
|
||||
|
||||
struct bfa_sgpg_wqe_s {
|
||||
struct list_head qe; /* queue sg page element */
|
||||
int nsgpg; /* pages to be allocated */
|
||||
int nsgpg_total; /* total pages required */
|
||||
void (*cbfn) (void *cbarg);
|
||||
/* callback function */
|
||||
void *cbarg; /* callback arg */
|
||||
struct list_head sgpg_q; /* queue of alloced sgpgs */
|
||||
};
|
||||
|
||||
struct bfa_sgpg_s {
|
||||
struct list_head qe; /* queue sg page element */
|
||||
struct bfi_sgpg_s *sgpg; /* va of SG page */
|
||||
union bfi_addr_u sgpg_pa;/* pa of SG page */
|
||||
};
|
||||
|
||||
/**
|
||||
* Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
|
||||
* SG pages required.
|
||||
*/
|
||||
#define BFA_SGPG_NPAGE(_nsges) (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
|
||||
|
||||
struct bfa_sgpg_mod_s {
|
||||
struct bfa_s *bfa;
|
||||
int num_sgpgs; /* number of SG pages */
|
||||
int free_sgpgs; /* number of free SG pages */
|
||||
struct bfa_sgpg_s *hsgpg_arr; /* BFA SG page array */
|
||||
struct bfi_sgpg_s *sgpg_arr; /* actual SG page array */
|
||||
u64 sgpg_arr_pa; /* SG page array DMA addr */
|
||||
struct list_head sgpg_q; /* queue of free SG pages */
|
||||
struct list_head sgpg_wait_q; /* wait queue for SG pages */
|
||||
};
|
||||
#define BFA_SGPG_MOD(__bfa) (&(__bfa)->modules.sgpg_mod)
|
||||
|
||||
bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
|
||||
int nsgpgs);
|
||||
void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q,
|
||||
int nsgpgs);
|
||||
void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
|
||||
void (*cbfn) (void *cbarg), void *cbarg);
|
||||
void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe,
|
||||
int nsgpgs);
|
||||
void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
|
||||
|
||||
#endif /* __BFA_SGPG_PRIV_H__ */
|
38
drivers/scsi/bfa/bfa_sm.c
Normal file
38
drivers/scsi/bfa/bfa_sm.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfasm.c BFA State machine utility functions
|
||||
*/
|
||||
|
||||
#include <cs/bfa_sm.h>
|
||||
|
||||
/**
|
||||
* cs_sm_api
|
||||
*/
|
||||
|
||||
int
|
||||
bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (smt[i].sm && smt[i].sm != sm)
|
||||
i++;
|
||||
return smt[i].state;
|
||||
}
|
||||
|
||||
|
90
drivers/scsi/bfa/bfa_timer.c
Normal file
90
drivers/scsi/bfa/bfa_timer.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa_timer.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
|
||||
void
|
||||
bfa_timer_init(struct bfa_timer_mod_s *mod)
|
||||
{
|
||||
INIT_LIST_HEAD(&mod->timer_q);
|
||||
}
|
||||
|
||||
void
|
||||
bfa_timer_beat(struct bfa_timer_mod_s *mod)
|
||||
{
|
||||
struct list_head *qh = &mod->timer_q;
|
||||
struct list_head *qe, *qe_next;
|
||||
struct bfa_timer_s *elem;
|
||||
struct list_head timedout_q;
|
||||
|
||||
INIT_LIST_HEAD(&timedout_q);
|
||||
|
||||
qe = bfa_q_next(qh);
|
||||
|
||||
while (qe != qh) {
|
||||
qe_next = bfa_q_next(qe);
|
||||
|
||||
elem = (struct bfa_timer_s *) qe;
|
||||
if (elem->timeout <= BFA_TIMER_FREQ) {
|
||||
elem->timeout = 0;
|
||||
list_del(&elem->qe);
|
||||
list_add_tail(&elem->qe, &timedout_q);
|
||||
} else {
|
||||
elem->timeout -= BFA_TIMER_FREQ;
|
||||
}
|
||||
|
||||
qe = qe_next; /* go to next elem */
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop all the timeout entries
|
||||
*/
|
||||
while (!list_empty(&timedout_q)) {
|
||||
bfa_q_deq(&timedout_q, &elem);
|
||||
elem->timercb(elem->arg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called with lock protection
|
||||
*/
|
||||
void
|
||||
bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
|
||||
void (*timercb) (void *), void *arg, unsigned int timeout)
|
||||
{
|
||||
|
||||
bfa_assert(timercb != NULL);
|
||||
bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
|
||||
|
||||
timer->timeout = timeout;
|
||||
timer->timercb = timercb;
|
||||
timer->arg = arg;
|
||||
|
||||
list_add_tail(&timer->qe, &mod->timer_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called with lock protection
|
||||
*/
|
||||
void
|
||||
bfa_timer_stop(struct bfa_timer_s *timer)
|
||||
{
|
||||
bfa_assert(!list_empty(&timer->qe));
|
||||
|
||||
list_del(&timer->qe);
|
||||
}
|
66
drivers/scsi/bfa/bfa_trcmod_priv.h
Normal file
66
drivers/scsi/bfa/bfa_trcmod_priv.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* hal_trcmod.h BFA trace modules
|
||||
*/
|
||||
|
||||
#ifndef __BFA_TRCMOD_PRIV_H__
|
||||
#define __BFA_TRCMOD_PRIV_H__
|
||||
|
||||
#include <cs/bfa_trc.h>
|
||||
|
||||
/*
|
||||
* !!! Only append to the enums defined here to avoid any versioning
|
||||
* !!! needed between trace utility and driver version
|
||||
*/
|
||||
enum {
|
||||
BFA_TRC_HAL_IOC = 1,
|
||||
BFA_TRC_HAL_INTR = 2,
|
||||
BFA_TRC_HAL_FCXP = 3,
|
||||
BFA_TRC_HAL_UF = 4,
|
||||
BFA_TRC_HAL_DIAG = 5,
|
||||
BFA_TRC_HAL_RPORT = 6,
|
||||
BFA_TRC_HAL_FCPIM = 7,
|
||||
BFA_TRC_HAL_IOIM = 8,
|
||||
BFA_TRC_HAL_TSKIM = 9,
|
||||
BFA_TRC_HAL_ITNIM = 10,
|
||||
BFA_TRC_HAL_PPORT = 11,
|
||||
BFA_TRC_HAL_SGPG = 12,
|
||||
BFA_TRC_HAL_FLASH = 13,
|
||||
BFA_TRC_HAL_DEBUG = 14,
|
||||
BFA_TRC_HAL_WWN = 15,
|
||||
BFA_TRC_HAL_FLASH_RAW = 16,
|
||||
BFA_TRC_HAL_SBOOT = 17,
|
||||
BFA_TRC_HAL_SBOOT_IO = 18,
|
||||
BFA_TRC_HAL_SBOOT_INTR = 19,
|
||||
BFA_TRC_HAL_SBTEST = 20,
|
||||
BFA_TRC_HAL_IPFC = 21,
|
||||
BFA_TRC_HAL_IOCFC = 22,
|
||||
BFA_TRC_HAL_FCPTM = 23,
|
||||
BFA_TRC_HAL_IOTM = 24,
|
||||
BFA_TRC_HAL_TSKTM = 25,
|
||||
BFA_TRC_HAL_TIN = 26,
|
||||
BFA_TRC_HAL_LPS = 27,
|
||||
BFA_TRC_HAL_FCDIAG = 28,
|
||||
BFA_TRC_HAL_PBIND = 29,
|
||||
BFA_TRC_HAL_IOCFC_CT = 30,
|
||||
BFA_TRC_HAL_IOCFC_CB = 31,
|
||||
BFA_TRC_HAL_IOCFC_Q = 32,
|
||||
};
|
||||
|
||||
#endif /* __BFA_TRCMOD_PRIV_H__ */
|
689
drivers/scsi/bfa/bfa_tskim.c
Normal file
689
drivers/scsi/bfa/bfa_tskim.c
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfa_cb_ioim_macros.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, TSKIM);
|
||||
|
||||
/**
|
||||
* task management completion handling
|
||||
*/
|
||||
#define bfa_tskim_qcomp(__tskim, __cbfn) do { \
|
||||
bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim)); \
|
||||
bfa_tskim_notify_comp(__tskim); \
|
||||
} while (0)
|
||||
|
||||
#define bfa_tskim_notify_comp(__tskim) do { \
|
||||
if ((__tskim)->notify) \
|
||||
bfa_itnim_tskdone((__tskim)->itnim); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* forward declarations
|
||||
*/
|
||||
static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
|
||||
static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
|
||||
static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
|
||||
lun_t lun);
|
||||
static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
|
||||
static void bfa_tskim_cleanp_comp(void *tskim_cbarg);
|
||||
static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
|
||||
static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
|
||||
static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
|
||||
static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
|
||||
|
||||
/**
|
||||
* bfa_tskim_sm
|
||||
*/
|
||||
|
||||
enum bfa_tskim_event {
|
||||
BFA_TSKIM_SM_START = 1, /* TM command start */
|
||||
BFA_TSKIM_SM_DONE = 2, /* TM completion */
|
||||
BFA_TSKIM_SM_QRESUME = 3, /* resume after qfull */
|
||||
BFA_TSKIM_SM_HWFAIL = 5, /* IOC h/w failure event */
|
||||
BFA_TSKIM_SM_HCB = 6, /* BFA callback completion */
|
||||
BFA_TSKIM_SM_IOS_DONE = 7, /* IO and sub TM completions */
|
||||
BFA_TSKIM_SM_CLEANUP = 8, /* TM cleanup on ITN offline */
|
||||
BFA_TSKIM_SM_CLEANUP_DONE = 9, /* TM abort completion */
|
||||
};
|
||||
|
||||
static void bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event);
|
||||
|
||||
/**
|
||||
* Task management command beginning state.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_START:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_active);
|
||||
bfa_tskim_gather_ios(tskim);
|
||||
|
||||
/**
|
||||
* If device is offline, do not send TM on wire. Just cleanup
|
||||
* any pending IO requests and complete TM request.
|
||||
*/
|
||||
if (!bfa_itnim_is_online(tskim->itnim)) {
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
|
||||
tskim->tsk_status = BFI_TSKIM_STS_OK;
|
||||
bfa_tskim_cleanup_ios(tskim);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bfa_tskim_send(tskim)) {
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
|
||||
bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
|
||||
&tskim->reqq_wait);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* brief
|
||||
* TM command is active, awaiting completion from firmware to
|
||||
* cleanup IO requests in TM scope.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_DONE:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
|
||||
bfa_tskim_cleanup_ios(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_CLEANUP:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
|
||||
if (!bfa_tskim_send_abort(tskim)) {
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
|
||||
bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
|
||||
&tskim->reqq_wait);
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_tskim_iocdisable_ios(tskim);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An active TM is being cleaned up since ITN is offline. Awaiting cleanup
|
||||
* completion event from firmware.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_DONE:
|
||||
/**
|
||||
* Ignore and wait for ABORT completion from firmware.
|
||||
*/
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_CLEANUP_DONE:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
|
||||
bfa_tskim_cleanup_ios(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_tskim_iocdisable_ios(tskim);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_IOS_DONE:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_CLEANUP:
|
||||
/**
|
||||
* Ignore, TM command completed on wire.
|
||||
* Notify TM conmpletion on IO cleanup completion.
|
||||
*/
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_tskim_iocdisable_ios(tskim);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Task management command is waiting for room in request CQ
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_QRESUME:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_active);
|
||||
bfa_tskim_send(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_CLEANUP:
|
||||
/**
|
||||
* No need to send TM on wire since ITN is offline.
|
||||
*/
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
|
||||
bfa_reqq_wcancel(&tskim->reqq_wait);
|
||||
bfa_tskim_cleanup_ios(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_reqq_wcancel(&tskim->reqq_wait);
|
||||
bfa_tskim_iocdisable_ios(tskim);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Task management command is active, awaiting for room in request CQ
|
||||
* to send clean up request.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
|
||||
enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_DONE:
|
||||
bfa_reqq_wcancel(&tskim->reqq_wait);
|
||||
/**
|
||||
*
|
||||
* Fall through !!!
|
||||
*/
|
||||
|
||||
case BFA_TSKIM_SM_QRESUME:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
|
||||
bfa_tskim_send_abort(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
|
||||
bfa_reqq_wcancel(&tskim->reqq_wait);
|
||||
bfa_tskim_iocdisable_ios(tskim);
|
||||
bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA callback is pending
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
|
||||
{
|
||||
bfa_trc(tskim->bfa, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_TSKIM_SM_HCB:
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
|
||||
bfa_tskim_free(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_CLEANUP:
|
||||
bfa_tskim_notify_comp(tskim);
|
||||
break;
|
||||
|
||||
case BFA_TSKIM_SM_HWFAIL:
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_tskim_private
|
||||
*/
|
||||
|
||||
static void
|
||||
__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_tskim_s *tskim = cbarg;
|
||||
|
||||
if (!complete) {
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_stats(tskim->itnim, tm_success);
|
||||
bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
|
||||
}
|
||||
|
||||
static void
|
||||
__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_tskim_s *tskim = cbarg;
|
||||
|
||||
if (!complete) {
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
|
||||
return;
|
||||
}
|
||||
|
||||
bfa_stats(tskim->itnim, tm_failures);
|
||||
bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
|
||||
BFI_TSKIM_STS_FAILED);
|
||||
}
|
||||
|
||||
static bfa_boolean_t
|
||||
bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
|
||||
{
|
||||
switch (tskim->tm_cmnd) {
|
||||
case FCP_TM_TARGET_RESET:
|
||||
return BFA_TRUE;
|
||||
|
||||
case FCP_TM_ABORT_TASK_SET:
|
||||
case FCP_TM_CLEAR_TASK_SET:
|
||||
case FCP_TM_LUN_RESET:
|
||||
case FCP_TM_CLEAR_ACA:
|
||||
return (tskim->lun == lun);
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
return BFA_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather affected IO requests and task management commands.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
struct bfa_itnim_s *itnim = tskim->itnim;
|
||||
struct bfa_ioim_s *ioim;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
INIT_LIST_HEAD(&tskim->io_q);
|
||||
|
||||
/**
|
||||
* Gather any active IO requests first.
|
||||
*/
|
||||
list_for_each_safe(qe, qen, &itnim->io_q) {
|
||||
ioim = (struct bfa_ioim_s *) qe;
|
||||
if (bfa_tskim_match_scope
|
||||
(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
|
||||
list_del(&ioim->qe);
|
||||
list_add_tail(&ioim->qe, &tskim->io_q);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Failback any pending IO requests immediately.
|
||||
*/
|
||||
list_for_each_safe(qe, qen, &itnim->pending_q) {
|
||||
ioim = (struct bfa_ioim_s *) qe;
|
||||
if (bfa_tskim_match_scope
|
||||
(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
|
||||
list_del(&ioim->qe);
|
||||
list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
|
||||
bfa_ioim_tov(ioim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IO cleanup completion
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_cleanp_comp(void *tskim_cbarg)
|
||||
{
|
||||
struct bfa_tskim_s *tskim = tskim_cbarg;
|
||||
|
||||
bfa_stats(tskim->itnim, tm_io_comps);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather affected IO requests and task management commands.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
struct bfa_ioim_s *ioim;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
|
||||
|
||||
list_for_each_safe(qe, qen, &tskim->io_q) {
|
||||
ioim = (struct bfa_ioim_s *) qe;
|
||||
bfa_wc_up(&tskim->wc);
|
||||
bfa_ioim_cleanup_tm(ioim, tskim);
|
||||
}
|
||||
|
||||
bfa_wc_wait(&tskim->wc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send task management request to firmware.
|
||||
*/
|
||||
static bfa_boolean_t
|
||||
bfa_tskim_send(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
struct bfa_itnim_s *itnim = tskim->itnim;
|
||||
struct bfi_tskim_req_s *m;
|
||||
|
||||
/**
|
||||
* check for room in queue to send request now
|
||||
*/
|
||||
m = bfa_reqq_next(tskim->bfa, itnim->reqq);
|
||||
if (!m)
|
||||
return BFA_FALSE;
|
||||
|
||||
/**
|
||||
* build i/o request message next
|
||||
*/
|
||||
bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
|
||||
bfa_lpuid(tskim->bfa));
|
||||
|
||||
m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
|
||||
m->itn_fhdl = tskim->itnim->rport->fw_handle;
|
||||
m->t_secs = tskim->tsecs;
|
||||
m->lun = tskim->lun;
|
||||
m->tm_flags = tskim->tm_cmnd;
|
||||
|
||||
/**
|
||||
* queue I/O message to firmware
|
||||
*/
|
||||
bfa_reqq_produce(tskim->bfa, itnim->reqq);
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send abort request to cleanup an active TM to firmware.
|
||||
*/
|
||||
static bfa_boolean_t
|
||||
bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
struct bfa_itnim_s *itnim = tskim->itnim;
|
||||
struct bfi_tskim_abortreq_s *m;
|
||||
|
||||
/**
|
||||
* check for room in queue to send request now
|
||||
*/
|
||||
m = bfa_reqq_next(tskim->bfa, itnim->reqq);
|
||||
if (!m)
|
||||
return BFA_FALSE;
|
||||
|
||||
/**
|
||||
* build i/o request message next
|
||||
*/
|
||||
bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
|
||||
bfa_lpuid(tskim->bfa));
|
||||
|
||||
m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
|
||||
|
||||
/**
|
||||
* queue I/O message to firmware
|
||||
*/
|
||||
bfa_reqq_produce(tskim->bfa, itnim->reqq);
|
||||
return BFA_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to resume task management cmnd waiting for room in request queue.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_qresume(void *cbarg)
|
||||
{
|
||||
struct bfa_tskim_s *tskim = cbarg;
|
||||
|
||||
bfa_fcpim_stats(tskim->fcpim, qresumes);
|
||||
bfa_stats(tskim->itnim, tm_qresumes);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup IOs associated with a task mangement command on IOC failures.
|
||||
*/
|
||||
static void
|
||||
bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
struct bfa_ioim_s *ioim;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &tskim->io_q) {
|
||||
ioim = (struct bfa_ioim_s *) qe;
|
||||
bfa_ioim_iocdisable(ioim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_tskim_friend
|
||||
*/
|
||||
|
||||
/**
|
||||
* Notification on completions from related ioim.
|
||||
*/
|
||||
void
|
||||
bfa_tskim_iodone(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
bfa_wc_down(&tskim->wc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle IOC h/w failure notification from itnim.
|
||||
*/
|
||||
void
|
||||
bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
tskim->notify = BFA_FALSE;
|
||||
bfa_stats(tskim->itnim, tm_iocdowns);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup TM command and associated IOs as part of ITNIM offline.
|
||||
*/
|
||||
void
|
||||
bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
tskim->notify = BFA_TRUE;
|
||||
bfa_stats(tskim->itnim, tm_cleanups);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory allocation and initialization.
|
||||
*/
|
||||
void
|
||||
bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
|
||||
{
|
||||
struct bfa_tskim_s *tskim;
|
||||
u16 i;
|
||||
|
||||
INIT_LIST_HEAD(&fcpim->tskim_free_q);
|
||||
|
||||
tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
|
||||
fcpim->tskim_arr = tskim;
|
||||
|
||||
for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
|
||||
/*
|
||||
* initialize TSKIM
|
||||
*/
|
||||
bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
|
||||
tskim->tsk_tag = i;
|
||||
tskim->bfa = fcpim->bfa;
|
||||
tskim->fcpim = fcpim;
|
||||
tskim->notify = BFA_FALSE;
|
||||
bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
|
||||
tskim);
|
||||
bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
|
||||
|
||||
list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
|
||||
}
|
||||
|
||||
bfa_meminfo_kva(minfo) = (u8 *) tskim;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
|
||||
{
|
||||
/**
|
||||
* @todo
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
|
||||
struct bfa_tskim_s *tskim;
|
||||
u16 tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
|
||||
|
||||
tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
|
||||
bfa_assert(tskim->tsk_tag == tsk_tag);
|
||||
|
||||
tskim->tsk_status = rsp->tsk_status;
|
||||
|
||||
/**
|
||||
* Firmware sends BFI_TSKIM_STS_ABORTED status for abort
|
||||
* requests. All other statuses are for normal completions.
|
||||
*/
|
||||
if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
|
||||
bfa_stats(tskim->itnim, tm_cleanup_comps);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
|
||||
} else {
|
||||
bfa_stats(tskim->itnim, tm_fw_rsps);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_tskim_api
|
||||
*/
|
||||
|
||||
|
||||
struct bfa_tskim_s *
|
||||
bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
|
||||
{
|
||||
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
|
||||
struct bfa_tskim_s *tskim;
|
||||
|
||||
bfa_q_deq(&fcpim->tskim_free_q, &tskim);
|
||||
|
||||
if (!tskim)
|
||||
bfa_fcpim_stats(fcpim, no_tskims);
|
||||
else
|
||||
tskim->dtsk = dtsk;
|
||||
|
||||
return tskim;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_tskim_free(struct bfa_tskim_s *tskim)
|
||||
{
|
||||
bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
|
||||
list_del(&tskim->qe);
|
||||
list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a task management command.
|
||||
*
|
||||
* @param[in] tskim BFA task management command instance
|
||||
* @param[in] itnim i-t nexus for the task management command
|
||||
* @param[in] lun lun, if applicable
|
||||
* @param[in] tm_cmnd Task management command code.
|
||||
* @param[in] t_secs Timeout in seconds
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void
|
||||
bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
|
||||
enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
|
||||
{
|
||||
tskim->itnim = itnim;
|
||||
tskim->lun = lun;
|
||||
tskim->tm_cmnd = tm_cmnd;
|
||||
tskim->tsecs = tsecs;
|
||||
tskim->notify = BFA_FALSE;
|
||||
bfa_stats(itnim, tm_cmnds);
|
||||
|
||||
list_add_tail(&tskim->qe, &itnim->tsk_q);
|
||||
bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
|
||||
}
|
||||
|
||||
|
345
drivers/scsi/bfa/bfa_uf.c
Normal file
345
drivers/scsi/bfa/bfa_uf.c
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_uf.c BFA unsolicited frame receive implementation
|
||||
*/
|
||||
|
||||
#include <bfa.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <bfi/bfi_uf.h>
|
||||
#include <cs/bfa_debug.h>
|
||||
|
||||
BFA_TRC_FILE(HAL, UF);
|
||||
BFA_MODULE(uf);
|
||||
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Internal functions
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void
|
||||
__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
|
||||
{
|
||||
struct bfa_uf_s *uf = cbarg;
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
|
||||
|
||||
if (complete)
|
||||
ufm->ufrecv(ufm->cbarg, uf);
|
||||
}
|
||||
|
||||
static void
|
||||
claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
u32 uf_pb_tot_sz;
|
||||
|
||||
ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
|
||||
ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
|
||||
uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
|
||||
bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
|
||||
bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
|
||||
|
||||
bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
|
||||
}
|
||||
|
||||
static void
|
||||
claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
struct bfi_uf_buf_post_s *uf_bp_msg;
|
||||
struct bfi_sge_s *sge;
|
||||
union bfi_addr_u sga_zero = { {0} };
|
||||
u16 i;
|
||||
u16 buf_len;
|
||||
|
||||
ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
|
||||
uf_bp_msg = ufm->uf_buf_posts;
|
||||
|
||||
for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
|
||||
i++, uf_bp_msg++) {
|
||||
bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
|
||||
|
||||
uf_bp_msg->buf_tag = i;
|
||||
buf_len = sizeof(struct bfa_uf_buf_s);
|
||||
uf_bp_msg->buf_len = bfa_os_htons(buf_len);
|
||||
bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
|
||||
bfa_lpuid(ufm->bfa));
|
||||
|
||||
sge = uf_bp_msg->sge;
|
||||
sge[0].sg_len = buf_len;
|
||||
sge[0].flags = BFI_SGE_DATA_LAST;
|
||||
bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
|
||||
bfa_sge_to_be(sge);
|
||||
|
||||
sge[1].sg_len = buf_len;
|
||||
sge[1].flags = BFI_SGE_PGDLEN;
|
||||
sge[1].sga = sga_zero;
|
||||
bfa_sge_to_be(&sge[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* advance pointer beyond consumed memory
|
||||
*/
|
||||
bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
|
||||
}
|
||||
|
||||
static void
|
||||
claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
u16 i;
|
||||
struct bfa_uf_s *uf;
|
||||
|
||||
/*
|
||||
* Claim block of memory for UF list
|
||||
*/
|
||||
ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
|
||||
|
||||
/*
|
||||
* Initialize UFs and queue it in UF free queue
|
||||
*/
|
||||
for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
|
||||
bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
|
||||
uf->bfa = ufm->bfa;
|
||||
uf->uf_tag = i;
|
||||
uf->pb_len = sizeof(struct bfa_uf_buf_s);
|
||||
uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
|
||||
uf->buf_pa = ufm_pbs_pa(ufm, i);
|
||||
list_add_tail(&uf->qe, &ufm->uf_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* advance memory pointer
|
||||
*/
|
||||
bfa_meminfo_kva(mi) = (u8 *) uf;
|
||||
}
|
||||
|
||||
static void
|
||||
uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
|
||||
{
|
||||
claim_uf_pbs(ufm, mi);
|
||||
claim_ufs(ufm, mi);
|
||||
claim_uf_post_msgs(ufm, mi);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
|
||||
{
|
||||
u32 num_ufs = cfg->fwcfg.num_uf_bufs;
|
||||
|
||||
/*
|
||||
* dma-able memory for UF posted bufs
|
||||
*/
|
||||
*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
|
||||
BFA_DMA_ALIGN_SZ);
|
||||
|
||||
/*
|
||||
* kernel Virtual memory for UFs and UF buf post msg copies
|
||||
*/
|
||||
*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
|
||||
*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
|
||||
|
||||
bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
|
||||
ufm->bfa = bfa;
|
||||
ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
|
||||
INIT_LIST_HEAD(&ufm->uf_free_q);
|
||||
INIT_LIST_HEAD(&ufm->uf_posted_q);
|
||||
|
||||
uf_mem_claim(ufm, meminfo);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_initdone(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static struct bfa_uf_s *
|
||||
bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
|
||||
{
|
||||
struct bfa_uf_s *uf;
|
||||
|
||||
bfa_q_deq(&uf_mod->uf_free_q, &uf);
|
||||
return (uf);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
|
||||
{
|
||||
list_add_tail(&uf->qe, &uf_mod->uf_free_q);
|
||||
}
|
||||
|
||||
static bfa_status_t
|
||||
bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
|
||||
{
|
||||
struct bfi_uf_buf_post_s *uf_post_msg;
|
||||
|
||||
uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
|
||||
if (!uf_post_msg)
|
||||
return BFA_STATUS_FAILED;
|
||||
|
||||
bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
|
||||
sizeof(struct bfi_uf_buf_post_s));
|
||||
bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
|
||||
|
||||
bfa_trc(ufm->bfa, uf->uf_tag);
|
||||
|
||||
list_add_tail(&uf->qe, &ufm->uf_posted_q);
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
|
||||
{
|
||||
struct bfa_uf_s *uf;
|
||||
|
||||
while ((uf = bfa_uf_get(uf_mod)) != NULL) {
|
||||
if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
|
||||
{
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
|
||||
u16 uf_tag = m->buf_tag;
|
||||
struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
|
||||
struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
|
||||
u8 *buf = &uf_buf->d[0];
|
||||
struct fchs_s *fchs;
|
||||
|
||||
m->frm_len = bfa_os_ntohs(m->frm_len);
|
||||
m->xfr_len = bfa_os_ntohs(m->xfr_len);
|
||||
|
||||
fchs = (struct fchs_s *) uf_buf;
|
||||
|
||||
list_del(&uf->qe); /* dequeue from posted queue */
|
||||
|
||||
uf->data_ptr = buf;
|
||||
uf->data_len = m->xfr_len;
|
||||
|
||||
bfa_assert(uf->data_len >= sizeof(struct fchs_s));
|
||||
|
||||
if (uf->data_len == sizeof(struct fchs_s)) {
|
||||
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
|
||||
uf->data_len, (struct fchs_s *) buf);
|
||||
} else {
|
||||
u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
|
||||
bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
|
||||
BFA_PL_EID_RX, uf->data_len,
|
||||
(struct fchs_s *) buf, pld_w0);
|
||||
}
|
||||
|
||||
bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
|
||||
struct bfa_uf_s *uf;
|
||||
struct list_head *qe, *qen;
|
||||
|
||||
list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
|
||||
uf = (struct bfa_uf_s *) qe;
|
||||
list_del(&uf->qe);
|
||||
bfa_uf_put(ufm, uf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_start(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_uf_post_all(BFA_UF_MOD(bfa));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* bfa_uf_api
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register handler for all unsolicted recieve frames.
|
||||
*
|
||||
* @param[in] bfa BFA instance
|
||||
* @param[in] ufrecv receive handler function
|
||||
* @param[in] cbarg receive handler arg
|
||||
*/
|
||||
void
|
||||
bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
|
||||
{
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
|
||||
|
||||
ufm->ufrecv = ufrecv;
|
||||
ufm->cbarg = cbarg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an unsolicited frame back to BFA.
|
||||
*
|
||||
* @param[in] uf unsolicited frame to be freed
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
bfa_uf_free(struct bfa_uf_s *uf)
|
||||
{
|
||||
bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
|
||||
bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* uf_pub BFA uf module public functions
|
||||
*/
|
||||
|
||||
void
|
||||
bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
|
||||
{
|
||||
bfa_trc(bfa, msg->mhdr.msg_id);
|
||||
|
||||
switch (msg->mhdr.msg_id) {
|
||||
case BFI_UF_I2H_FRM_RCVD:
|
||||
uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_trc(bfa, msg->mhdr.msg_id);
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
47
drivers/scsi/bfa/bfa_uf_priv.h
Normal file
47
drivers/scsi/bfa/bfa_uf_priv.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_UF_PRIV_H__
|
||||
#define __BFA_UF_PRIV_H__
|
||||
|
||||
#include <cs/bfa_sm.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <bfi/bfi_uf.h>
|
||||
|
||||
#define BFA_UF_MIN (4)
|
||||
|
||||
struct bfa_uf_mod_s {
|
||||
struct bfa_s *bfa; /* back pointer to BFA */
|
||||
struct bfa_uf_s *uf_list; /* array of UFs */
|
||||
u16 num_ufs; /* num unsolicited rx frames */
|
||||
struct list_head uf_free_q; /* free UFs */
|
||||
struct list_head uf_posted_q; /* UFs posted to IOC */
|
||||
struct bfa_uf_buf_s *uf_pbs_kva; /* list UF bufs request pld */
|
||||
u64 uf_pbs_pa; /* phy addr for UF bufs */
|
||||
struct bfi_uf_buf_post_s *uf_buf_posts;
|
||||
/* pre-built UF post msgs */
|
||||
bfa_cb_uf_recv_t ufrecv; /* uf recv handler function */
|
||||
void *cbarg; /* uf receive handler arg */
|
||||
};
|
||||
|
||||
#define BFA_UF_MOD(__bfa) (&(__bfa)->modules.uf_mod)
|
||||
|
||||
#define ufm_pbs_pa(_ufmod, _uftag) \
|
||||
((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
|
||||
|
||||
void bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
|
||||
|
||||
#endif /* __BFA_UF_PRIV_H__ */
|
1182
drivers/scsi/bfa/bfad.c
Normal file
1182
drivers/scsi/bfa/bfad.c
Normal file
File diff suppressed because it is too large
Load Diff
649
drivers/scsi/bfa/bfad_attr.c
Normal file
649
drivers/scsi/bfa/bfad_attr.c
Normal file
@ -0,0 +1,649 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_attr.c Linux driver configuration interface module.
|
||||
*/
|
||||
|
||||
#include "bfad_drv.h"
|
||||
#include "bfad_im.h"
|
||||
#include "bfad_trcmod.h"
|
||||
#include "bfad_attr.h"
|
||||
|
||||
/**
|
||||
* FC_transport_template FC transport template
|
||||
*/
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target port ID.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_port_id(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct bfad_im_port_s *im_port;
|
||||
struct bfad_s *bfad;
|
||||
struct bfad_itnim_s *itnim = NULL;
|
||||
u32 fc_id = -1;
|
||||
unsigned long flags;
|
||||
|
||||
shost = bfad_os_starget_to_shost(starget);
|
||||
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
|
||||
bfad = im_port->bfad;
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
|
||||
itnim = bfad_os_get_itnim(im_port, starget->id);
|
||||
if (itnim)
|
||||
fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
|
||||
|
||||
fc_starget_port_id(starget) = fc_id;
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target nwwn.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_node_name(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct bfad_im_port_s *im_port;
|
||||
struct bfad_s *bfad;
|
||||
struct bfad_itnim_s *itnim = NULL;
|
||||
u64 node_name = 0;
|
||||
unsigned long flags;
|
||||
|
||||
shost = bfad_os_starget_to_shost(starget);
|
||||
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
|
||||
bfad = im_port->bfad;
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
|
||||
itnim = bfad_os_get_itnim(im_port, starget->id);
|
||||
if (itnim)
|
||||
node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
|
||||
|
||||
fc_starget_node_name(starget) = bfa_os_htonll(node_name);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target pwwn.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_port_name(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct bfad_im_port_s *im_port;
|
||||
struct bfad_s *bfad;
|
||||
struct bfad_itnim_s *itnim = NULL;
|
||||
u64 port_name = 0;
|
||||
unsigned long flags;
|
||||
|
||||
shost = bfad_os_starget_to_shost(starget);
|
||||
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
|
||||
bfad = im_port->bfad;
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
|
||||
itnim = bfad_os_get_itnim(im_port, starget->id);
|
||||
if (itnim)
|
||||
port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
|
||||
|
||||
fc_starget_port_name(starget) = bfa_os_htonll(port_name);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host port ID.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_host_port_id(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_port_s *port = im_port->port;
|
||||
|
||||
fc_host_port_id(shost) =
|
||||
bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct Scsi_Host *
|
||||
bfad_os_starget_to_shost(struct scsi_target *starget)
|
||||
{
|
||||
return dev_to_shost(starget->dev.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host port type.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_host_port_type(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_pport_attr_s attr;
|
||||
|
||||
bfa_pport_get_attr(&bfad->bfa, &attr);
|
||||
|
||||
switch (attr.port_type) {
|
||||
case BFA_PPORT_TYPE_NPORT:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
|
||||
break;
|
||||
case BFA_PPORT_TYPE_NLPORT:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
|
||||
break;
|
||||
case BFA_PPORT_TYPE_P2P:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
|
||||
break;
|
||||
case BFA_PPORT_TYPE_LPORT:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
|
||||
break;
|
||||
default:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host port state.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_host_port_state(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_pport_attr_s attr;
|
||||
|
||||
bfa_pport_get_attr(&bfad->bfa, &attr);
|
||||
|
||||
switch (attr.port_state) {
|
||||
case BFA_PPORT_ST_LINKDOWN:
|
||||
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
|
||||
break;
|
||||
case BFA_PPORT_ST_LINKUP:
|
||||
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
|
||||
break;
|
||||
case BFA_PPORT_ST_UNINIT:
|
||||
case BFA_PPORT_ST_ENABLING_QWAIT:
|
||||
case BFA_PPORT_ST_ENABLING:
|
||||
case BFA_PPORT_ST_DISABLING_QWAIT:
|
||||
case BFA_PPORT_ST_DISABLING:
|
||||
case BFA_PPORT_ST_DISABLED:
|
||||
case BFA_PPORT_ST_STOPPED:
|
||||
case BFA_PPORT_ST_IOCDOWN:
|
||||
default:
|
||||
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host active fc4s.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_port_s *port = im_port->port;
|
||||
|
||||
memset(fc_host_active_fc4s(shost), 0,
|
||||
sizeof(fc_host_active_fc4s(shost)));
|
||||
|
||||
if (port->supported_fc4s &
|
||||
(BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
|
||||
fc_host_active_fc4s(shost)[2] = 1;
|
||||
|
||||
if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
|
||||
fc_host_active_fc4s(shost)[3] = 0x20;
|
||||
|
||||
fc_host_active_fc4s(shost)[7] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host link speed.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_host_speed(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_pport_attr_s attr;
|
||||
|
||||
bfa_pport_get_attr(&bfad->bfa, &attr);
|
||||
switch (attr.speed) {
|
||||
case BFA_PPORT_SPEED_8GBPS:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
|
||||
break;
|
||||
case BFA_PPORT_SPEED_4GBPS:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
|
||||
break;
|
||||
case BFA_PPORT_SPEED_2GBPS:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
|
||||
break;
|
||||
case BFA_PPORT_SPEED_1GBPS:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
default:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host port type.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_port_s *port = im_port->port;
|
||||
wwn_t fabric_nwwn = 0;
|
||||
|
||||
fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
|
||||
|
||||
fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get BFAD statistics.
|
||||
*/
|
||||
static struct fc_host_statistics *
|
||||
bfad_im_get_stats(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfad_hal_comp fcomp;
|
||||
struct fc_host_statistics *hstats;
|
||||
bfa_status_t rc;
|
||||
unsigned long flags;
|
||||
|
||||
hstats = &bfad->link_stats;
|
||||
init_completion(&fcomp.comp);
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
memset(hstats, 0, sizeof(struct fc_host_statistics));
|
||||
rc = bfa_pport_get_stats(&bfad->bfa,
|
||||
(union bfa_pport_stats_u *) hstats,
|
||||
bfad_hcb_comp, &fcomp);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
if (rc != BFA_STATUS_OK)
|
||||
return NULL;
|
||||
|
||||
wait_for_completion(&fcomp.comp);
|
||||
|
||||
return hstats;
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, reset BFAD statistics.
|
||||
*/
|
||||
static void
|
||||
bfad_im_reset_stats(struct Scsi_Host *shost)
|
||||
{
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfad_hal_comp fcomp;
|
||||
unsigned long flags;
|
||||
bfa_status_t rc;
|
||||
|
||||
init_completion(&fcomp.comp);
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
rc = bfa_pport_clear_stats(&bfad->bfa, bfad_hcb_comp, &fcomp);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
if (rc != BFA_STATUS_OK)
|
||||
return;
|
||||
|
||||
wait_for_completion(&fcomp.comp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, get rport loss timeout.
|
||||
*/
|
||||
static void
|
||||
bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
|
||||
{
|
||||
struct bfad_itnim_data_s *itnim_data = rport->dd_data;
|
||||
struct bfad_itnim_s *itnim = itnim_data->itnim;
|
||||
struct bfad_s *bfad = itnim->im->bfad;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* FC transport template entry, set rport loss timeout.
|
||||
*/
|
||||
static void
|
||||
bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
|
||||
{
|
||||
struct bfad_itnim_data_s *itnim_data = rport->dd_data;
|
||||
struct bfad_itnim_s *itnim = itnim_data->itnim;
|
||||
struct bfad_s *bfad = itnim->im->bfad;
|
||||
unsigned long flags;
|
||||
|
||||
if (timeout > 0) {
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
|
||||
rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct fc_function_template bfad_im_fc_function_template = {
|
||||
|
||||
/* Target dynamic attributes */
|
||||
.get_starget_port_id = bfad_im_get_starget_port_id,
|
||||
.show_starget_port_id = 1,
|
||||
.get_starget_node_name = bfad_im_get_starget_node_name,
|
||||
.show_starget_node_name = 1,
|
||||
.get_starget_port_name = bfad_im_get_starget_port_name,
|
||||
.show_starget_port_name = 1,
|
||||
|
||||
/* Host dynamic attribute */
|
||||
.get_host_port_id = bfad_im_get_host_port_id,
|
||||
.show_host_port_id = 1,
|
||||
|
||||
/* Host fixed attributes */
|
||||
.show_host_node_name = 1,
|
||||
.show_host_port_name = 1,
|
||||
.show_host_supported_classes = 1,
|
||||
.show_host_supported_fc4s = 1,
|
||||
.show_host_supported_speeds = 1,
|
||||
.show_host_maxframe_size = 1,
|
||||
|
||||
/* More host dynamic attributes */
|
||||
.show_host_port_type = 1,
|
||||
.get_host_port_type = bfad_im_get_host_port_type,
|
||||
.show_host_port_state = 1,
|
||||
.get_host_port_state = bfad_im_get_host_port_state,
|
||||
.show_host_active_fc4s = 1,
|
||||
.get_host_active_fc4s = bfad_im_get_host_active_fc4s,
|
||||
.show_host_speed = 1,
|
||||
.get_host_speed = bfad_im_get_host_speed,
|
||||
.show_host_fabric_name = 1,
|
||||
.get_host_fabric_name = bfad_im_get_host_fabric_name,
|
||||
|
||||
.show_host_symbolic_name = 1,
|
||||
|
||||
/* Statistics */
|
||||
.get_fc_host_stats = bfad_im_get_stats,
|
||||
.reset_fc_host_stats = bfad_im_reset_stats,
|
||||
|
||||
/* Allocation length for host specific data */
|
||||
.dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
|
||||
|
||||
/* Remote port fixed attributes */
|
||||
.show_rport_maxframe_size = 1,
|
||||
.show_rport_supported_classes = 1,
|
||||
.show_rport_dev_loss_tmo = 1,
|
||||
.get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
|
||||
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
|
||||
};
|
||||
|
||||
/**
|
||||
* Scsi_Host_attrs SCSI host attributes
|
||||
*/
|
||||
static ssize_t
|
||||
bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ioc_attr.adapter_attr.serial_num);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_model_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.model);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ioc_attr.adapter_attr.model_descr);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_port_s *port = im_port->port;
|
||||
u64 nwwn;
|
||||
|
||||
nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
|
||||
ioc_attr.adapter_attr.model,
|
||||
ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.hw_ver);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_optionrom_version_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ioc_attr.adapter_attr.optrom_ver);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.fw_ver);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
struct bfa_ioc_attr_s ioc_attr;
|
||||
|
||||
memset(&ioc_attr, 0, sizeof(ioc_attr));
|
||||
bfa_get_attr(&bfad->bfa, &ioc_attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ioc_attr.adapter_attr.nports);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bfad_im_num_of_discovered_ports_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct bfad_im_port_s *im_port =
|
||||
(struct bfad_im_port_s *) shost->hostdata[0];
|
||||
struct bfad_port_s *port = im_port->port;
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
int nrports = 2048;
|
||||
wwn_t *rports = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
|
||||
if (rports == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
kfree(rports);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(serial_number, S_IRUGO,
|
||||
bfad_im_serial_num_show, NULL);
|
||||
static DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL);
|
||||
static DEVICE_ATTR(model_description, S_IRUGO,
|
||||
bfad_im_model_desc_show, NULL);
|
||||
static DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL);
|
||||
static DEVICE_ATTR(symbolic_name, S_IRUGO,
|
||||
bfad_im_symbolic_name_show, NULL);
|
||||
static DEVICE_ATTR(hardware_version, S_IRUGO,
|
||||
bfad_im_hw_version_show, NULL);
|
||||
static DEVICE_ATTR(driver_version, S_IRUGO,
|
||||
bfad_im_drv_version_show, NULL);
|
||||
static DEVICE_ATTR(option_rom_version, S_IRUGO,
|
||||
bfad_im_optionrom_version_show, NULL);
|
||||
static DEVICE_ATTR(firmware_version, S_IRUGO,
|
||||
bfad_im_fw_version_show, NULL);
|
||||
static DEVICE_ATTR(number_of_ports, S_IRUGO,
|
||||
bfad_im_num_of_ports_show, NULL);
|
||||
static DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL);
|
||||
static DEVICE_ATTR(number_of_discovered_ports, S_IRUGO,
|
||||
bfad_im_num_of_discovered_ports_show, NULL);
|
||||
|
||||
struct device_attribute *bfad_im_host_attrs[] = {
|
||||
&dev_attr_serial_number,
|
||||
&dev_attr_model,
|
||||
&dev_attr_model_description,
|
||||
&dev_attr_node_name,
|
||||
&dev_attr_symbolic_name,
|
||||
&dev_attr_hardware_version,
|
||||
&dev_attr_driver_version,
|
||||
&dev_attr_option_rom_version,
|
||||
&dev_attr_firmware_version,
|
||||
&dev_attr_number_of_ports,
|
||||
&dev_attr_driver_name,
|
||||
&dev_attr_number_of_discovered_ports,
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct device_attribute *bfad_im_vport_attrs[] = {
|
||||
&dev_attr_serial_number,
|
||||
&dev_attr_model,
|
||||
&dev_attr_model_description,
|
||||
&dev_attr_node_name,
|
||||
&dev_attr_symbolic_name,
|
||||
&dev_attr_hardware_version,
|
||||
&dev_attr_driver_version,
|
||||
&dev_attr_option_rom_version,
|
||||
&dev_attr_firmware_version,
|
||||
&dev_attr_number_of_ports,
|
||||
&dev_attr_driver_name,
|
||||
&dev_attr_number_of_discovered_ports,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
65
drivers/scsi/bfa/bfad_attr.h
Normal file
65
drivers/scsi/bfa/bfad_attr.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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_ATTR_H__
|
||||
#define __BFAD_ATTR_H__
|
||||
/**
|
||||
* bfad_attr.h VMware driver configuration interface module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FC_transport_template FC transport template
|
||||
*/
|
||||
|
||||
struct Scsi_Host*
|
||||
bfad_os_dev_to_shost(struct scsi_target *starget);
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target port ID.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_port_id(struct scsi_target *starget);
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target nwwn.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_node_name(struct scsi_target *starget);
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI target pwwn.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_starget_port_name(struct scsi_target *starget);
|
||||
|
||||
/**
|
||||
* FC transport template entry, get SCSI host port ID.
|
||||
*/
|
||||
void
|
||||
bfad_im_get_host_port_id(struct Scsi_Host *shost);
|
||||
|
||||
/**
|
||||
* FC transport template entry, issue a LIP.
|
||||
*/
|
||||
int
|
||||
bfad_im_issue_fc_host_lip(struct Scsi_Host *shost);
|
||||
|
||||
struct Scsi_Host*
|
||||
bfad_os_starget_to_shost(struct scsi_target *starget);
|
||||
|
||||
|
||||
#endif /* __BFAD_ATTR_H__ */
|
295
drivers/scsi/bfa/bfad_drv.h
Normal file
295
drivers/scsi/bfa/bfad_drv.h
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains base driver definitions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_drv.h Linux driver data structures.
|
||||
*/
|
||||
|
||||
#ifndef __BFAD_DRV_H__
|
||||
#define __BFAD_DRV_H__
|
||||
|
||||
#include "bfa_os_inc.h"
|
||||
|
||||
#include <bfa.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <defs/bfa_defs_pci.h>
|
||||
#include <defs/bfa_defs_port.h>
|
||||
#include <defs/bfa_defs_rport.h>
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
#include <defs/bfa_defs_vport.h>
|
||||
#include <fcs/bfa_fcs_vport.h>
|
||||
|
||||
#include <cs/bfa_plog.h>
|
||||
#include "aen/bfa_aen.h"
|
||||
#include <log/bfa_log_linux.h>
|
||||
|
||||
#define BFAD_DRIVER_NAME "bfa"
|
||||
#ifdef BFA_DRIVER_VERSION
|
||||
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
|
||||
#else
|
||||
#define BFAD_DRIVER_VERSION "2.0.0.0"
|
||||
#endif
|
||||
|
||||
|
||||
#define BFAD_IRQ_FLAGS IRQF_SHARED
|
||||
|
||||
/*
|
||||
* BFAD flags
|
||||
*/
|
||||
#define BFAD_MSIX_ON 0x00000001
|
||||
#define BFAD_HAL_INIT_DONE 0x00000002
|
||||
#define BFAD_DRV_INIT_DONE 0x00000004
|
||||
#define BFAD_CFG_PPORT_DONE 0x00000008
|
||||
#define BFAD_HAL_START_DONE 0x00000010
|
||||
#define BFAD_PORT_ONLINE 0x00000020
|
||||
#define BFAD_RPORT_ONLINE 0x00000040
|
||||
|
||||
#define BFAD_PORT_DELETE 0x00000001
|
||||
|
||||
/*
|
||||
* BFAD related definition
|
||||
*/
|
||||
#define SCSI_SCAN_DELAY HZ
|
||||
#define BFAD_STOP_TIMEOUT 30
|
||||
#define BFAD_SUSPEND_TIMEOUT BFAD_STOP_TIMEOUT
|
||||
|
||||
/*
|
||||
* BFAD configuration parameter default values
|
||||
*/
|
||||
#define BFAD_LUN_QUEUE_DEPTH 32
|
||||
#define BFAD_IO_MAX_SGE SG_ALL
|
||||
|
||||
#define bfad_isr_t irq_handler_t
|
||||
|
||||
#define MAX_MSIX_ENTRY 22
|
||||
|
||||
struct bfad_msix_s {
|
||||
struct bfad_s *bfad;
|
||||
struct msix_entry msix;
|
||||
};
|
||||
|
||||
enum bfad_port_pvb_type {
|
||||
BFAD_PORT_PHYS_BASE = 0,
|
||||
BFAD_PORT_PHYS_VPORT = 1,
|
||||
BFAD_PORT_VF_BASE = 2,
|
||||
BFAD_PORT_VF_VPORT = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* PORT data structure
|
||||
*/
|
||||
struct bfad_port_s {
|
||||
struct list_head list_entry;
|
||||
struct bfad_s *bfad;
|
||||
struct bfa_fcs_port_s *fcs_port;
|
||||
u32 roles;
|
||||
s32 flags;
|
||||
u32 supported_fc4s;
|
||||
u8 ipfc_flags;
|
||||
enum bfad_port_pvb_type pvb_type;
|
||||
struct bfad_im_port_s *im_port; /* IM specific data */
|
||||
struct bfad_tm_port_s *tm_port; /* TM specific data */
|
||||
struct bfad_ipfc_port_s *ipfc_port; /* IPFC specific data */
|
||||
};
|
||||
|
||||
/*
|
||||
* VPORT data structure
|
||||
*/
|
||||
struct bfad_vport_s {
|
||||
struct bfad_port_s drv_port;
|
||||
struct bfa_fcs_vport_s fcs_vport;
|
||||
struct completion *comp_del;
|
||||
};
|
||||
|
||||
/*
|
||||
* VF data structure
|
||||
*/
|
||||
struct bfad_vf_s {
|
||||
bfa_fcs_vf_t fcs_vf;
|
||||
struct bfad_port_s base_port; /* base port for vf */
|
||||
struct bfad_s *bfad;
|
||||
};
|
||||
|
||||
struct bfad_cfg_param_s {
|
||||
u32 rport_del_timeout;
|
||||
u32 ioc_queue_depth;
|
||||
u32 lun_queue_depth;
|
||||
u32 io_max_sge;
|
||||
u32 binding_method;
|
||||
};
|
||||
|
||||
#define BFAD_AEN_MAX_APPS 8
|
||||
struct bfad_aen_file_s {
|
||||
struct list_head qe;
|
||||
struct bfad_s *bfad;
|
||||
s32 ri;
|
||||
s32 app_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* BFAD (PCI function) data structure
|
||||
*/
|
||||
struct bfad_s {
|
||||
struct list_head list_entry;
|
||||
struct bfa_s bfa;
|
||||
struct bfa_fcs_s bfa_fcs;
|
||||
struct pci_dev *pcidev;
|
||||
const char *pci_name;
|
||||
struct bfa_pcidev_s hal_pcidev;
|
||||
struct bfa_ioc_pci_attr_s pci_attr;
|
||||
unsigned long pci_bar0_map;
|
||||
void __iomem *pci_bar0_kva;
|
||||
struct completion comp;
|
||||
struct completion suspend;
|
||||
struct completion disable_comp;
|
||||
bfa_boolean_t disable_active;
|
||||
struct bfad_port_s pport; /* physical port of the BFAD */
|
||||
struct bfa_meminfo_s meminfo;
|
||||
struct bfa_iocfc_cfg_s ioc_cfg;
|
||||
u32 inst_no; /* BFAD instance number */
|
||||
u32 bfad_flags;
|
||||
spinlock_t bfad_lock;
|
||||
struct bfad_cfg_param_s cfg_data;
|
||||
struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
|
||||
int nvec;
|
||||
char adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
|
||||
char port_name[BFA_ADAPTER_SYM_NAME_LEN];
|
||||
struct timer_list hal_tmo;
|
||||
unsigned long hs_start;
|
||||
struct bfad_im_s *im; /* IM specific data */
|
||||
struct bfad_tm_s *tm; /* TM specific data */
|
||||
struct bfad_ipfc_s *ipfc; /* IPFC specific data */
|
||||
struct bfa_log_mod_s log_data;
|
||||
struct bfa_trc_mod_s *trcmod;
|
||||
struct bfa_log_mod_s *logmod;
|
||||
struct bfa_aen_s *aen;
|
||||
struct bfa_aen_s aen_buf;
|
||||
struct bfad_aen_file_s file_buf[BFAD_AEN_MAX_APPS];
|
||||
struct list_head file_q;
|
||||
struct list_head file_free_q;
|
||||
struct bfa_plog_s plog_buf;
|
||||
int ref_count;
|
||||
bfa_boolean_t ipfc_enabled;
|
||||
struct fc_host_statistics link_stats;
|
||||
|
||||
struct kobject *bfa_kobj;
|
||||
struct kobject *ioc_kobj;
|
||||
struct kobject *pport_kobj;
|
||||
struct kobject *lport_kobj;
|
||||
};
|
||||
|
||||
/*
|
||||
* RPORT data structure
|
||||
*/
|
||||
struct bfad_rport_s {
|
||||
struct bfa_fcs_rport_s fcs_rport;
|
||||
};
|
||||
|
||||
struct bfad_buf_info {
|
||||
void *virt;
|
||||
dma_addr_t phys;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct bfad_fcxp {
|
||||
struct bfad_port_s *port;
|
||||
struct bfa_rport_s *bfa_rport;
|
||||
bfa_status_t req_status;
|
||||
u16 tag;
|
||||
u16 rsp_len;
|
||||
u16 rsp_maxlen;
|
||||
u8 use_ireqbuf;
|
||||
u8 use_irspbuf;
|
||||
u32 num_req_sgles;
|
||||
u32 num_rsp_sgles;
|
||||
struct fchs_s fchs;
|
||||
void *reqbuf_info;
|
||||
void *rspbuf_info;
|
||||
struct bfa_sge_s *req_sge;
|
||||
struct bfa_sge_s *rsp_sge;
|
||||
fcxp_send_cb_t send_cbfn;
|
||||
void *send_cbarg;
|
||||
void *bfa_fcxp;
|
||||
struct completion comp;
|
||||
};
|
||||
|
||||
struct bfad_hal_comp {
|
||||
bfa_status_t status;
|
||||
struct completion comp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro to obtain the immediate lower power
|
||||
* of two for the integer.
|
||||
*/
|
||||
#define nextLowerInt(x) \
|
||||
do { \
|
||||
int j; \
|
||||
(*x)--; \
|
||||
for (j = 1; j < (sizeof(int) * 8); j <<= 1) \
|
||||
(*x) = (*x) | (*x) >> j; \
|
||||
(*x)++; \
|
||||
(*x) = (*x) >> 1; \
|
||||
} while (0)
|
||||
|
||||
|
||||
bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
|
||||
struct bfa_port_cfg_s *port_cfg);
|
||||
bfa_status_t bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
|
||||
struct bfa_port_cfg_s *port_cfg);
|
||||
bfa_status_t bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
|
||||
bfa_status_t bfad_drv_init(struct bfad_s *bfad);
|
||||
void bfad_drv_start(struct bfad_s *bfad);
|
||||
void bfad_uncfg_pport(struct bfad_s *bfad);
|
||||
void bfad_drv_stop(struct bfad_s *bfad);
|
||||
void bfad_remove_intr(struct bfad_s *bfad);
|
||||
void bfad_hal_mem_release(struct bfad_s *bfad);
|
||||
void bfad_hcb_comp(void *arg, bfa_status_t status);
|
||||
|
||||
int bfad_setup_intr(struct bfad_s *bfad);
|
||||
void bfad_remove_intr(struct bfad_s *bfad);
|
||||
|
||||
void bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
|
||||
bfa_status_t bfad_hal_mem_alloc(struct bfad_s *bfad);
|
||||
void bfad_bfa_tmo(unsigned long data);
|
||||
void bfad_init_timer(struct bfad_s *bfad);
|
||||
int bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad);
|
||||
void bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
|
||||
void bfad_fcs_port_cfg(struct bfad_s *bfad);
|
||||
void bfad_drv_uninit(struct bfad_s *bfad);
|
||||
void bfad_drv_log_level_set(struct bfad_s *bfad);
|
||||
bfa_status_t bfad_fc4_module_init(void);
|
||||
void bfad_fc4_module_exit(void);
|
||||
|
||||
void bfad_pci_remove(struct pci_dev *pdev);
|
||||
int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid);
|
||||
void bfad_os_rport_online_wait(struct bfad_s *bfad);
|
||||
int bfad_os_get_linkup_delay(struct bfad_s *bfad);
|
||||
int bfad_install_msix_handler(struct bfad_s *bfad);
|
||||
|
||||
extern struct idr bfad_im_port_index;
|
||||
extern struct list_head bfad_list;
|
||||
extern int bfa_lun_queue_depth;
|
||||
extern int bfad_supported_fc4s;
|
||||
extern int bfa_linkup_delay;
|
||||
|
||||
#endif /* __BFAD_DRV_H__ */
|
95
drivers/scsi/bfa/bfad_fwimg.c
Normal file
95
drivers/scsi/bfa/bfad_fwimg.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfad_fwimg.c Linux driver PCI interface module.
|
||||
*/
|
||||
#include <bfa_os_inc.h>
|
||||
#include <bfad_drv.h>
|
||||
#include <bfad_im_compat.h>
|
||||
#include <defs/bfa_defs_version.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/fcntl.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <bfa_fwimg_priv.h>
|
||||
#include <bfa.h>
|
||||
|
||||
u32 bfi_image_ct_size;
|
||||
u32 bfi_image_cb_size;
|
||||
u32 *bfi_image_ct;
|
||||
u32 *bfi_image_cb;
|
||||
|
||||
|
||||
#define BFAD_FW_FILE_CT "ctfw.bin"
|
||||
#define BFAD_FW_FILE_CB "cbfw.bin"
|
||||
|
||||
u32 *
|
||||
bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
|
||||
u32 *bfi_image_size, char *fw_name)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
|
||||
if (request_firmware(&fw, fw_name, &pdev->dev)) {
|
||||
printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*bfi_image = vmalloc(fw->size);
|
||||
if (NULL == *bfi_image) {
|
||||
printk(KERN_ALERT "Fail to allocate buffer for fw image "
|
||||
"size=%x!\n", (u32) fw->size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(*bfi_image, fw->data, fw->size);
|
||||
*bfi_image_size = fw->size/sizeof(u32);
|
||||
|
||||
return(*bfi_image);
|
||||
|
||||
error:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
u32 *
|
||||
bfad_get_firmware_buf(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
|
||||
if (bfi_image_ct_size == 0)
|
||||
bfad_read_firmware(pdev, &bfi_image_ct,
|
||||
&bfi_image_ct_size, BFAD_FW_FILE_CT);
|
||||
return(bfi_image_ct);
|
||||
} else {
|
||||
if (bfi_image_cb_size == 0)
|
||||
bfad_read_firmware(pdev, &bfi_image_cb,
|
||||
&bfi_image_cb_size, BFAD_FW_FILE_CB);
|
||||
return(bfi_image_cb);
|
||||
}
|
||||
}
|
||||
|
||||
u32 *
|
||||
bfi_image_ct_get_chunk(u32 off)
|
||||
{ return (u32 *)(bfi_image_ct + off); }
|
||||
|
||||
u32 *
|
||||
bfi_image_cb_get_chunk(u32 off)
|
||||
{ return (u32 *)(bfi_image_cb + off); }
|
||||
|
1230
drivers/scsi/bfa/bfad_im.c
Normal file
1230
drivers/scsi/bfa/bfad_im.c
Normal file
File diff suppressed because it is too large
Load Diff
150
drivers/scsi/bfa/bfad_im.h
Normal file
150
drivers/scsi/bfa/bfad_im.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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_IM_H__
|
||||
#define __BFAD_IM_H__
|
||||
|
||||
#include "fcs/bfa_fcs_fcpim.h"
|
||||
#include "bfad_im_compat.h"
|
||||
|
||||
#define FCPI_NAME " fcpim"
|
||||
|
||||
void bfad_flags_set(struct bfad_s *bfad, u32 flags);
|
||||
bfa_status_t bfad_im_module_init(void);
|
||||
void bfad_im_module_exit(void);
|
||||
bfa_status_t bfad_im_probe(struct bfad_s *bfad);
|
||||
void bfad_im_probe_undo(struct bfad_s *bfad);
|
||||
void bfad_im_probe_post(struct bfad_im_s *im);
|
||||
bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
|
||||
void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
|
||||
void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
|
||||
void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
|
||||
void bfad_im_port_clean(struct bfad_im_port_s *im_port);
|
||||
int bfad_im_scsi_host_alloc(struct bfad_s *bfad,
|
||||
struct bfad_im_port_s *im_port);
|
||||
void bfad_im_scsi_host_free(struct bfad_s *bfad,
|
||||
struct bfad_im_port_s *im_port);
|
||||
|
||||
#define MAX_FCP_TARGET 1024
|
||||
#define MAX_FCP_LUN 16384
|
||||
#define BFAD_TARGET_RESET_TMO 60
|
||||
#define BFAD_LUN_RESET_TMO 60
|
||||
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
||||
#define BFA_QUEUE_FULL_RAMP_UP_TIME 120
|
||||
#define BFAD_KOBJ_NAME_LEN 20
|
||||
|
||||
/*
|
||||
* itnim flags
|
||||
*/
|
||||
#define ITNIM_MAPPED 0x00000001
|
||||
|
||||
#define SCSI_TASK_MGMT 0x00000001
|
||||
#define IO_DONE_BIT 0
|
||||
|
||||
struct bfad_itnim_data_s {
|
||||
struct bfad_itnim_s *itnim;
|
||||
};
|
||||
|
||||
struct bfad_im_port_s {
|
||||
struct bfad_s *bfad;
|
||||
struct bfad_port_s *port;
|
||||
struct work_struct port_delete_work;
|
||||
int idr_id;
|
||||
u16 cur_scsi_id;
|
||||
struct list_head binding_list;
|
||||
struct Scsi_Host *shost;
|
||||
struct list_head itnim_mapped_list;
|
||||
};
|
||||
|
||||
enum bfad_itnim_state {
|
||||
ITNIM_STATE_NONE,
|
||||
ITNIM_STATE_ONLINE,
|
||||
ITNIM_STATE_OFFLINE_PENDING,
|
||||
ITNIM_STATE_OFFLINE,
|
||||
ITNIM_STATE_TIMEOUT,
|
||||
ITNIM_STATE_FREE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Per itnim data structure
|
||||
*/
|
||||
struct bfad_itnim_s {
|
||||
struct list_head list_entry;
|
||||
struct bfa_fcs_itnim_s fcs_itnim;
|
||||
struct work_struct itnim_work;
|
||||
u32 flags;
|
||||
enum bfad_itnim_state state;
|
||||
struct bfad_im_s *im;
|
||||
struct bfad_im_port_s *im_port;
|
||||
struct bfad_rport_s *drv_rport;
|
||||
struct fc_rport *fc_rport;
|
||||
struct bfa_itnim_s *bfa_itnim;
|
||||
u16 scsi_tgt_id;
|
||||
u16 queue_work;
|
||||
unsigned long last_ramp_up_time;
|
||||
unsigned long last_queue_full_time;
|
||||
};
|
||||
|
||||
enum bfad_binding_type {
|
||||
FCP_PWWN_BINDING = 0x1,
|
||||
FCP_NWWN_BINDING = 0x2,
|
||||
FCP_FCID_BINDING = 0x3,
|
||||
};
|
||||
|
||||
struct bfad_fcp_binding {
|
||||
struct list_head list_entry;
|
||||
enum bfad_binding_type binding_type;
|
||||
u16 scsi_target_id;
|
||||
u32 fc_id;
|
||||
wwn_t nwwn;
|
||||
wwn_t pwwn;
|
||||
};
|
||||
|
||||
struct bfad_im_s {
|
||||
struct bfad_s *bfad;
|
||||
struct workqueue_struct *drv_workq;
|
||||
char drv_workq_name[BFAD_KOBJ_NAME_LEN];
|
||||
};
|
||||
|
||||
struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
|
||||
struct bfad_s *);
|
||||
bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
|
||||
void bfad_os_destroy_workq(struct bfad_im_s *im);
|
||||
void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv);
|
||||
void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
|
||||
void bfad_os_init_work(struct bfad_im_port_s *im_port);
|
||||
void bfad_os_scsi_host_free(struct bfad_s *bfad,
|
||||
struct bfad_im_port_s *im_port);
|
||||
void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim,
|
||||
struct scsi_device *sdev);
|
||||
void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
|
||||
struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
|
||||
int bfad_os_scsi_add_host(struct Scsi_Host *shost,
|
||||
struct bfad_im_port_s *im_port, struct bfad_s *bfad);
|
||||
|
||||
/*
|
||||
* scsi_host_template entries
|
||||
*/
|
||||
void bfad_im_itnim_unmap(struct bfad_im_port_s *im_port,
|
||||
struct bfad_itnim_s *itnim);
|
||||
|
||||
extern struct scsi_host_template bfad_im_scsi_host_template;
|
||||
extern struct scsi_host_template bfad_im_vport_template;
|
||||
extern struct fc_function_template bfad_im_fc_function_template;
|
||||
extern struct scsi_transport_template *bfad_im_scsi_transport_template;
|
||||
|
||||
#endif
|
46
drivers/scsi/bfa/bfad_im_compat.h
Normal file
46
drivers/scsi/bfa/bfad_im_compat.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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_IM_COMPAT_H__
|
||||
#define __BFAD_IM_COMPAT_H__
|
||||
|
||||
extern u32 *bfi_image_buf;
|
||||
extern u32 bfi_image_size;
|
||||
|
||||
extern struct device_attribute *bfad_im_host_attrs[];
|
||||
extern struct device_attribute *bfad_im_vport_attrs[];
|
||||
|
||||
u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
|
||||
u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
|
||||
u32 *bfi_image_size, char *fw_name);
|
||||
|
||||
static inline u32 *
|
||||
bfad_load_fwimg(struct pci_dev *pdev)
|
||||
{
|
||||
return(bfad_get_firmware_buf(pdev));
|
||||
}
|
||||
|
||||
static inline void
|
||||
bfad_free_fwimg(void)
|
||||
{
|
||||
if (bfi_image_ct_size && bfi_image_ct)
|
||||
vfree(bfi_image_ct);
|
||||
if (bfi_image_cb_size && bfi_image_cb)
|
||||
vfree(bfi_image_cb);
|
||||
}
|
||||
|
||||
#endif
|
214
drivers/scsi/bfa/bfad_intr.c
Normal file
214
drivers/scsi/bfa/bfad_intr.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 "bfad_drv.h"
|
||||
#include "bfad_trcmod.h"
|
||||
|
||||
BFA_TRC_FILE(LDRV, INTR);
|
||||
|
||||
/**
|
||||
* bfa_isr BFA driver interrupt functions
|
||||
*/
|
||||
irqreturn_t bfad_intx(int irq, void *dev_id);
|
||||
static int msix_disable;
|
||||
module_param(msix_disable, int, S_IRUGO | S_IWUSR);
|
||||
/**
|
||||
* Line based interrupt handler.
|
||||
*/
|
||||
irqreturn_t
|
||||
bfad_intx(int irq, void *dev_id)
|
||||
{
|
||||
struct bfad_s *bfad = dev_id;
|
||||
struct list_head doneq;
|
||||
unsigned long flags;
|
||||
bfa_boolean_t rc;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
rc = bfa_intx(&bfad->bfa);
|
||||
if (!rc) {
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
bfa_comp_deq(&bfad->bfa, &doneq);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
if (!list_empty(&doneq)) {
|
||||
bfa_comp_process(&bfad->bfa, &doneq);
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_comp_free(&bfad->bfa, &doneq);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
bfa_trc_fp(bfad, irq);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
bfad_msix(int irq, void *dev_id)
|
||||
{
|
||||
struct bfad_msix_s *vec = dev_id;
|
||||
struct bfad_s *bfad = vec->bfad;
|
||||
struct list_head doneq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
|
||||
bfa_msix(&bfad->bfa, vec->msix.entry);
|
||||
bfa_comp_deq(&bfad->bfa, &doneq);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
|
||||
if (!list_empty(&doneq)) {
|
||||
bfa_comp_process(&bfad->bfa, &doneq);
|
||||
|
||||
spin_lock_irqsave(&bfad->bfad_lock, flags);
|
||||
bfa_comp_free(&bfad->bfa, &doneq);
|
||||
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the MSIX entry table.
|
||||
*/
|
||||
static void
|
||||
bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
|
||||
int mask, int max_bit)
|
||||
{
|
||||
int i;
|
||||
int match = 0x00000001;
|
||||
|
||||
for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
|
||||
if (mask & match) {
|
||||
bfad->msix_tab[bfad->nvec].msix.entry = i;
|
||||
bfad->msix_tab[bfad->nvec].bfad = bfad;
|
||||
msix_entries[bfad->nvec].entry = i;
|
||||
bfad->nvec++;
|
||||
}
|
||||
|
||||
match <<= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
bfad_install_msix_handler(struct bfad_s *bfad)
|
||||
{
|
||||
int i, error = 0;
|
||||
|
||||
for (i = 0; i < bfad->nvec; i++) {
|
||||
error = request_irq(bfad->msix_tab[i].msix.vector,
|
||||
(irq_handler_t) bfad_msix, 0,
|
||||
BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
|
||||
bfa_trc(bfad, i);
|
||||
bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
|
||||
if (error) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
free_irq(bfad->msix_tab[j].msix.vector,
|
||||
&bfad->msix_tab[j]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup MSIX based interrupt.
|
||||
*/
|
||||
int
|
||||
bfad_setup_intr(struct bfad_s *bfad)
|
||||
{
|
||||
int error = 0;
|
||||
u32 mask = 0, i, num_bit = 0, max_bit = 0;
|
||||
struct msix_entry msix_entries[MAX_MSIX_ENTRY];
|
||||
|
||||
/* Call BFA to get the msix map for this PCI function. */
|
||||
bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
|
||||
|
||||
/* Set up the msix entry table */
|
||||
bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
|
||||
|
||||
if (!msix_disable) {
|
||||
error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
|
||||
if (error) {
|
||||
/*
|
||||
* Only error number of vector is available.
|
||||
* We don't have a mechanism to map multiple
|
||||
* interrupts into one vector, so even if we
|
||||
* can try to request less vectors, we don't
|
||||
* know how to associate interrupt events to
|
||||
* vectors. Linux doesn't dupicate vectors
|
||||
* in the MSIX table for this case.
|
||||
*/
|
||||
|
||||
printk(KERN_WARNING "bfad%d: "
|
||||
"pci_enable_msix failed (%d),"
|
||||
" use line based.\n", bfad->inst_no, error);
|
||||
|
||||
goto line_based;
|
||||
}
|
||||
|
||||
/* Save the vectors */
|
||||
for (i = 0; i < bfad->nvec; i++) {
|
||||
bfa_trc(bfad, msix_entries[i].vector);
|
||||
bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
|
||||
}
|
||||
|
||||
bfa_msix_init(&bfad->bfa, bfad->nvec);
|
||||
|
||||
bfad->bfad_flags |= BFAD_MSIX_ON;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
line_based:
|
||||
error = 0;
|
||||
if (request_irq
|
||||
(bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
|
||||
BFAD_DRIVER_NAME, bfad) != 0) {
|
||||
/* Enable interrupt handler failed */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
bfad_remove_intr(struct bfad_s *bfad)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bfad->bfad_flags & BFAD_MSIX_ON) {
|
||||
for (i = 0; i < bfad->nvec; i++)
|
||||
free_irq(bfad->msix_tab[i].msix.vector,
|
||||
&bfad->msix_tab[i]);
|
||||
|
||||
pci_disable_msix(bfad->pcidev);
|
||||
bfad->bfad_flags &= ~BFAD_MSIX_ON;
|
||||
} else {
|
||||
free_irq(bfad->pcidev->irq, bfad);
|
||||
}
|
||||
}
|
||||
|
||||
|
42
drivers/scsi/bfa/bfad_ipfc.h
Normal file
42
drivers/scsi/bfa/bfad_ipfc.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __BFA_DRV_IPFC_H__
|
||||
#define __BFA_DRV_IPFC_H__
|
||||
|
||||
|
||||
#define IPFC_NAME ""
|
||||
|
||||
#define bfad_ipfc_module_init(x) do {} while (0)
|
||||
#define bfad_ipfc_module_exit(x) do {} while (0)
|
||||
#define bfad_ipfc_probe(x) do {} while (0)
|
||||
#define bfad_ipfc_probe_undo(x) do {} while (0)
|
||||
#define bfad_ipfc_port_config(x, y) BFA_STATUS_OK
|
||||
#define bfad_ipfc_port_unconfig(x, y) do {} while (0)
|
||||
|
||||
#define bfad_ipfc_probe_post(x) do {} while (0)
|
||||
#define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK
|
||||
#define bfad_ipfc_port_delete(x, y) do {} while (0)
|
||||
#define bfad_ipfc_port_online(x, y) do {} while (0)
|
||||
#define bfad_ipfc_port_offline(x, y) do {} while (0)
|
||||
|
||||
#define bfad_ip_get_attr(x) BFA_STATUS_FAILED
|
||||
#define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED
|
||||
#define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED
|
||||
#define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED
|
||||
|
||||
|
||||
#endif
|
50
drivers/scsi/bfa/bfad_os.c
Normal file
50
drivers/scsi/bfa/bfad_os.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfad_os.c Linux driver OS specific calls.
|
||||
*/
|
||||
|
||||
#include "bfa_os_inc.h"
|
||||
#include "bfad_drv.h"
|
||||
|
||||
void
|
||||
bfa_os_gettimeofday(struct bfa_timeval_s *tv)
|
||||
{
|
||||
struct timeval tmp_tv;
|
||||
|
||||
do_gettimeofday(&tmp_tv);
|
||||
tv->tv_sec = (u32) tmp_tv.tv_sec;
|
||||
tv->tv_usec = (u32) tmp_tv.tv_usec;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
#define BFA_STRING_256 256
|
||||
char tmp[BFA_STRING_256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(tmp, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
printk(tmp);
|
||||
}
|
||||
|
||||
|
59
drivers/scsi/bfa/bfad_tm.h
Normal file
59
drivers/scsi/bfa/bfad_tm.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Brocade Fibre Channel HBA Linux Target Mode Driver
|
||||
*/
|
||||
|
||||
/**
|
||||
* tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module.
|
||||
*/
|
||||
|
||||
#ifndef __BFAD_TM_H__
|
||||
#define __BFAD_TM_H__
|
||||
|
||||
#include <defs/bfa_defs_status.h>
|
||||
|
||||
#define FCPT_NAME ""
|
||||
|
||||
/*
|
||||
* Called from base Linux driver on (De)Init events
|
||||
*/
|
||||
|
||||
/* attach tgt template with scst */
|
||||
#define bfad_tm_module_init() do {} while (0)
|
||||
|
||||
/* detach/release tgt template */
|
||||
#define bfad_tm_module_exit() do {} while (0)
|
||||
|
||||
#define bfad_tm_probe(x) do {} while (0)
|
||||
#define bfad_tm_probe_undo(x) do {} while (0)
|
||||
#define bfad_tm_probe_post(x) do {} while (0)
|
||||
|
||||
/*
|
||||
* Called by base Linux driver but triggered by BFA FCS on config events
|
||||
*/
|
||||
#define bfad_tm_port_new(x, y) BFA_STATUS_OK
|
||||
#define bfad_tm_port_delete(x, y) do {} while (0)
|
||||
|
||||
/*
|
||||
* Called by base Linux driver but triggered by BFA FCS on PLOGI/O events
|
||||
*/
|
||||
#define bfad_tm_port_online(x, y) do {} while (0)
|
||||
#define bfad_tm_port_offline(x, y) do {} while (0)
|
||||
|
||||
#endif
|
52
drivers/scsi/bfa/bfad_trcmod.h
Normal file
52
drivers/scsi/bfa/bfad_trcmod.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfad_trcmod.h Linux driver trace modules
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BFAD_TRCMOD_H__
|
||||
#define __BFAD_TRCMOD_H__
|
||||
|
||||
#include <cs/bfa_trc.h>
|
||||
|
||||
/*
|
||||
* !!! Only append to the enums defined here to avoid any versioning
|
||||
* !!! needed between trace utility and driver version
|
||||
*/
|
||||
enum {
|
||||
/* 2.6 Driver */
|
||||
BFA_TRC_LDRV_BFAD = 1,
|
||||
BFA_TRC_LDRV_BFAD_2_6 = 2,
|
||||
BFA_TRC_LDRV_BFAD_2_6_9 = 3,
|
||||
BFA_TRC_LDRV_BFAD_2_6_10 = 4,
|
||||
BFA_TRC_LDRV_INTR = 5,
|
||||
BFA_TRC_LDRV_IOCTL = 6,
|
||||
BFA_TRC_LDRV_OS = 7,
|
||||
BFA_TRC_LDRV_IM = 8,
|
||||
BFA_TRC_LDRV_IM_2_6 = 9,
|
||||
BFA_TRC_LDRV_IM_2_6_9 = 10,
|
||||
BFA_TRC_LDRV_IM_2_6_10 = 11,
|
||||
BFA_TRC_LDRV_TM = 12,
|
||||
BFA_TRC_LDRV_IPFC = 13,
|
||||
BFA_TRC_LDRV_IM_2_4 = 14,
|
||||
BFA_TRC_LDRV_IM_VMW = 15,
|
||||
BFA_TRC_LDRV_IM_LT_2_6_10 = 16,
|
||||
};
|
||||
|
||||
#endif /* __BFAD_TRCMOD_H__ */
|
62
drivers/scsi/bfa/fab.c
Normal file
62
drivers/scsi/bfa/fab.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 <bfa.h>
|
||||
#include <bfa_svc.h>
|
||||
#include "fcs_lport.h"
|
||||
#include "fcs_rport.h"
|
||||
#include "lport_priv.h"
|
||||
|
||||
/**
|
||||
* fab.c port fab implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* bfa_fcs_port_fab_public port fab public functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called by port to initialize fabric services of the base port.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_fcs_port_ns_init(port);
|
||||
bfa_fcs_port_scn_init(port);
|
||||
bfa_fcs_port_ms_init(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by port to notify transition to online state.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_fcs_port_ns_online(port);
|
||||
bfa_fcs_port_scn_online(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by port to notify transition to offline state.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port)
|
||||
{
|
||||
bfa_fcs_port_ns_offline(port);
|
||||
bfa_fcs_port_scn_offline(port);
|
||||
bfa_fcs_port_ms_offline(port);
|
||||
}
|
1278
drivers/scsi/bfa/fabric.c
Normal file
1278
drivers/scsi/bfa/fabric.c
Normal file
File diff suppressed because it is too large
Load Diff
1449
drivers/scsi/bfa/fcbuild.c
Normal file
1449
drivers/scsi/bfa/fcbuild.c
Normal file
File diff suppressed because it is too large
Load Diff
273
drivers/scsi/bfa/fcbuild.h
Normal file
273
drivers/scsi/bfa/fcbuild.h
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
/*
|
||||
* fcbuild.h - FC link service frame building and parsing routines
|
||||
*/
|
||||
|
||||
#ifndef __FCBUILD_H__
|
||||
#define __FCBUILD_H__
|
||||
|
||||
#include <bfa_os_inc.h>
|
||||
#include <protocol/fc.h>
|
||||
#include <protocol/fcp.h>
|
||||
#include <protocol/ct.h>
|
||||
#include <defs/bfa_defs_port.h>
|
||||
#include <defs/bfa_defs_pport.h>
|
||||
|
||||
/*
|
||||
* Utility Macros/functions
|
||||
*/
|
||||
|
||||
#define fcif_sof_set(_ifhdr, _sof) (_ifhdr)->sof = FC_ ## _sof
|
||||
#define fcif_eof_set(_ifhdr, _eof) (_ifhdr)->eof = FC_ ## _eof
|
||||
|
||||
#define wwn_is_equal(_wwn1, _wwn2) \
|
||||
(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
|
||||
|
||||
#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
|
||||
|
||||
/*
|
||||
* Given the fc response length, this routine will return
|
||||
* the length of the actual payload bytes following the CT header.
|
||||
*
|
||||
* Assumes the input response length does not include the crc, eof, etc.
|
||||
*/
|
||||
static inline u32
|
||||
fc_get_ctresp_pyld_len(u32 resp_len)
|
||||
{
|
||||
return (resp_len - sizeof(struct ct_hdr_s));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert bfa speed to rpsc speed value.
|
||||
*/
|
||||
static inline enum bfa_pport_speed
|
||||
fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed)
|
||||
{
|
||||
switch (speed) {
|
||||
|
||||
case RPSC_OP_SPEED_1G:
|
||||
return BFA_PPORT_SPEED_1GBPS;
|
||||
|
||||
case RPSC_OP_SPEED_2G:
|
||||
return BFA_PPORT_SPEED_2GBPS;
|
||||
|
||||
case RPSC_OP_SPEED_4G:
|
||||
return BFA_PPORT_SPEED_4GBPS;
|
||||
|
||||
case RPSC_OP_SPEED_8G:
|
||||
return BFA_PPORT_SPEED_8GBPS;
|
||||
|
||||
default:
|
||||
return BFA_PPORT_SPEED_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert RPSC speed to bfa speed value.
|
||||
*/
|
||||
static inline enum fc_rpsc_op_speed_s
|
||||
fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed)
|
||||
{
|
||||
switch (op_speed) {
|
||||
|
||||
case BFA_PPORT_SPEED_1GBPS:
|
||||
return RPSC_OP_SPEED_1G;
|
||||
|
||||
case BFA_PPORT_SPEED_2GBPS:
|
||||
return RPSC_OP_SPEED_2G;
|
||||
|
||||
case BFA_PPORT_SPEED_4GBPS:
|
||||
return RPSC_OP_SPEED_4G;
|
||||
|
||||
case BFA_PPORT_SPEED_8GBPS:
|
||||
return RPSC_OP_SPEED_8G;
|
||||
|
||||
default:
|
||||
return RPSC_OP_SPEED_NOT_EST;
|
||||
}
|
||||
}
|
||||
enum fc_parse_status {
|
||||
FC_PARSE_OK = 0,
|
||||
FC_PARSE_FAILURE = 1,
|
||||
FC_PARSE_BUSY = 2,
|
||||
FC_PARSE_LEN_INVAL,
|
||||
FC_PARSE_ACC_INVAL,
|
||||
FC_PARSE_PWWN_NOT_EQUAL,
|
||||
FC_PARSE_NWWN_NOT_EQUAL,
|
||||
FC_PARSE_RXSZ_INVAL,
|
||||
FC_PARSE_NOT_FCP,
|
||||
FC_PARSE_OPAFLAG_INVAL,
|
||||
FC_PARSE_RPAFLAG_INVAL,
|
||||
FC_PARSE_OPA_INVAL,
|
||||
FC_PARSE_RPA_INVAL,
|
||||
|
||||
};
|
||||
|
||||
struct fc_templates_s {
|
||||
struct fchs_s fc_els_req;
|
||||
struct fchs_s fc_bls_req;
|
||||
struct fc_logi_s plogi;
|
||||
struct fc_rrq_s rrq;
|
||||
};
|
||||
|
||||
void fcbuild_init(void);
|
||||
|
||||
u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
|
||||
u32 s_id, u16 ox_id, wwn_t port_name,
|
||||
wwn_t node_name, u16 pdu_size, u8 set_npiv,
|
||||
u8 set_auth, u16 local_bb_credits);
|
||||
u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi,
|
||||
u32 s_id, u16 ox_id, wwn_t port_name,
|
||||
wwn_t node_name, u16 pdu_size);
|
||||
u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
|
||||
u32 s_id, u16 ox_id, wwn_t port_name,
|
||||
wwn_t node_name, u16 pdu_size,
|
||||
u16 local_bb_credits);
|
||||
u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
|
||||
u32 s_id, u16 ox_id, wwn_t port_name,
|
||||
wwn_t node_name, u16 pdu_size);
|
||||
enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
|
||||
u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
|
||||
u16 ox_id);
|
||||
enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
|
||||
u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
|
||||
u32 s_id, u16 ox_id, u16 rrq_oxid);
|
||||
enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
|
||||
u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
|
||||
u16 ox_id, u8 *name);
|
||||
u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
|
||||
u16 ox_id, enum bfa_port_role role);
|
||||
u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u16 ox_id, u8 *fc4_bitmap,
|
||||
u32 bitmap_size);
|
||||
u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
|
||||
u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u16 ox_id, wwn_t port_name);
|
||||
u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
|
||||
u16 ox_id, u32 port_id);
|
||||
u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
|
||||
u8 set_br_reg, u32 s_id, u16 ox_id);
|
||||
u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
|
||||
u32 s_id, u16 ox_id,
|
||||
wwn_t port_name, wwn_t node_name, u16 pdu_size);
|
||||
|
||||
u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
wwn_t port_name, wwn_t node_name);
|
||||
enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
|
||||
u32 host_dap,
|
||||
wwn_t node_name, wwn_t port_name);
|
||||
enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
|
||||
wwn_t port_name, wwn_t node_name);
|
||||
u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
wwn_t port_name, wwn_t node_name);
|
||||
u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
u8 reason_code, u8 reason_code_expl);
|
||||
u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
|
||||
u32 d_id, u32 s_id, u16 ox_id);
|
||||
u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
|
||||
u32 s_id, u16 ox_id);
|
||||
enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
|
||||
|
||||
u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
|
||||
u32 s_id, u16 ox_id,
|
||||
enum bfa_port_role role);
|
||||
u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
u32 data_format);
|
||||
u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
u32 data_format,
|
||||
struct fc_rnid_common_id_data_s *common_id_data,
|
||||
struct fc_rnid_general_topology_data_s *
|
||||
gen_topo_data);
|
||||
u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
|
||||
u32 d_id, u32 s_id,
|
||||
u32 *pid_list, u16 npids);
|
||||
u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
|
||||
u32 d_id, u32 s_id, u16 ox_id);
|
||||
u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
struct fc_rpsc_speed_info_s *oper_speed);
|
||||
u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
|
||||
u8 fc4_type);
|
||||
u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u32 port_id, wwn_t port_name);
|
||||
u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u32 port_id, wwn_t node_name);
|
||||
u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u32 port_id, u32 cos);
|
||||
u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u32 port_id, u8 port_type);
|
||||
u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u32 port_id);
|
||||
u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
wwn_t port_name);
|
||||
u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
|
||||
u32 s_id, u16 ox_id);
|
||||
u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u16 cmd_code);
|
||||
u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
wwn_t wwn);
|
||||
u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
wwn_t wwn);
|
||||
void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
|
||||
void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
|
||||
u16 ox_id);
|
||||
enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
|
||||
enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
|
||||
wwn_t port_name);
|
||||
enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
|
||||
enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
|
||||
wwn_t port_name);
|
||||
u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
u16 rx_id);
|
||||
int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
|
||||
u16 fc_tprlo_acc_build(struct fchs_s *fchs,
|
||||
struct fc_tprlo_acc_s *tprlo_acc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
int num_pages);
|
||||
u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
|
||||
u32 d_id, u32 s_id, u16 ox_id,
|
||||
int num_pages);
|
||||
u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
|
||||
u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
|
||||
u16 ox_id, wwn_t port_name, wwn_t node_name,
|
||||
u16 pdu_size);
|
||||
u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
|
||||
u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
|
||||
u16 ox_id, int num_pages);
|
||||
u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
|
||||
u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
|
||||
u16 ox_id, int num_pages,
|
||||
enum fc_tprlo_type tprlo_type, u32 tpr_id);
|
||||
u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
|
||||
u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
|
||||
u16 ox_id, u32 reason_code,
|
||||
u32 reason_expl);
|
||||
u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
|
||||
u16 ox_id, u32 port_id);
|
||||
u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
|
||||
u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
|
||||
u32 s_id, u16 ox_id);
|
||||
#endif
|
844
drivers/scsi/bfa/fcpim.c
Normal file
844
drivers/scsi/bfa/fcpim.c
Normal file
@ -0,0 +1,844 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcpim.c - FCP initiator mode i-t nexus state machine
|
||||
*/
|
||||
|
||||
#include <bfa.h>
|
||||
#include <bfa_svc.h>
|
||||
#include "fcs_fcpim.h"
|
||||
#include "fcs_rport.h"
|
||||
#include "fcs_lport.h"
|
||||
#include "fcs_trcmod.h"
|
||||
#include "fcs_fcxp.h"
|
||||
#include "fcs.h"
|
||||
#include <fcs/bfa_fcs_fcpim.h>
|
||||
#include <fcb/bfa_fcb_fcpim.h>
|
||||
#include <aen/bfa_aen_itnim.h>
|
||||
|
||||
BFA_TRC_FILE(FCS, FCPIM);
|
||||
|
||||
/*
|
||||
* forward declarations
|
||||
*/
|
||||
static void bfa_fcs_itnim_timeout(void *arg);
|
||||
static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
|
||||
static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
|
||||
struct bfa_fcxp_s *fcxp_alloced);
|
||||
static void bfa_fcs_itnim_prli_response(void *fcsarg,
|
||||
struct bfa_fcxp_s *fcxp,
|
||||
void *cbarg,
|
||||
bfa_status_t req_status,
|
||||
u32 rsp_len,
|
||||
u32 resid_len,
|
||||
struct fchs_s *rsp_fchs);
|
||||
static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_itnim_aen_event event);
|
||||
|
||||
/**
|
||||
* fcs_itnim_sm FCS itnim state machine events
|
||||
*/
|
||||
|
||||
enum bfa_fcs_itnim_event {
|
||||
BFA_FCS_ITNIM_SM_ONLINE = 1, /* rport online event */
|
||||
BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
|
||||
BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
|
||||
BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
|
||||
BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
|
||||
BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
|
||||
BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
|
||||
BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
|
||||
BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
|
||||
BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
|
||||
BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
|
||||
};
|
||||
|
||||
static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event);
|
||||
|
||||
static struct bfa_sm_table_s itnim_sm_table[] = {
|
||||
{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
|
||||
{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
|
||||
};
|
||||
|
||||
/**
|
||||
* fcs_itnim_sm FCS itnim state machine
|
||||
*/
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_ONLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
|
||||
bfa_fcs_itnim_send_prli(itnim, NULL);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_INITIATOR:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_FRMSENT:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_INITIATOR:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
|
||||
bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_RSP_OK:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
|
||||
bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_RSP_ERROR:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
|
||||
bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
|
||||
bfa_fcs_itnim_timeout, itnim,
|
||||
BFA_FCS_RETRY_TIMEOUT);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcxp_discard(itnim->fcxp);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_INITIATOR:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
|
||||
/*
|
||||
* dont discard fcxp. accept will reach same state
|
||||
*/
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcxp_discard(itnim->fcxp);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_TIMEOUT:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
|
||||
bfa_fcs_itnim_send_prli(itnim, NULL);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_timer_stop(&itnim->timer);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_INITIATOR:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
|
||||
bfa_timer_stop(&itnim->timer);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_timer_stop(&itnim->timer);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_HCB_ONLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
|
||||
bfa_fcb_itnim_online(itnim->itnim_drv);
|
||||
bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_itnim_offline(itnim->bfa_itnim);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
|
||||
bfa_fcb_itnim_offline(itnim->itnim_drv);
|
||||
bfa_itnim_offline(itnim->bfa_itnim);
|
||||
if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE) {
|
||||
bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
|
||||
} else {
|
||||
bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
|
||||
}
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This state is set when a discovered rport is also in intiator mode.
|
||||
* This ITN is marked as no_op and is not active and will not be truned into
|
||||
* online state.
|
||||
*/
|
||||
static void
|
||||
bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_fcs_itnim_event event)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_trc(itnim->fcs, event);
|
||||
|
||||
switch (event) {
|
||||
case BFA_FCS_ITNIM_SM_OFFLINE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_rport_itnim_ack(itnim->rport);
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_RSP_ERROR:
|
||||
case BFA_FCS_ITNIM_SM_ONLINE:
|
||||
case BFA_FCS_ITNIM_SM_INITIATOR:
|
||||
break;
|
||||
|
||||
case BFA_FCS_ITNIM_SM_DELETE:
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
bfa_fcs_itnim_free(itnim);
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* itnim_private FCS ITNIM private interfaces
|
||||
*/
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
|
||||
enum bfa_itnim_aen_event event)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport = itnim->rport;
|
||||
union bfa_aen_data_u aen_data;
|
||||
struct bfa_log_mod_s *logmod = rport->fcs->logm;
|
||||
wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
|
||||
wwn_t rpwwn = rport->pwwn;
|
||||
char lpwwn_ptr[BFA_STRING_32];
|
||||
char rpwwn_ptr[BFA_STRING_32];
|
||||
|
||||
/*
|
||||
* Don't post events for well known addresses
|
||||
*/
|
||||
if (BFA_FCS_PID_IS_WKA(rport->pid))
|
||||
return;
|
||||
|
||||
wwn2str(lpwwn_ptr, lpwwn);
|
||||
wwn2str(rpwwn_ptr, rpwwn);
|
||||
|
||||
switch (event) {
|
||||
case BFA_ITNIM_AEN_ONLINE:
|
||||
bfa_log(logmod, BFA_AEN_ITNIM_ONLINE, rpwwn_ptr, lpwwn_ptr);
|
||||
break;
|
||||
case BFA_ITNIM_AEN_OFFLINE:
|
||||
bfa_log(logmod, BFA_AEN_ITNIM_OFFLINE, rpwwn_ptr, lpwwn_ptr);
|
||||
break;
|
||||
case BFA_ITNIM_AEN_DISCONNECT:
|
||||
bfa_log(logmod, BFA_AEN_ITNIM_DISCONNECT, rpwwn_ptr, lpwwn_ptr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
aen_data.itnim.vf_id = rport->port->fabric->vf_id;
|
||||
aen_data.itnim.ppwwn =
|
||||
bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
|
||||
aen_data.itnim.lpwwn = lpwwn;
|
||||
aen_data.itnim.rpwwn = rpwwn;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
|
||||
struct bfa_fcs_rport_s *rport = itnim->rport;
|
||||
struct bfa_fcs_port_s *port = rport->port;
|
||||
struct fchs_s fchs;
|
||||
struct bfa_fcxp_s *fcxp;
|
||||
int len;
|
||||
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
|
||||
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
|
||||
if (!fcxp) {
|
||||
itnim->stats.fcxp_alloc_wait++;
|
||||
bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
|
||||
bfa_fcs_itnim_send_prli, itnim);
|
||||
return;
|
||||
}
|
||||
itnim->fcxp = fcxp;
|
||||
|
||||
len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
|
||||
bfa_fcs_port_get_fcid(port), 0);
|
||||
|
||||
bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
|
||||
BFA_FALSE, FC_CLASS_3, len, &fchs,
|
||||
bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
|
||||
FC_RA_TOV);
|
||||
|
||||
itnim->stats.prli_sent++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
|
||||
bfa_status_t req_status, u32 rsp_len,
|
||||
u32 resid_len, struct fchs_s *rsp_fchs)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
|
||||
struct fc_els_cmd_s *els_cmd;
|
||||
struct fc_prli_s *prli_resp;
|
||||
struct fc_ls_rjt_s *ls_rjt;
|
||||
struct fc_prli_params_s *sparams;
|
||||
|
||||
bfa_trc(itnim->fcs, req_status);
|
||||
|
||||
/*
|
||||
* Sanity Checks
|
||||
*/
|
||||
if (req_status != BFA_STATUS_OK) {
|
||||
itnim->stats.prli_rsp_err++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
|
||||
|
||||
if (els_cmd->els_code == FC_ELS_ACC) {
|
||||
prli_resp = (struct fc_prli_s *) els_cmd;
|
||||
|
||||
if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
|
||||
bfa_trc(itnim->fcs, rsp_len);
|
||||
/*
|
||||
* Check if this r-port is also in Initiator mode.
|
||||
* If so, we need to set this ITN as a no-op.
|
||||
*/
|
||||
if (prli_resp->parampage.servparams.initiator) {
|
||||
bfa_trc(itnim->fcs, prli_resp->parampage.type);
|
||||
itnim->rport->scsi_function =
|
||||
BFA_RPORT_INITIATOR;
|
||||
itnim->stats.prli_rsp_acc++;
|
||||
bfa_sm_send_event(itnim,
|
||||
BFA_FCS_ITNIM_SM_INITIATOR);
|
||||
return;
|
||||
}
|
||||
|
||||
itnim->stats.prli_rsp_parse_err++;
|
||||
return;
|
||||
}
|
||||
itnim->rport->scsi_function = BFA_RPORT_TARGET;
|
||||
|
||||
sparams = &prli_resp->parampage.servparams;
|
||||
itnim->seq_rec = sparams->retry;
|
||||
itnim->rec_support = sparams->rec_support;
|
||||
itnim->task_retry_id = sparams->task_retry_id;
|
||||
itnim->conf_comp = sparams->confirm;
|
||||
|
||||
itnim->stats.prli_rsp_acc++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
|
||||
} else {
|
||||
ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
|
||||
|
||||
bfa_trc(itnim->fcs, ls_rjt->reason_code);
|
||||
bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
|
||||
|
||||
itnim->stats.prli_rsp_rjt++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_timeout(void *arg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
|
||||
|
||||
itnim->stats.timeout++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
bfa_itnim_delete(itnim->bfa_itnim);
|
||||
bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* itnim_public FCS ITNIM public interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called by rport when a new rport is created.
|
||||
*
|
||||
* @param[in] rport - remote port.
|
||||
*/
|
||||
struct bfa_fcs_itnim_s *
|
||||
bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
|
||||
{
|
||||
struct bfa_fcs_port_s *port = rport->port;
|
||||
struct bfa_fcs_itnim_s *itnim;
|
||||
struct bfad_itnim_s *itnim_drv;
|
||||
struct bfa_itnim_s *bfa_itnim;
|
||||
|
||||
/*
|
||||
* call bfad to allocate the itnim
|
||||
*/
|
||||
bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
|
||||
if (itnim == NULL) {
|
||||
bfa_trc(port->fcs, rport->pwwn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize itnim
|
||||
*/
|
||||
itnim->rport = rport;
|
||||
itnim->fcs = rport->fcs;
|
||||
itnim->itnim_drv = itnim_drv;
|
||||
|
||||
/*
|
||||
* call BFA to create the itnim
|
||||
*/
|
||||
bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
|
||||
|
||||
if (bfa_itnim == NULL) {
|
||||
bfa_trc(port->fcs, rport->pwwn);
|
||||
bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
|
||||
bfa_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
itnim->bfa_itnim = bfa_itnim;
|
||||
itnim->seq_rec = BFA_FALSE;
|
||||
itnim->rec_support = BFA_FALSE;
|
||||
itnim->conf_comp = BFA_FALSE;
|
||||
itnim->task_retry_id = BFA_FALSE;
|
||||
|
||||
/*
|
||||
* Set State machine
|
||||
*/
|
||||
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
|
||||
|
||||
return itnim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport to delete the instance of FCPIM.
|
||||
*
|
||||
* @param[in] rport - remote port.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pid);
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification from rport that PLOGI is complete to initiate FC-4 session.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
itnim->stats.onlines++;
|
||||
|
||||
if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
|
||||
} else {
|
||||
/*
|
||||
* For well known addresses, we set the itnim to initiator
|
||||
* state
|
||||
*/
|
||||
itnim->stats.initiator++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport to handle a remote device offline.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
itnim->stats.offlines++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport when remote port is known to be an initiator from
|
||||
* PRLI received.
|
||||
*/
|
||||
void
|
||||
bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pid);
|
||||
itnim->stats.initiator++;
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by rport to check if the itnim is online.
|
||||
*/
|
||||
bfa_status_t
|
||||
bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
bfa_trc(itnim->fcs, itnim->rport->pid);
|
||||
switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
|
||||
case BFA_ITNIM_ONLINE:
|
||||
case BFA_ITNIM_INITIATIOR:
|
||||
return BFA_STATUS_OK;
|
||||
|
||||
default:
|
||||
return BFA_STATUS_NO_FCPIM_NEXUS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA completion callback for bfa_itnim_online().
|
||||
*/
|
||||
void
|
||||
bfa_cb_itnim_online(void *cbarg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
|
||||
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA completion callback for bfa_itnim_offline().
|
||||
*/
|
||||
void
|
||||
bfa_cb_itnim_offline(void *cb_arg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
|
||||
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the beginning of PATH TOV handling. IO completion callbacks
|
||||
* are still pending.
|
||||
*/
|
||||
void
|
||||
bfa_cb_itnim_tov_begin(void *cb_arg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
|
||||
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_fcb_itnim_tov_begin(itnim->itnim_drv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
|
||||
*/
|
||||
void
|
||||
bfa_cb_itnim_tov(void *cb_arg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
|
||||
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_fcb_itnim_tov(itnim->itnim_drv);
|
||||
}
|
||||
|
||||
/**
|
||||
* BFA notification to FCS/driver for second level error recovery.
|
||||
*
|
||||
* Atleast one I/O request has timedout and target is unresponsive to
|
||||
* repeated abort requests. Second level error recovery should be initiated
|
||||
* by starting implicit logout and recovery procedures.
|
||||
*/
|
||||
void
|
||||
bfa_cb_itnim_sler(void *cb_arg)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
|
||||
|
||||
itnim->stats.sler++;
|
||||
bfa_trc(itnim->fcs, itnim->rport->pwwn);
|
||||
bfa_fcs_rport_logo_imp(itnim->rport);
|
||||
}
|
||||
|
||||
struct bfa_fcs_itnim_s *
|
||||
bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
|
||||
{
|
||||
struct bfa_fcs_rport_s *rport;
|
||||
rport = bfa_fcs_rport_lookup(port, rpwwn);
|
||||
|
||||
if (!rport)
|
||||
return NULL;
|
||||
|
||||
bfa_assert(rport->itnim != NULL);
|
||||
return (rport->itnim);
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
|
||||
struct bfa_itnim_attr_s *attr)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = NULL;
|
||||
|
||||
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
|
||||
|
||||
if (itnim == NULL)
|
||||
return BFA_STATUS_NO_FCPIM_NEXUS;
|
||||
|
||||
attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
|
||||
attr->retry = itnim->seq_rec;
|
||||
attr->rec_support = itnim->rec_support;
|
||||
attr->conf_comp = itnim->conf_comp;
|
||||
attr->task_retry_id = itnim->task_retry_id;
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
|
||||
struct bfa_itnim_stats_s *stats)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = NULL;
|
||||
|
||||
bfa_assert(port != NULL);
|
||||
|
||||
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
|
||||
|
||||
if (itnim == NULL)
|
||||
return BFA_STATUS_NO_FCPIM_NEXUS;
|
||||
|
||||
bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
|
||||
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
|
||||
{
|
||||
struct bfa_fcs_itnim_s *itnim = NULL;
|
||||
|
||||
bfa_assert(port != NULL);
|
||||
|
||||
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
|
||||
|
||||
if (itnim == NULL)
|
||||
return BFA_STATUS_NO_FCPIM_NEXUS;
|
||||
|
||||
bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
|
||||
return BFA_STATUS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
|
||||
u16 len)
|
||||
{
|
||||
struct fc_els_cmd_s *els_cmd;
|
||||
|
||||
bfa_trc(itnim->fcs, fchs->type);
|
||||
|
||||
if (fchs->type != FC_TYPE_ELS)
|
||||
return;
|
||||
|
||||
els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
|
||||
|
||||
bfa_trc(itnim->fcs, els_cmd->els_code);
|
||||
|
||||
switch (els_cmd->els_code) {
|
||||
case FC_ELS_PRLO:
|
||||
/* bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_PRLO); */
|
||||
break;
|
||||
|
||||
default:
|
||||
bfa_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Module initialization
|
||||
*/
|
||||
void
|
||||
bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Module cleanup
|
||||
*/
|
||||
void
|
||||
bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs)
|
||||
{
|
||||
bfa_fcs_modexit_comp(fcs);
|
||||
}
|
||||
|
||||
|
68
drivers/scsi/bfa/fcptm.c
Normal file
68
drivers/scsi/bfa/fcptm.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains dummy FCPTM routines to aid in Initiator Mode only
|
||||
* compilation of OS driver.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bfa_os_inc.h"
|
||||
#include "fcs_rport.h"
|
||||
#include "fcs_fcptm.h"
|
||||
#include "fcs/bfa_fcs_rport.h"
|
||||
|
||||
struct bfa_fcs_tin_s *
|
||||
bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin)
|
||||
{
|
||||
}
|
30
drivers/scsi/bfa/fcs.h
Normal file
30
drivers/scsi/bfa/fcs.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs.h FCS module functions
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FCS_H__
|
||||
#define __FCS_H__
|
||||
|
||||
#define __fcs_min_cfg(__fcs) (__fcs)->min_cfg
|
||||
|
||||
void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
|
||||
|
||||
#endif /* __FCS_H__ */
|
37
drivers/scsi/bfa/fcs_auth.h
Normal file
37
drivers/scsi/bfa/fcs_auth.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_uf.h FCS unsolicited frame receive
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FCS_AUTH_H__
|
||||
#define __FCS_AUTH_H__
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <fcs/bfa_fcs_vport.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
|
||||
/*
|
||||
* fcs friend functions: only between fcs modules
|
||||
*/
|
||||
void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len);
|
||||
void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric);
|
||||
void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric);
|
||||
|
||||
#endif /* __FCS_UF_H__ */
|
61
drivers/scsi/bfa/fcs_fabric.h
Normal file
61
drivers/scsi/bfa/fcs_fabric.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_lport.h FCS logical port interfaces
|
||||
*/
|
||||
|
||||
#ifndef __FCS_FABRIC_H__
|
||||
#define __FCS_FABRIC_H__
|
||||
|
||||
#include <fcs/bfa_fcs.h>
|
||||
#include <fcs/bfa_fcs_vport.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
|
||||
/*
|
||||
* fcs friend functions: only between fcs modules
|
||||
*/
|
||||
void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
|
||||
void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
|
||||
void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
|
||||
struct bfa_fcs_vport_s *vport);
|
||||
void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
|
||||
struct bfa_fcs_vport_s *vport);
|
||||
int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
|
||||
struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
|
||||
struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
|
||||
void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
|
||||
struct fchs_s *fchs, u16 len);
|
||||
u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
|
||||
bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
|
||||
enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
|
||||
void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
|
||||
void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
|
||||
|
||||
bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
|
||||
struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg,
|
||||
struct bfad_vf_s *vf_drv);
|
||||
void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric,
|
||||
enum auth_status status);
|
||||
|
||||
void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
|
||||
wwn_t fabric_name);
|
||||
#endif /* __FCS_FABRIC_H__ */
|
44
drivers/scsi/bfa/fcs_fcpim.h
Normal file
44
drivers/scsi/bfa/fcs_fcpim.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __FCS_FCPIM_H__
|
||||
#define __FCS_FCPIM_H__
|
||||
|
||||
#include <defs/bfa_defs_port.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
|
||||
/*
|
||||
* Following routines are from FCPIM and will be called by rport.
|
||||
*/
|
||||
struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
|
||||
void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
|
||||
void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
|
||||
bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
|
||||
|
||||
void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
|
||||
void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim);
|
||||
void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim);
|
||||
|
||||
/*
|
||||
* Modudle init/cleanup routines.
|
||||
*/
|
||||
void bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
|
||||
u16 len);
|
||||
#endif /* __FCS_FCPIM_H__ */
|
45
drivers/scsi/bfa/fcs_fcptm.h
Normal file
45
drivers/scsi/bfa/fcs_fcptm.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __FCS_FCPTM_H__
|
||||
#define __FCS_FCPTM_H__
|
||||
|
||||
#include <defs/bfa_defs_port.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
|
||||
/*
|
||||
* Following routines are from FCPTM and will be called by rport.
|
||||
*/
|
||||
struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin);
|
||||
void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin);
|
||||
void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin);
|
||||
void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
|
||||
u16 len);
|
||||
void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin);
|
||||
void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin);
|
||||
|
||||
/*
|
||||
* Modudle init/cleanup routines.
|
||||
*/
|
||||
void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
|
||||
u16 len);
|
||||
|
||||
#endif /* __FCS_FCPTM_H__ */
|
29
drivers/scsi/bfa/fcs_fcxp.h
Normal file
29
drivers/scsi/bfa/fcs_fcxp.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_fcxp.h FCXP helper macros for FCS
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FCS_FCXP_H__
|
||||
#define __FCS_FCXP_H__
|
||||
|
||||
#define bfa_fcs_fcxp_alloc(__fcs) \
|
||||
bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
|
||||
|
||||
#endif /* __FCS_FCXP_H__ */
|
117
drivers/scsi/bfa/fcs_lport.h
Normal file
117
drivers/scsi/bfa/fcs_lport.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_lport.h FCS logical port interfaces
|
||||
*/
|
||||
|
||||
#ifndef __FCS_LPORT_H__
|
||||
#define __FCS_LPORT_H__
|
||||
|
||||
#define __VPORT_H__
|
||||
#include <defs/bfa_defs_port.h>
|
||||
#include <bfa_svc.h>
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
#include <fcs/bfa_fcs_vport.h>
|
||||
#include <fcs_fabric.h>
|
||||
#include <fcs_ms.h>
|
||||
#include <cs/bfa_q.h>
|
||||
#include <fcbuild.h>
|
||||
|
||||
/*
|
||||
* PID used in P2P/N2N ( In Big Endian)
|
||||
*/
|
||||
#define N2N_LOCAL_PID 0x010000
|
||||
#define N2N_REMOTE_PID 0x020000
|
||||
|
||||
/*
|
||||
* Misc Timeouts
|
||||
*/
|
||||
/*
|
||||
* To be used when spawning a timer before retrying a failed command. Milli
|
||||
* Secs.
|
||||
*/
|
||||
#define BFA_FCS_RETRY_TIMEOUT 2000
|
||||
|
||||
/*
|
||||
* Check for Port/Vport Mode/Role
|
||||
*/
|
||||
#define BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
|
||||
(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
|
||||
|
||||
#define BFA_FCS_VPORT_IS_TARGET_MODE(port) \
|
||||
(port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
|
||||
|
||||
#define BFA_FCS_VPORT_IS_IPFC_MODE(port) \
|
||||
(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC)
|
||||
|
||||
/*
|
||||
* Is this a Well Known Address
|
||||
*/
|
||||
#define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
|
||||
|
||||
/*
|
||||
* Pointer to elements within Port
|
||||
*/
|
||||
#define BFA_FCS_GET_HAL_FROM_PORT(port) (port->fcs->bfa)
|
||||
#define BFA_FCS_GET_NS_FROM_PORT(port) (&port->port_topo.pfab.ns)
|
||||
#define BFA_FCS_GET_SCN_FROM_PORT(port) (&port->port_topo.pfab.scn)
|
||||
#define BFA_FCS_GET_MS_FROM_PORT(port) (&port->port_topo.pfab.ms)
|
||||
#define BFA_FCS_GET_FDMI_FROM_PORT(port) (&port->port_topo.pfab.ms.fdmi)
|
||||
|
||||
/*
|
||||
* handler for unsolicied frames
|
||||
*/
|
||||
void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
|
||||
u16 len);
|
||||
|
||||
/*
|
||||
* Following routines will be called by Fabric to indicate port
|
||||
* online/offline to vport.
|
||||
*/
|
||||
void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
|
||||
u16 vf_id, struct bfa_port_cfg_s *port_cfg,
|
||||
struct bfa_fcs_vport_s *vport);
|
||||
void bfa_fcs_port_online(struct bfa_fcs_port_s *port);
|
||||
void bfa_fcs_port_offline(struct bfa_fcs_port_s *port);
|
||||
void bfa_fcs_port_delete(struct bfa_fcs_port_s *port);
|
||||
bfa_boolean_t bfa_fcs_port_is_online(struct bfa_fcs_port_s *port);
|
||||
|
||||
/*
|
||||
* Lookup rport based on PID
|
||||
*/
|
||||
struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid(
|
||||
struct bfa_fcs_port_s *port, u32 pid);
|
||||
|
||||
/*
|
||||
* Lookup rport based on PWWN
|
||||
*/
|
||||
struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn(
|
||||
struct bfa_fcs_port_s *port, wwn_t pwwn);
|
||||
struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn(
|
||||
struct bfa_fcs_port_s *port, wwn_t nwwn);
|
||||
void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
|
||||
struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
|
||||
struct bfa_fcs_rport_s *rport);
|
||||
|
||||
void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_port_lip(struct bfa_fcs_port_s *port);
|
||||
|
||||
#endif /* __FCS_LPORT_H__ */
|
35
drivers/scsi/bfa/fcs_ms.h
Normal file
35
drivers/scsi/bfa/fcs_ms.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_ms.h FCS ms interfaces
|
||||
*/
|
||||
#ifndef __FCS_MS_H__
|
||||
#define __FCS_MS_H__
|
||||
|
||||
/* MS FCS routines */
|
||||
void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port);
|
||||
void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port);
|
||||
void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port);
|
||||
void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port);
|
||||
|
||||
/* FDMI FCS routines */
|
||||
void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms);
|
||||
void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms);
|
||||
void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms);
|
||||
|
||||
#endif
|
32
drivers/scsi/bfa/fcs_port.h
Normal file
32
drivers/scsi/bfa/fcs_port.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_pport.h FCS physical port interfaces
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FCS_PPORT_H__
|
||||
#define __FCS_PPORT_H__
|
||||
|
||||
/*
|
||||
* fcs friend functions: only between fcs modules
|
||||
*/
|
||||
void bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs);
|
||||
|
||||
#endif /* __FCS_PPORT_H__ */
|
61
drivers/scsi/bfa/fcs_rport.h
Normal file
61
drivers/scsi/bfa/fcs_rport.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_rport.h FCS rport interfaces and defines
|
||||
*/
|
||||
|
||||
#ifndef __FCS_RPORT_H__
|
||||
#define __FCS_RPORT_H__
|
||||
|
||||
#include <fcs/bfa_fcs_rport.h>
|
||||
|
||||
void bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs);
|
||||
|
||||
void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
|
||||
u16 len);
|
||||
void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
|
||||
|
||||
struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port,
|
||||
u32 pid);
|
||||
void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
|
||||
struct fc_logi_s *plogi_rsp);
|
||||
void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port,
|
||||
struct fchs_s *rx_fchs,
|
||||
struct fc_logi_s *plogi);
|
||||
void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
|
||||
struct fc_logi_s *plogi);
|
||||
void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
|
||||
int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
|
||||
struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port,
|
||||
wwn_t wwn);
|
||||
|
||||
|
||||
/* Rport Features */
|
||||
void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
|
||||
void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
|
||||
|
||||
#endif /* __FCS_RPORT_H__ */
|
56
drivers/scsi/bfa/fcs_trcmod.h
Normal file
56
drivers/scsi/bfa/fcs_trcmod.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_trcmod.h BFA FCS trace modules
|
||||
*/
|
||||
|
||||
#ifndef __FCS_TRCMOD_H__
|
||||
#define __FCS_TRCMOD_H__
|
||||
|
||||
#include <cs/bfa_trc.h>
|
||||
|
||||
/*
|
||||
* !!! Only append to the enums defined here to avoid any versioning
|
||||
* !!! needed between trace utility and driver version
|
||||
*/
|
||||
enum {
|
||||
BFA_TRC_FCS_FABRIC = 1,
|
||||
BFA_TRC_FCS_VFAPI = 2,
|
||||
BFA_TRC_FCS_PORT = 3,
|
||||
BFA_TRC_FCS_VPORT = 4,
|
||||
BFA_TRC_FCS_VP_API = 5,
|
||||
BFA_TRC_FCS_VPS = 6,
|
||||
BFA_TRC_FCS_RPORT = 7,
|
||||
BFA_TRC_FCS_FCPIM = 8,
|
||||
BFA_TRC_FCS_FCPTM = 9,
|
||||
BFA_TRC_FCS_NS = 10,
|
||||
BFA_TRC_FCS_SCN = 11,
|
||||
BFA_TRC_FCS_LOOP = 12,
|
||||
BFA_TRC_FCS_UF = 13,
|
||||
BFA_TRC_FCS_PPORT = 14,
|
||||
BFA_TRC_FCS_FCPIP = 15,
|
||||
BFA_TRC_FCS_PORT_API = 16,
|
||||
BFA_TRC_FCS_RPORT_API = 17,
|
||||
BFA_TRC_FCS_AUTH = 18,
|
||||
BFA_TRC_FCS_N2N = 19,
|
||||
BFA_TRC_FCS_MS = 20,
|
||||
BFA_TRC_FCS_FDMI = 21,
|
||||
BFA_TRC_FCS_RPORT_FTRS = 22,
|
||||
};
|
||||
|
||||
#endif /* __FCS_TRCMOD_H__ */
|
32
drivers/scsi/bfa/fcs_uf.h
Normal file
32
drivers/scsi/bfa/fcs_uf.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fcs_uf.h FCS unsolicited frame receive
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FCS_UF_H__
|
||||
#define __FCS_UF_H__
|
||||
|
||||
/*
|
||||
* fcs friend functions: only between fcs modules
|
||||
*/
|
||||
void bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs);
|
||||
|
||||
#endif /* __FCS_UF_H__ */
|
39
drivers/scsi/bfa/fcs_vport.h
Normal file
39
drivers/scsi/bfa/fcs_vport.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2009 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 __FCS_VPORT_H__
|
||||
#define __FCS_VPORT_H__
|
||||
|
||||
#include <fcs/bfa_fcs_lport.h>
|
||||
#include <fcs/bfa_fcs_vport.h>
|
||||
#include <defs/bfa_defs_pci.h>
|
||||
|
||||
/*
|
||||
* Modudle init/cleanup routines.
|
||||
*/
|
||||
|
||||
void bfa_fcs_vport_modinit(struct bfa_fcs_s *fcs);
|
||||
void bfa_fcs_vport_modexit(struct bfa_fcs_s *fcs);
|
||||
|
||||
void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
|
||||
void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
|
||||
void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
|
||||
void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
|
||||
u32 bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs);
|
||||
|
||||
#endif /* __FCS_VPORT_H__ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user