Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
config QEDF
tristate "QLogic QEDF 25/40/100Gb FCoE Initiator Driver Support"
depends on PCI && SCSI
depends on QED
depends on LIBFC
depends on LIBFCOE
select QED_LL2
select QED_FCOE
help
This driver supports FCoE offload for the QLogic FastLinQ
41000 Series Converged Network Adapters.
+6
View File
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_QEDF) := qedf.o
qedf-y = qedf_dbg.o qedf_main.o qedf_io.o qedf_fip.o \
qedf_attr.o qedf_els.o drv_scsi_fw_funcs.o drv_fcoe_fw_funcs.o
qedf-$(CONFIG_DEBUG_FS) += qedf_debugfs.o
@@ -0,0 +1,196 @@
// SPDX-License-Identifier: GPL-2.0-only
/* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#include "drv_fcoe_fw_funcs.h"
#include "drv_scsi_fw_funcs.h"
#define FCOE_RX_ID (0xFFFFu)
static inline void init_common_sqe(struct fcoe_task_params *task_params,
enum fcoe_sqe_request_type request_type)
{
memset(task_params->sqe, 0, sizeof(*(task_params->sqe)));
SET_FIELD(task_params->sqe->flags, FCOE_WQE_REQ_TYPE,
request_type);
task_params->sqe->task_id = task_params->itid;
}
int init_initiator_rw_fcoe_task(struct fcoe_task_params *task_params,
struct scsi_sgl_task_params *sgl_task_params,
struct regpair sense_data_buffer_phys_addr,
u32 task_retry_id,
u8 fcp_cmd_payload[32])
{
struct fcoe_task_context *ctx = task_params->context;
const u8 val_byte = ctx->ystorm_ag_context.byte0;
struct ustorm_fcoe_task_ag_ctx *u_ag_ctx;
struct ystorm_fcoe_task_st_ctx *y_st_ctx;
struct tstorm_fcoe_task_st_ctx *t_st_ctx;
struct mstorm_fcoe_task_st_ctx *m_st_ctx;
u32 io_size, val;
bool slow_sgl;
memset(ctx, 0, sizeof(*(ctx)));
ctx->ystorm_ag_context.byte0 = val_byte;
slow_sgl = scsi_is_slow_sgl(sgl_task_params->num_sges,
sgl_task_params->small_mid_sge);
io_size = (task_params->task_type == FCOE_TASK_TYPE_WRITE_INITIATOR ?
task_params->tx_io_size : task_params->rx_io_size);
/* Ystorm ctx */
y_st_ctx = &ctx->ystorm_st_context;
y_st_ctx->data_2_trns_rem = cpu_to_le32(io_size);
y_st_ctx->task_rety_identifier = cpu_to_le32(task_retry_id);
y_st_ctx->task_type = (u8)task_params->task_type;
memcpy(&y_st_ctx->tx_info_union.fcp_cmd_payload,
fcp_cmd_payload, sizeof(struct fcoe_fcp_cmd_payload));
/* Tstorm ctx */
t_st_ctx = &ctx->tstorm_st_context;
t_st_ctx->read_only.dev_type = (u8)(task_params->is_tape_device == 1 ?
FCOE_TASK_DEV_TYPE_TAPE :
FCOE_TASK_DEV_TYPE_DISK);
t_st_ctx->read_only.cid = cpu_to_le32(task_params->conn_cid);
val = cpu_to_le32(task_params->cq_rss_number);
t_st_ctx->read_only.glbl_q_num = val;
t_st_ctx->read_only.fcp_cmd_trns_size = cpu_to_le32(io_size);
t_st_ctx->read_only.task_type = (u8)task_params->task_type;
SET_FIELD(t_st_ctx->read_write.flags,
FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_EXP_FIRST_FRAME, 1);
t_st_ctx->read_write.rx_id = cpu_to_le16(FCOE_RX_ID);
/* Ustorm ctx */
u_ag_ctx = &ctx->ustorm_ag_context;
u_ag_ctx->global_cq_num = cpu_to_le32(task_params->cq_rss_number);
/* Mstorm buffer for sense/rsp data placement */
m_st_ctx = &ctx->mstorm_st_context;
val = cpu_to_le32(sense_data_buffer_phys_addr.hi);
m_st_ctx->rsp_buf_addr.hi = val;
val = cpu_to_le32(sense_data_buffer_phys_addr.lo);
m_st_ctx->rsp_buf_addr.lo = val;
if (task_params->task_type == FCOE_TASK_TYPE_WRITE_INITIATOR) {
/* Ystorm ctx */
y_st_ctx->expect_first_xfer = 1;
/* Set the amount of super SGEs. Can be up to 4. */
SET_FIELD(y_st_ctx->sgl_mode,
YSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE,
(slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL));
init_scsi_sgl_context(&y_st_ctx->sgl_params,
&y_st_ctx->data_desc,
sgl_task_params);
/* Mstorm ctx */
SET_FIELD(m_st_ctx->flags,
MSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE,
(slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL));
m_st_ctx->sgl_params.sgl_num_sges =
cpu_to_le16(sgl_task_params->num_sges);
} else {
/* Tstorm ctx */
SET_FIELD(t_st_ctx->read_write.flags,
FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_RX_SGL_MODE,
(slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL));
/* Mstorm ctx */
m_st_ctx->data_2_trns_rem = cpu_to_le32(io_size);
init_scsi_sgl_context(&m_st_ctx->sgl_params,
&m_st_ctx->data_desc,
sgl_task_params);
}
/* Init Sqe */
init_common_sqe(task_params, SEND_FCOE_CMD);
return 0;
}
int init_initiator_midpath_unsolicited_fcoe_task(
struct fcoe_task_params *task_params,
struct fcoe_tx_mid_path_params *mid_path_fc_header,
struct scsi_sgl_task_params *tx_sgl_task_params,
struct scsi_sgl_task_params *rx_sgl_task_params,
u8 fw_to_place_fc_header)
{
struct fcoe_task_context *ctx = task_params->context;
const u8 val_byte = ctx->ystorm_ag_context.byte0;
struct ustorm_fcoe_task_ag_ctx *u_ag_ctx;
struct ystorm_fcoe_task_st_ctx *y_st_ctx;
struct tstorm_fcoe_task_st_ctx *t_st_ctx;
struct mstorm_fcoe_task_st_ctx *m_st_ctx;
u32 val;
memset(ctx, 0, sizeof(*(ctx)));
ctx->ystorm_ag_context.byte0 = val_byte;
/* Init Ystorm */
y_st_ctx = &ctx->ystorm_st_context;
init_scsi_sgl_context(&y_st_ctx->sgl_params,
&y_st_ctx->data_desc,
tx_sgl_task_params);
SET_FIELD(y_st_ctx->sgl_mode,
YSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE, SCSI_FAST_SGL);
y_st_ctx->data_2_trns_rem = cpu_to_le32(task_params->tx_io_size);
y_st_ctx->task_type = (u8)task_params->task_type;
memcpy(&y_st_ctx->tx_info_union.tx_params.mid_path,
mid_path_fc_header, sizeof(struct fcoe_tx_mid_path_params));
/* Init Mstorm */
m_st_ctx = &ctx->mstorm_st_context;
init_scsi_sgl_context(&m_st_ctx->sgl_params,
&m_st_ctx->data_desc,
rx_sgl_task_params);
SET_FIELD(m_st_ctx->flags,
MSTORM_FCOE_TASK_ST_CTX_MP_INCLUDE_FC_HEADER,
fw_to_place_fc_header);
m_st_ctx->data_2_trns_rem = cpu_to_le32(task_params->rx_io_size);
/* Init Tstorm */
t_st_ctx = &ctx->tstorm_st_context;
t_st_ctx->read_only.cid = cpu_to_le32(task_params->conn_cid);
val = cpu_to_le32(task_params->cq_rss_number);
t_st_ctx->read_only.glbl_q_num = val;
t_st_ctx->read_only.task_type = (u8)task_params->task_type;
SET_FIELD(t_st_ctx->read_write.flags,
FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_EXP_FIRST_FRAME, 1);
t_st_ctx->read_write.rx_id = cpu_to_le16(FCOE_RX_ID);
/* Init Ustorm */
u_ag_ctx = &ctx->ustorm_ag_context;
u_ag_ctx->global_cq_num = cpu_to_le32(task_params->cq_rss_number);
/* Init SQE */
init_common_sqe(task_params, SEND_FCOE_MIDPATH);
task_params->sqe->additional_info_union.burst_length =
tx_sgl_task_params->total_buffer_size;
SET_FIELD(task_params->sqe->flags,
FCOE_WQE_NUM_SGES, tx_sgl_task_params->num_sges);
SET_FIELD(task_params->sqe->flags, FCOE_WQE_SGL_MODE,
SCSI_FAST_SGL);
return 0;
}
int init_initiator_abort_fcoe_task(struct fcoe_task_params *task_params)
{
init_common_sqe(task_params, SEND_FCOE_ABTS_REQUEST);
return 0;
}
int init_initiator_cleanup_fcoe_task(struct fcoe_task_params *task_params)
{
init_common_sqe(task_params, FCOE_EXCHANGE_CLEANUP);
return 0;
}
int init_initiator_sequence_recovery_fcoe_task(
struct fcoe_task_params *task_params, u32 desired_offset)
{
init_common_sqe(task_params, FCOE_SEQUENCE_RECOVERY);
task_params->sqe->additional_info_union.seq_rec_updated_offset =
desired_offset;
return 0;
}
@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#ifndef _FCOE_FW_FUNCS_H
#define _FCOE_FW_FUNCS_H
#include "drv_scsi_fw_funcs.h"
#include "qedf_hsi.h"
#include <linux/qed/qed_if.h>
struct fcoe_task_params {
/* Output parameter [set/filled by the HSI function] */
struct fcoe_task_context *context;
/* Output parameter [set/filled by the HSI function] */
struct fcoe_wqe *sqe;
enum fcoe_task_type task_type;
u32 tx_io_size; /* in bytes */
u32 rx_io_size; /* in bytes */
u32 conn_cid;
u16 itid;
u8 cq_rss_number;
/* Whether it's Tape device or not (0=Disk, 1=Tape) */
u8 is_tape_device;
};
/**
* @brief init_initiator_rw_fcoe_task - Initializes FCoE task context for
* read/write task types and init fcoe_sqe
*
* @param task_params - Pointer to task parameters struct
* @param sgl_task_params - Pointer to SGL task params
* @param sense_data_buffer_phys_addr - Pointer to sense data buffer
* @param task_retry_id - retry identification - Used only for Tape device
* @param fcp_cmnd_payload - FCP CMD Payload
*/
int init_initiator_rw_fcoe_task(struct fcoe_task_params *task_params,
struct scsi_sgl_task_params *sgl_task_params,
struct regpair sense_data_buffer_phys_addr,
u32 task_retry_id,
u8 fcp_cmd_payload[32]);
/**
* @brief init_initiator_midpath_fcoe_task - Initializes FCoE task context for
* midpath/unsolicited task types and init fcoe_sqe
*
* @param task_params - Pointer to task parameters struct
* @param mid_path_fc_header - FC header
* @param tx_sgl_task_params - Pointer to Tx SGL task params
* @param rx_sgl_task_params - Pointer to Rx SGL task params
* @param fw_to_place_fc_header - Indication if the FW will place the FC header
* in addition to the data arrives.
*/
int init_initiator_midpath_unsolicited_fcoe_task(
struct fcoe_task_params *task_params,
struct fcoe_tx_mid_path_params *mid_path_fc_header,
struct scsi_sgl_task_params *tx_sgl_task_params,
struct scsi_sgl_task_params *rx_sgl_task_params,
u8 fw_to_place_fc_header);
/**
* @brief init_initiator_abort_fcoe_task - Initializes FCoE task context for
* abort task types and init fcoe_sqe
*
* @param task_params - Pointer to task parameters struct
*/
int init_initiator_abort_fcoe_task(struct fcoe_task_params *task_params);
/**
* @brief init_initiator_cleanup_fcoe_task - Initializes FCoE task context for
* cleanup task types and init fcoe_sqe
*
*
* @param task_params - Pointer to task parameters struct
*/
int init_initiator_cleanup_fcoe_task(struct fcoe_task_params *task_params);
/**
* @brief init_initiator_cleanup_fcoe_task - Initializes FCoE task context for
* sequence recovery task types and init fcoe_sqe
*
*
* @param task_params - Pointer to task parameters struct
* @param desired_offset - The desired offest the task will be re-sent from
*/
int init_initiator_sequence_recovery_fcoe_task(
struct fcoe_task_params *task_params,
u32 desired_offset);
#endif
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0-only
/* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#include "drv_scsi_fw_funcs.h"
#define SCSI_NUM_SGES_IN_CACHE 0x4
bool scsi_is_slow_sgl(u16 num_sges, bool small_mid_sge)
{
return (num_sges > SCSI_NUM_SGES_SLOW_SGL_THR && small_mid_sge);
}
void init_scsi_sgl_context(struct scsi_sgl_params *ctx_sgl_params,
struct scsi_cached_sges *ctx_data_desc,
struct scsi_sgl_task_params *sgl_task_params)
{
/* no need to check for sgl_task_params->sgl validity */
u8 num_sges_to_init = sgl_task_params->num_sges >
SCSI_NUM_SGES_IN_CACHE ? SCSI_NUM_SGES_IN_CACHE :
sgl_task_params->num_sges;
u8 sge_index;
u32 val;
val = cpu_to_le32(sgl_task_params->sgl_phys_addr.lo);
ctx_sgl_params->sgl_addr.lo = val;
val = cpu_to_le32(sgl_task_params->sgl_phys_addr.hi);
ctx_sgl_params->sgl_addr.hi = val;
val = cpu_to_le32(sgl_task_params->total_buffer_size);
ctx_sgl_params->sgl_total_length = val;
ctx_sgl_params->sgl_num_sges = cpu_to_le16(sgl_task_params->num_sges);
for (sge_index = 0; sge_index < num_sges_to_init; sge_index++) {
val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_addr.lo);
ctx_data_desc->sge[sge_index].sge_addr.lo = val;
val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_addr.hi);
ctx_data_desc->sge[sge_index].sge_addr.hi = val;
val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_len);
ctx_data_desc->sge[sge_index].sge_len = val;
}
}
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#ifndef _SCSI_FW_FUNCS_H
#define _SCSI_FW_FUNCS_H
#include <linux/qed/common_hsi.h>
#include <linux/qed/storage_common.h>
#include <linux/qed/fcoe_common.h>
struct scsi_sgl_task_params {
struct scsi_sge *sgl;
struct regpair sgl_phys_addr;
u32 total_buffer_size;
u16 num_sges;
/* true if SGL contains a small (< 4KB) SGE in middle(not 1st or last)
* -> relevant for tx only
*/
bool small_mid_sge;
};
struct scsi_dif_task_params {
u32 initial_ref_tag;
bool initial_ref_tag_is_valid;
u16 application_tag;
u16 application_tag_mask;
u16 dif_block_size_log;
bool dif_on_network;
bool dif_on_host;
u8 host_guard_type;
u8 protection_type;
u8 ref_tag_mask;
bool crc_seed;
/* Enable Connection error upon DIF error (segments with DIF errors are
* dropped)
*/
bool tx_dif_conn_err_en;
bool ignore_app_tag;
bool keep_ref_tag_const;
bool validate_guard;
bool validate_app_tag;
bool validate_ref_tag;
bool forward_guard;
bool forward_app_tag;
bool forward_ref_tag;
bool forward_app_tag_with_mask;
bool forward_ref_tag_with_mask;
};
struct scsi_initiator_cmd_params {
/* for cdb_size > default CDB size (extended CDB > 16 bytes) ->
* pointer to the CDB buffer SGE
*/
struct scsi_sge extended_cdb_sge;
/* Physical address of sense data buffer for sense data - 256B buffer */
struct regpair sense_data_buffer_phys_addr;
};
/**
* @brief scsi_is_slow_sgl - checks for slow SGL
*
* @param num_sges - number of sges in SGL
* @param small_mid_sge - True is the SGL contains an SGE which is smaller than
* 4KB and its not the 1st or last SGE in the SGL
*/
bool scsi_is_slow_sgl(u16 num_sges, bool small_mid_sge);
/**
* @brief init_scsi_sgl_context - initializes SGL task context
*
* @param sgl_params - SGL context parameters to initialize (output parameter)
* @param data_desc - context struct containing SGEs array to set (output
* parameter)
* @param sgl_task_params - SGL parameters (input)
*/
void init_scsi_sgl_context(struct scsi_sgl_params *sgl_params,
struct scsi_cached_sges *ctx_data_desc,
struct scsi_sgl_task_params *sgl_task_params);
#endif
+605
View File
@@ -0,0 +1,605 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#ifndef _QEDFC_H_
#define _QEDFC_H_
#include <scsi/libfcoe.h>
#include <scsi/libfc.h>
#include <scsi/fc/fc_fip.h>
#include <scsi/fc/fc_fc2.h>
#include <scsi/scsi_tcq.h>
/* qedf_hsi.h needs to before included any qed includes */
#include "qedf_hsi.h"
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_fcoe_if.h>
#include <linux/qed/qed_ll2_if.h>
#include "qedf_version.h"
#include "qedf_dbg.h"
#include "drv_fcoe_fw_funcs.h"
/* Helpers to extract upper and lower 32-bits of pointer */
#define U64_HI(val) ((u32)(((u64)(val)) >> 32))
#define U64_LO(val) ((u32)(((u64)(val)) & 0xffffffff))
#define QEDF_DESCR "QLogic FCoE Offload Driver"
#define QEDF_MODULE_NAME "qedf"
#define QEDF_FLOGI_RETRY_CNT 3
#define QEDF_RPORT_RETRY_CNT 255
#define QEDF_MAX_SESSIONS 1024
#define QEDF_MAX_PAYLOAD 2048
#define QEDF_MAX_BDS_PER_CMD 256
#define QEDF_MAX_BD_LEN 0xffff
#define QEDF_BD_SPLIT_SZ 0x1000
#define QEDF_PAGE_SIZE 4096
#define QED_HW_DMA_BOUNDARY 0xfff
#define QEDF_MAX_SGLEN_FOR_CACHESGL ((1U << 16) - 1)
#define QEDF_MFS (QEDF_MAX_PAYLOAD + \
sizeof(struct fc_frame_header))
#define QEDF_MAX_NPIV 64
#define QEDF_TM_TIMEOUT 10
#define QEDF_ABORT_TIMEOUT (10 * 1000)
#define QEDF_CLEANUP_TIMEOUT 1
#define QEDF_MAX_CDB_LEN 16
#define QEDF_LL2_BUF_SIZE 2500 /* Buffer size required for LL2 Rx */
#define UPSTREAM_REMOVE 1
#define UPSTREAM_KEEP 1
struct qedf_mp_req {
uint32_t req_len;
void *req_buf;
dma_addr_t req_buf_dma;
struct scsi_sge *mp_req_bd;
dma_addr_t mp_req_bd_dma;
struct fc_frame_header req_fc_hdr;
uint32_t resp_len;
void *resp_buf;
dma_addr_t resp_buf_dma;
struct scsi_sge *mp_resp_bd;
dma_addr_t mp_resp_bd_dma;
struct fc_frame_header resp_fc_hdr;
};
struct qedf_els_cb_arg {
struct qedf_ioreq *aborted_io_req;
struct qedf_ioreq *io_req;
u8 op; /* Used to keep track of ELS op */
uint16_t l2_oxid;
u32 offset; /* Used for sequence cleanup */
u8 r_ctl; /* Used for sequence cleanup */
};
enum qedf_ioreq_event {
QEDF_IOREQ_EV_NONE,
QEDF_IOREQ_EV_ABORT_SUCCESS,
QEDF_IOREQ_EV_ABORT_FAILED,
QEDF_IOREQ_EV_SEND_RRQ,
QEDF_IOREQ_EV_ELS_TMO,
QEDF_IOREQ_EV_ELS_ERR_DETECT,
QEDF_IOREQ_EV_ELS_FLUSH,
QEDF_IOREQ_EV_CLEANUP_SUCCESS,
QEDF_IOREQ_EV_CLEANUP_FAILED,
};
#define FC_GOOD 0
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
struct qedf_ioreq {
struct list_head link;
uint16_t xid;
struct scsi_cmnd *sc_cmd;
#define QEDF_SCSI_CMD 1
#define QEDF_TASK_MGMT_CMD 2
#define QEDF_ABTS 3
#define QEDF_ELS 4
#define QEDF_CLEANUP 5
#define QEDF_SEQ_CLEANUP 6
u8 cmd_type;
#define QEDF_CMD_OUTSTANDING 0x0
#define QEDF_CMD_IN_ABORT 0x1
#define QEDF_CMD_IN_CLEANUP 0x2
#define QEDF_CMD_SRR_SENT 0x3
#define QEDF_CMD_DIRTY 0x4
#define QEDF_CMD_ERR_SCSI_DONE 0x5
u8 io_req_flags;
uint8_t tm_flags;
u64 tm_lun;
struct qedf_rport *fcport;
#define QEDF_CMD_ST_INACTIVE 0
#define QEDFC_CMD_ST_IO_ACTIVE 1
#define QEDFC_CMD_ST_ABORT_ACTIVE 2
#define QEDFC_CMD_ST_ABORT_ACTIVE_EH 3
#define QEDFC_CMD_ST_CLEANUP_ACTIVE 4
#define QEDFC_CMD_ST_CLEANUP_ACTIVE_EH 5
#define QEDFC_CMD_ST_RRQ_ACTIVE 6
#define QEDFC_CMD_ST_RRQ_WAIT 7
#define QEDFC_CMD_ST_OXID_RETIRE_WAIT 8
#define QEDFC_CMD_ST_TMF_ACTIVE 9
#define QEDFC_CMD_ST_DRAIN_ACTIVE 10
#define QEDFC_CMD_ST_CLEANED 11
#define QEDFC_CMD_ST_ELS_ACTIVE 12
atomic_t state;
unsigned long flags;
enum qedf_ioreq_event event;
size_t data_xfer_len;
/* ID: 001: Alloc cmd (qedf_alloc_cmd) */
/* ID: 002: Initiate ABTS (qedf_initiate_abts) */
/* ID: 003: For RRQ (qedf_process_abts_compl) */
struct kref refcount;
struct qedf_cmd_mgr *cmd_mgr;
struct io_bdt *bd_tbl;
struct delayed_work timeout_work;
struct completion tm_done;
struct completion abts_done;
struct completion cleanup_done;
struct fcoe_task_context *task;
struct fcoe_task_params *task_params;
struct scsi_sgl_task_params *sgl_task_params;
int idx;
int lun;
/*
* Need to allocate enough room for both sense data and FCP response data
* which has a max length of 8 bytes according to spec.
*/
#define QEDF_SCSI_SENSE_BUFFERSIZE (SCSI_SENSE_BUFFERSIZE + 8)
uint8_t *sense_buffer;
dma_addr_t sense_buffer_dma;
u32 fcp_resid;
u32 fcp_rsp_len;
u32 fcp_sns_len;
u8 cdb_status;
u8 fcp_status;
u8 fcp_rsp_code;
u8 scsi_comp_flags;
#define QEDF_MAX_REUSE 0xfff
u16 reuse_count;
struct qedf_mp_req mp_req;
void (*cb_func)(struct qedf_els_cb_arg *cb_arg);
struct qedf_els_cb_arg *cb_arg;
int fp_idx;
unsigned int cpu;
unsigned int int_cpu;
#define QEDF_IOREQ_UNKNOWN_SGE 1
#define QEDF_IOREQ_SLOW_SGE 2
#define QEDF_IOREQ_FAST_SGE 3
u8 sge_type;
struct delayed_work rrq_work;
/* Used for sequence level recovery; i.e. REC/SRR */
uint32_t rx_buf_off;
uint32_t tx_buf_off;
uint32_t rx_id;
uint32_t task_retry_identifier;
/*
* Used to tell if we need to return a SCSI command
* during some form of error processing.
*/
bool return_scsi_cmd_on_abts;
unsigned int alloc;
};
struct qedf_cmd_priv {
struct qedf_ioreq *io_req;
};
static inline struct qedf_cmd_priv *qedf_priv(struct scsi_cmnd *cmd)
{
return scsi_cmd_priv(cmd);
}
extern struct workqueue_struct *qedf_io_wq;
struct qedf_rport {
spinlock_t rport_lock;
#define QEDF_RPORT_SESSION_READY 1
#define QEDF_RPORT_UPLOADING_CONNECTION 2
#define QEDF_RPORT_IN_RESET 3
#define QEDF_RPORT_IN_LUN_RESET 4
#define QEDF_RPORT_IN_TARGET_RESET 5
unsigned long flags;
int lun_reset_lun;
unsigned long retry_delay_timestamp;
struct fc_rport *rport;
struct fc_rport_priv *rdata;
struct qedf_ctx *qedf;
u32 handle; /* Handle from qed */
u32 fw_cid; /* fw_cid from qed */
void __iomem *p_doorbell;
/* Send queue management */
atomic_t free_sqes;
atomic_t ios_to_queue;
atomic_t num_active_ios;
struct fcoe_wqe *sq;
dma_addr_t sq_dma;
u16 sq_prod_idx;
u16 fw_sq_prod_idx;
u16 sq_con_idx;
u32 sq_mem_size;
void *sq_pbl;
dma_addr_t sq_pbl_dma;
u32 sq_pbl_size;
u32 sid;
#define QEDF_RPORT_TYPE_DISK 0
#define QEDF_RPORT_TYPE_TAPE 1
uint dev_type; /* Disk or tape */
struct list_head peers;
};
/* Used to contain LL2 skb's in ll2_skb_list */
struct qedf_skb_work {
struct work_struct work;
struct sk_buff *skb;
struct qedf_ctx *qedf;
};
struct qedf_fastpath {
#define QEDF_SB_ID_NULL 0xffff
u16 sb_id;
struct qed_sb_info *sb_info;
struct qedf_ctx *qedf;
/* Keep track of number of completions on this fastpath */
unsigned long completions;
uint32_t cq_num_entries;
};
/* Used to pass fastpath information needed to process CQEs */
struct qedf_io_work {
struct work_struct work;
struct fcoe_cqe cqe;
struct qedf_ctx *qedf;
struct fc_frame *fp;
};
struct qedf_glbl_q_params {
u64 hw_p_cq; /* Completion queue PBL */
u64 hw_p_rq; /* Request queue PBL */
u64 hw_p_cmdq; /* Command queue PBL */
};
struct global_queue {
struct fcoe_cqe *cq;
dma_addr_t cq_dma;
u32 cq_mem_size;
u32 cq_cons_idx; /* Completion queue consumer index */
u32 cq_prod_idx;
void *cq_pbl;
dma_addr_t cq_pbl_dma;
u32 cq_pbl_size;
};
/* I/O tracing entry */
#define QEDF_IO_TRACE_SIZE 2048
struct qedf_io_log {
#define QEDF_IO_TRACE_REQ 0
#define QEDF_IO_TRACE_RSP 1
uint8_t direction;
uint16_t task_id;
uint32_t port_id; /* Remote port fabric ID */
int lun;
unsigned char op; /* SCSI CDB */
uint8_t lba[4];
unsigned int bufflen; /* SCSI buffer length */
unsigned int sg_count; /* Number of SG elements */
int result; /* Result passed back to mid-layer */
unsigned long jiffies; /* Time stamp when I/O logged */
int refcount; /* Reference count for task id */
unsigned int req_cpu; /* CPU that the task is queued on */
unsigned int int_cpu; /* Interrupt CPU that the task is received on */
unsigned int rsp_cpu; /* CPU that task is returned on */
u8 sge_type; /* Did we take the slow, single or fast SGE path */
};
/* Number of entries in BDQ */
#define QEDF_BDQ_SIZE 256
#define QEDF_BDQ_BUF_SIZE 2072
/* DMA coherent buffers for BDQ */
struct qedf_bdq_buf {
void *buf_addr;
dma_addr_t buf_dma;
};
/* Main adapter struct */
struct qedf_ctx {
struct qedf_dbg_ctx dbg_ctx;
struct fcoe_ctlr ctlr;
struct fc_lport *lport;
u8 data_src_addr[ETH_ALEN];
#define QEDF_LINK_DOWN 0
#define QEDF_LINK_UP 1
atomic_t link_state;
#define QEDF_DCBX_PENDING 0
#define QEDF_DCBX_DONE 1
atomic_t dcbx;
#define QEDF_NULL_VLAN_ID -1
#define QEDF_FALLBACK_VLAN 1002
#define QEDF_DEFAULT_PRIO 3
int vlan_id;
u8 prio;
struct qed_dev *cdev;
struct qed_dev_fcoe_info dev_info;
struct qed_int_info int_info;
uint16_t last_command;
spinlock_t hba_lock;
struct pci_dev *pdev;
u64 wwnn;
u64 wwpn;
u8 __aligned(16) mac[ETH_ALEN];
struct list_head fcports;
atomic_t num_offloads;
unsigned int curr_conn_id;
struct workqueue_struct *ll2_recv_wq;
struct workqueue_struct *link_update_wq;
struct devlink *devlink;
struct delayed_work link_update;
struct delayed_work link_recovery;
struct completion flogi_compl;
struct completion fipvlan_compl;
/*
* Used to tell if we're in the window where we are waiting for
* the link to come back up before informting fcoe that the link is
* done.
*/
atomic_t link_down_tmo_valid;
#define QEDF_TIMER_INTERVAL (1 * HZ)
struct timer_list timer; /* One second book keeping timer */
#define QEDF_DRAIN_ACTIVE 1
#define QEDF_LL2_STARTED 2
#define QEDF_UNLOADING 3
#define QEDF_GRCDUMP_CAPTURE 4
#define QEDF_IN_RECOVERY 5
#define QEDF_DBG_STOP_IO 6
#define QEDF_PROBING 8
#define QEDF_STAG_IN_PROGRESS 9
unsigned long flags; /* Miscellaneous state flags */
int fipvlan_retries;
u8 num_queues;
struct global_queue **global_queues;
/* Pointer to array of queue structures */
struct qedf_glbl_q_params *p_cpuq;
/* Physical address of array of queue structures */
dma_addr_t hw_p_cpuq;
struct qedf_bdq_buf bdq[QEDF_BDQ_SIZE];
void *bdq_pbl;
dma_addr_t bdq_pbl_dma;
size_t bdq_pbl_mem_size;
void *bdq_pbl_list;
dma_addr_t bdq_pbl_list_dma;
u8 bdq_pbl_list_num_entries;
void __iomem *bdq_primary_prod;
void __iomem *bdq_secondary_prod;
uint16_t bdq_prod_idx;
/* Structure for holding all the fastpath for this qedf_ctx */
struct qedf_fastpath *fp_array;
struct qed_fcoe_tid tasks;
struct qedf_cmd_mgr *cmd_mgr;
/* Holds the PF parameters we pass to qed to start he FCoE function */
struct qed_pf_params pf_params;
/* Used to time middle path ELS and TM commands */
struct workqueue_struct *timer_work_queue;
#define QEDF_IO_WORK_MIN 64
mempool_t *io_mempool;
struct workqueue_struct *dpc_wq;
struct delayed_work recovery_work;
struct delayed_work board_disable_work;
struct delayed_work grcdump_work;
struct delayed_work stag_work;
u32 slow_sge_ios;
u32 fast_sge_ios;
uint8_t *grcdump;
uint32_t grcdump_size;
struct qedf_io_log io_trace_buf[QEDF_IO_TRACE_SIZE];
spinlock_t io_trace_lock;
uint16_t io_trace_idx;
bool stop_io_on_error;
u32 flogi_cnt;
u32 flogi_failed;
u32 flogi_pending;
/* Used for fc statistics */
struct mutex stats_mutex;
u64 input_requests;
u64 output_requests;
u64 control_requests;
u64 packet_aborts;
u64 alloc_failures;
u8 lun_resets;
u8 target_resets;
u8 task_set_fulls;
u8 busy;
/* Used for flush routine */
struct mutex flush_mutex;
};
struct io_bdt {
struct qedf_ioreq *io_req;
struct scsi_sge *bd_tbl;
dma_addr_t bd_tbl_dma;
u16 bd_valid;
};
struct qedf_cmd_mgr {
struct qedf_ctx *qedf;
u16 idx;
struct io_bdt **io_bdt_pool;
#define FCOE_PARAMS_NUM_TASKS 2048
struct qedf_ioreq cmds[FCOE_PARAMS_NUM_TASKS];
spinlock_t lock;
atomic_t free_list_cnt;
};
/* Stolen from qed_cxt_api.h and adapted for qed_fcoe_info
* Usage:
*
* void *ptr;
* ptr = qedf_get_task_mem(&qedf->tasks, 128);
*/
static inline void *qedf_get_task_mem(struct qed_fcoe_tid *info, u32 tid)
{
return (void *)(info->blocks[tid / info->num_tids_per_block] +
(tid % info->num_tids_per_block) * info->size);
}
static inline void qedf_stop_all_io(struct qedf_ctx *qedf)
{
set_bit(QEDF_DBG_STOP_IO, &qedf->flags);
}
/*
* Externs
*/
/*
* (QEDF_LOG_NPIV | QEDF_LOG_SESS | QEDF_LOG_LPORT | QEDF_LOG_ELS | QEDF_LOG_MQ
* | QEDF_LOG_IO | QEDF_LOG_UNSOL | QEDF_LOG_SCSI_TM | QEDF_LOG_MP_REQ |
* QEDF_LOG_EVT | QEDF_LOG_CONN | QEDF_LOG_DISC | QEDF_LOG_INFO)
*/
#define QEDF_DEFAULT_LOG_MASK 0x3CFB6
extern const struct qed_fcoe_ops *qed_ops;
extern uint qedf_dump_frames;
extern uint qedf_io_tracing;
extern uint qedf_stop_io_on_error;
extern uint qedf_link_down_tmo;
#define QEDF_RETRY_DELAY_MAX 600 /* 60 seconds */
extern bool qedf_retry_delay;
extern uint qedf_debug;
extern struct qedf_cmd_mgr *qedf_cmd_mgr_alloc(struct qedf_ctx *qedf);
extern void qedf_cmd_mgr_free(struct qedf_cmd_mgr *cmgr);
extern enum scsi_qc_status qedf_queuecommand(struct Scsi_Host *host,
struct scsi_cmnd *sc_cmd);
extern void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
extern u8 *qedf_get_src_mac(struct fc_lport *lport);
extern void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb);
extern void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf);
extern void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *io_req);
extern void qedf_process_warning_compl(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
extern void qedf_process_error_detect(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
extern void qedf_flush_active_ios(struct qedf_rport *fcport, u64 lun);
extern void qedf_release_cmd(struct kref *ref);
extern int qedf_initiate_abts(struct qedf_ioreq *io_req,
bool return_scsi_cmd_on_abts);
extern void qedf_process_abts_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *io_req);
extern struct qedf_ioreq *qedf_alloc_cmd(struct qedf_rport *fcport,
u8 cmd_type);
extern const struct attribute_group *qedf_host_groups[];
extern void qedf_cmd_timer_set(struct qedf_ctx *qedf, struct qedf_ioreq *io_req,
unsigned int timer_msec);
extern int qedf_init_mp_req(struct qedf_ioreq *io_req);
extern void qedf_init_mp_task(struct qedf_ioreq *io_req,
struct fcoe_task_context *task_ctx, struct fcoe_wqe *sqe);
extern u16 qedf_get_sqe_idx(struct qedf_rport *fcport);
extern void qedf_ring_doorbell(struct qedf_rport *fcport);
extern void qedf_process_els_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *els_req);
extern int qedf_send_rrq(struct qedf_ioreq *aborted_io_req);
extern int qedf_send_adisc(struct qedf_rport *fcport, struct fc_frame *fp);
extern int qedf_initiate_cleanup(struct qedf_ioreq *io_req,
bool return_scsi_cmd_on_abts);
extern void qedf_process_cleanup_compl(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
extern int qedf_initiate_tmf(struct fc_rport *rport, u64 lun, u8 tm_flags);
extern void qedf_process_tmf_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *io_req);
extern void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe);
extern void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req,
int result);
extern void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id);
extern void qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf);
extern void qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf);
extern void qedf_capture_grc_dump(struct qedf_ctx *qedf);
bool qedf_wait_for_upload(struct qedf_ctx *qedf);
extern void qedf_process_unsol_compl(struct qedf_ctx *qedf, uint16_t que_idx,
struct fcoe_cqe *cqe);
extern void qedf_restart_rport(struct qedf_rport *fcport);
extern int qedf_send_rec(struct qedf_ioreq *orig_io_req);
extern int qedf_post_io_req(struct qedf_rport *fcport,
struct qedf_ioreq *io_req);
extern void qedf_process_seq_cleanup_compl(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
extern int qedf_send_flogi(struct qedf_ctx *qedf);
extern void qedf_get_protocol_tlv_data(void *dev, void *data);
extern void qedf_fp_io_handler(struct work_struct *work);
extern void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data);
extern void qedf_wq_grcdump(struct work_struct *work);
void qedf_stag_change_work(struct work_struct *work);
void qedf_ctx_soft_reset(struct fc_lport *lport);
extern void qedf_schedule_hw_err_handler(void *dev,
enum qed_hw_err_type err_type);
#define FCOE_WORD_TO_BYTE 4
#define QEDF_MAX_TASK_NUM 0xFFFF
#define QL45xxx 0x165C
#define QL41xxx 0x8080
#define MAX_CT_PAYLOAD 2048
#define DISCOVERED_PORTS 4
#define NUMBER_OF_PORTS 1
struct fip_vlan {
struct ethhdr eth;
struct fip_header fip;
struct {
struct fip_mac_desc mac;
struct fip_wwn_desc wwnn;
} desc;
};
/* SQ/CQ Sizes */
#define GBL_RSVD_TASKS 16
#define NUM_TASKS_PER_CONNECTION 1024
#define NUM_RW_TASKS_PER_CONNECTION 512
#define FCOE_PARAMS_CQ_NUM_ENTRIES FCOE_PARAMS_NUM_TASKS
#define FCOE_PARAMS_CMDQ_NUM_ENTRIES FCOE_PARAMS_NUM_TASKS
#define SQ_NUM_ENTRIES NUM_TASKS_PER_CONNECTION
#define QEDF_FCOE_PARAMS_GL_RQ_PI 0
#define QEDF_FCOE_PARAMS_GL_CMD_PI 1
#define QEDF_READ (1 << 1)
#define QEDF_WRITE (1 << 0)
#define MAX_FIBRE_LUNS 0xffffffff
#define MIN_NUM_CPUS_MSIX(x) min_t(u32, x->dev_info.num_cqs, \
num_online_cpus())
/*
* PCI function probe defines
*/
/* Probe/remove called during normal PCI probe */
#define QEDF_MODE_NORMAL 0
/* Probe/remove called from qed error recovery */
#define QEDF_MODE_RECOVERY 1
#define SUPPORTED_25000baseKR_Full (1<<27)
#define SUPPORTED_50000baseKR2_Full (1<<28)
#define SUPPORTED_100000baseKR4_Full (1<<29)
#define SUPPORTED_100000baseCR4_Full (1<<30)
#endif
+186
View File
@@ -0,0 +1,186 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#include "qedf.h"
inline bool qedf_is_vport(struct qedf_ctx *qedf)
{
return qedf->lport->vport != NULL;
}
/* Get base qedf for physical port from vport */
static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf)
{
struct fc_lport *lport;
struct fc_lport *base_lport;
if (!(qedf_is_vport(qedf)))
return NULL;
lport = qedf->lport;
base_lport = shost_priv(vport_to_shost(lport->vport));
return lport_priv(base_lport);
}
static ssize_t fcoe_mac_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fc_lport *lport = shost_priv(class_to_shost(dev));
u32 port_id;
u8 lport_src_id[3];
u8 fcoe_mac[6];
port_id = fc_host_port_id(lport->host);
lport_src_id[2] = (port_id & 0x000000FF);
lport_src_id[1] = (port_id & 0x0000FF00) >> 8;
lport_src_id[0] = (port_id & 0x00FF0000) >> 16;
fc_fcoe_set_mac(fcoe_mac, lport_src_id);
return scnprintf(buf, PAGE_SIZE, "%pM\n", fcoe_mac);
}
static ssize_t fka_period_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fc_lport *lport = shost_priv(class_to_shost(dev));
struct qedf_ctx *qedf = lport_priv(lport);
int fka_period = -1;
if (qedf_is_vport(qedf))
qedf = qedf_get_base_qedf(qedf);
if (qedf->ctlr.sel_fcf)
fka_period = qedf->ctlr.sel_fcf->fka_period;
return scnprintf(buf, PAGE_SIZE, "%d\n", fka_period);
}
static DEVICE_ATTR_RO(fcoe_mac);
static DEVICE_ATTR_RO(fka_period);
static struct attribute *qedf_host_attrs[] = {
&dev_attr_fcoe_mac.attr,
&dev_attr_fka_period.attr,
NULL,
};
static const struct attribute_group qedf_host_attr_group = {
.attrs = qedf_host_attrs
};
const struct attribute_group *qedf_host_groups[] = {
&qedf_host_attr_group,
NULL
};
extern const struct qed_fcoe_ops *qed_ops;
void qedf_capture_grc_dump(struct qedf_ctx *qedf)
{
struct qedf_ctx *base_qedf;
/* Make sure we use the base qedf to take the GRC dump */
if (qedf_is_vport(qedf))
base_qedf = qedf_get_base_qedf(qedf);
else
base_qedf = qedf;
if (test_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags)) {
QEDF_INFO(&(base_qedf->dbg_ctx), QEDF_LOG_INFO,
"GRC Dump already captured.\n");
return;
}
qedf_get_grc_dump(base_qedf->cdev, qed_ops->common,
&base_qedf->grcdump, &base_qedf->grcdump_size);
QEDF_ERR(&(base_qedf->dbg_ctx), "GRC Dump captured.\n");
set_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags);
qedf_uevent_emit(base_qedf->lport->host, QEDF_UEVENT_CODE_GRCDUMP,
NULL);
}
static ssize_t
qedf_sysfs_read_grcdump(struct file *filep, struct kobject *kobj,
const struct bin_attribute *ba, char *buf, loff_t off,
size_t count)
{
ssize_t ret = 0;
struct fc_lport *lport = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qedf_ctx *qedf = lport_priv(lport);
if (test_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags)) {
ret = memory_read_from_buffer(buf, count, &off,
qedf->grcdump, qedf->grcdump_size);
} else {
QEDF_ERR(&(qedf->dbg_ctx), "GRC Dump not captured!\n");
}
return ret;
}
static ssize_t
qedf_sysfs_write_grcdump(struct file *filep, struct kobject *kobj,
const struct bin_attribute *ba, char *buf, loff_t off,
size_t count)
{
struct fc_lport *lport = NULL;
struct qedf_ctx *qedf = NULL;
long reading;
int ret = 0;
if (off != 0)
return ret;
lport = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
qedf = lport_priv(lport);
buf[1] = 0;
ret = kstrtol(buf, 10, &reading);
if (ret) {
QEDF_ERR(&(qedf->dbg_ctx), "Invalid input, err(%d)\n", ret);
return ret;
}
switch (reading) {
case 0:
memset(qedf->grcdump, 0, qedf->grcdump_size);
clear_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags);
break;
case 1:
qedf_capture_grc_dump(qedf);
break;
}
return count;
}
static const struct bin_attribute sysfs_grcdump_attr = {
.attr = {
.name = "grcdump",
.mode = S_IRUSR | S_IWUSR,
},
.size = 0,
.read = qedf_sysfs_read_grcdump,
.write = qedf_sysfs_write_grcdump,
};
static struct sysfs_bin_attrs bin_file_entries[] = {
{"grcdump", &sysfs_grcdump_attr},
{NULL},
};
void qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf)
{
qedf_create_sysfs_attr(qedf->lport->host, bin_file_entries);
}
void qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf)
{
qedf_remove_sysfs_attr(qedf->lport->host, bin_file_entries);
}
+175
View File
@@ -0,0 +1,175 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#include "qedf_dbg.h"
#include <linux/vmalloc.h>
void
qedf_dbg_err(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
const char *fmt, ...)
{
va_list va;
struct va_format vaf;
va_start(va, fmt);
vaf.fmt = fmt;
vaf.va = &va;
if (likely(qedf) && likely(qedf->pdev))
pr_err("[%s]:[%s:%d]:%d: %pV", dev_name(&(qedf->pdev->dev)),
func, line, qedf->host_no, &vaf);
else
pr_err("[0000:00:00.0]:[%s:%d]: %pV", func, line, &vaf);
va_end(va);
}
void
qedf_dbg_warn(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
const char *fmt, ...)
{
va_list va;
struct va_format vaf;
va_start(va, fmt);
vaf.fmt = fmt;
vaf.va = &va;
if (!(qedf_debug & QEDF_LOG_WARN))
goto ret;
if (likely(qedf) && likely(qedf->pdev))
pr_warn("[%s]:[%s:%d]:%d: %pV", dev_name(&(qedf->pdev->dev)),
func, line, qedf->host_no, &vaf);
else
pr_warn("[0000:00:00.0]:[%s:%d]: %pV", func, line, &vaf);
ret:
va_end(va);
}
void
qedf_dbg_notice(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
const char *fmt, ...)
{
va_list va;
struct va_format vaf;
va_start(va, fmt);
vaf.fmt = fmt;
vaf.va = &va;
if (!(qedf_debug & QEDF_LOG_NOTICE))
goto ret;
if (likely(qedf) && likely(qedf->pdev))
pr_notice("[%s]:[%s:%d]:%d: %pV",
dev_name(&(qedf->pdev->dev)), func, line,
qedf->host_no, &vaf);
else
pr_notice("[0000:00:00.0]:[%s:%d]: %pV", func, line, &vaf);
ret:
va_end(va);
}
void
qedf_dbg_info(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
u32 level, const char *fmt, ...)
{
va_list va;
struct va_format vaf;
va_start(va, fmt);
vaf.fmt = fmt;
vaf.va = &va;
if (!(qedf_debug & level))
goto ret;
if (likely(qedf) && likely(qedf->pdev))
pr_info("[%s]:[%s:%d]:%d: %pV", dev_name(&(qedf->pdev->dev)),
func, line, qedf->host_no, &vaf);
else
pr_info("[0000:00:00.0]:[%s:%d]: %pV", func, line, &vaf);
ret:
va_end(va);
}
int
qedf_alloc_grc_dump_buf(u8 **buf, uint32_t len)
{
*buf = vzalloc(len);
if (!(*buf))
return -ENOMEM;
return 0;
}
void
qedf_free_grc_dump_buf(uint8_t **buf)
{
vfree(*buf);
*buf = NULL;
}
int
qedf_get_grc_dump(struct qed_dev *cdev, const struct qed_common_ops *common,
u8 **buf, uint32_t *grcsize)
{
if (!*buf)
return -EINVAL;
return common->dbg_all_data(cdev, *buf);
}
void
qedf_uevent_emit(struct Scsi_Host *shost, u32 code, char *msg)
{
char event_string[40];
char *envp[] = {event_string, NULL};
memset(event_string, 0, sizeof(event_string));
switch (code) {
case QEDF_UEVENT_CODE_GRCDUMP:
if (msg)
strscpy(event_string, msg, sizeof(event_string));
else
sprintf(event_string, "GRCDUMP=%u", shost->host_no);
break;
default:
/* do nothing */
break;
}
kobject_uevent_env(&shost->shost_gendev.kobj, KOBJ_CHANGE, envp);
}
int
qedf_create_sysfs_attr(struct Scsi_Host *shost, struct sysfs_bin_attrs *iter)
{
int ret = 0;
for (; iter->name; iter++) {
ret = sysfs_create_bin_file(&shost->shost_gendev.kobj,
iter->attr);
if (ret)
pr_err("Unable to create sysfs %s attr, err(%d).\n",
iter->name, ret);
}
return ret;
}
void
qedf_remove_sysfs_attr(struct Scsi_Host *shost, struct sysfs_bin_attrs *iter)
{
for (; iter->name; iter++)
sysfs_remove_bin_file(&shost->shost_gendev.kobj, iter->attr);
}
+158
View File
@@ -0,0 +1,158 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#ifndef _QEDF_DBG_H_
#define _QEDF_DBG_H_
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <scsi/scsi_transport.h>
#include <linux/fs.h>
#include <linux/qed/common_hsi.h>
#include <linux/qed/qed_if.h>
extern uint qedf_debug;
/* Debug print level definitions */
#define QEDF_LOG_DEFAULT 0x1 /* Set default logging mask */
#define QEDF_LOG_INFO 0x2 /*
* Informational logs,
* MAC address, WWPN, WWNN
*/
#define QEDF_LOG_DISC 0x4 /* Init, discovery, rport */
#define QEDF_LOG_LL2 0x8 /* LL2, VLAN logs */
#define QEDF_LOG_CONN 0x10 /* Connection setup, cleanup */
#define QEDF_LOG_EVT 0x20 /* Events, link, mtu */
#define QEDF_LOG_TIMER 0x40 /* Timer events */
#define QEDF_LOG_MP_REQ 0x80 /* Middle Path (MP) logs */
#define QEDF_LOG_SCSI_TM 0x100 /* SCSI Aborts, Task Mgmt */
#define QEDF_LOG_UNSOL 0x200 /* unsolicited event logs */
#define QEDF_LOG_IO 0x400 /* scsi cmd, completion */
#define QEDF_LOG_MQ 0x800 /* Multi Queue logs */
#define QEDF_LOG_BSG 0x1000 /* BSG logs */
#define QEDF_LOG_DEBUGFS 0x2000 /* debugFS logs */
#define QEDF_LOG_LPORT 0x4000 /* lport logs */
#define QEDF_LOG_ELS 0x8000 /* ELS logs */
#define QEDF_LOG_NPIV 0x10000 /* NPIV logs */
#define QEDF_LOG_SESS 0x20000 /* Connection setup, cleanup */
#define QEDF_LOG_TID 0x80000 /*
* FW TID context acquire
* free
*/
#define QEDF_TRACK_TID 0x100000 /*
* Track TID state. To be
* enabled only at module load
* and not run-time.
*/
#define QEDF_TRACK_CMD_LIST 0x300000 /*
* Track active cmd list nodes,
* done with reference to TID,
* hence TRACK_TID also enabled.
*/
#define QEDF_LOG_NOTICE 0x40000000 /* Notice logs */
#define QEDF_LOG_WARN 0x80000000 /* Warning logs */
#define QEDF_DEBUGFS_LOG_LEN (2 * PAGE_SIZE)
/* Debug context structure */
struct qedf_dbg_ctx {
unsigned int host_no;
struct pci_dev *pdev;
#ifdef CONFIG_DEBUG_FS
struct dentry *bdf_dentry;
#endif
};
#define QEDF_ERR(pdev, fmt, ...) \
qedf_dbg_err(pdev, __func__, __LINE__, fmt, ## __VA_ARGS__)
#define QEDF_WARN(pdev, fmt, ...) \
qedf_dbg_warn(pdev, __func__, __LINE__, fmt, ## __VA_ARGS__)
#define QEDF_NOTICE(pdev, fmt, ...) \
qedf_dbg_notice(pdev, __func__, __LINE__, fmt, ## __VA_ARGS__)
#define QEDF_INFO(pdev, level, fmt, ...) \
qedf_dbg_info(pdev, __func__, __LINE__, level, fmt, \
## __VA_ARGS__)
__printf(4, 5)
void qedf_dbg_err(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
const char *fmt, ...);
__printf(4, 5)
void qedf_dbg_warn(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
const char *, ...);
__printf(4, 5)
void qedf_dbg_notice(struct qedf_dbg_ctx *qedf, const char *func,
u32 line, const char *, ...);
__printf(5, 6)
void qedf_dbg_info(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
u32 info, const char *fmt, ...);
/* GRC Dump related defines */
struct Scsi_Host;
#define QEDF_UEVENT_CODE_GRCDUMP 0
struct sysfs_bin_attrs {
char *name;
const struct bin_attribute *attr;
};
extern int qedf_alloc_grc_dump_buf(uint8_t **buf, uint32_t len);
extern void qedf_free_grc_dump_buf(uint8_t **buf);
extern int qedf_get_grc_dump(struct qed_dev *cdev,
const struct qed_common_ops *common, uint8_t **buf,
uint32_t *grcsize);
extern void qedf_uevent_emit(struct Scsi_Host *shost, u32 code, char *msg);
extern int qedf_create_sysfs_attr(struct Scsi_Host *shost,
struct sysfs_bin_attrs *iter);
extern void qedf_remove_sysfs_attr(struct Scsi_Host *shost,
struct sysfs_bin_attrs *iter);
struct qedf_debugfs_ops {
char *name;
struct qedf_list_of_funcs *qedf_funcs;
};
extern const struct qedf_debugfs_ops qedf_debugfs_ops[];
extern const struct file_operations qedf_dbg_fops[];
#ifdef CONFIG_DEBUG_FS
/* DebugFS related code */
struct qedf_list_of_funcs {
char *oper_str;
ssize_t (*oper_func)(struct qedf_dbg_ctx *qedf);
};
#define qedf_dbg_fileops(drv, ops) \
{ \
.owner = THIS_MODULE, \
.open = simple_open, \
.read = drv##_dbg_##ops##_cmd_read, \
.write = drv##_dbg_##ops##_cmd_write \
}
/* Used for debugfs sequential files */
#define qedf_dbg_fileops_seq(drv, ops) \
{ \
.owner = THIS_MODULE, \
.open = drv##_dbg_##ops##_open, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release, \
}
extern void qedf_dbg_host_init(struct qedf_dbg_ctx *qedf,
const struct qedf_debugfs_ops *dops,
const struct file_operations *fops);
extern void qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf);
extern void qedf_dbg_init(char *drv_name);
extern void qedf_dbg_exit(void);
#endif /* CONFIG_DEBUG_FS */
#endif /* _QEDF_DBG_H_ */
@@ -0,0 +1,494 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 QLogic Corporation
*/
#ifdef CONFIG_DEBUG_FS
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include "qedf.h"
#include "qedf_dbg.h"
static struct dentry *qedf_dbg_root;
/*
* qedf_dbg_host_init - setup the debugfs file for the pf
*/
void
qedf_dbg_host_init(struct qedf_dbg_ctx *qedf,
const struct qedf_debugfs_ops *dops,
const struct file_operations *fops)
{
char host_dirname[32];
QEDF_INFO(qedf, QEDF_LOG_DEBUGFS, "Creating debugfs host node\n");
/* create pf dir */
sprintf(host_dirname, "host%u", qedf->host_no);
qedf->bdf_dentry = debugfs_create_dir(host_dirname, qedf_dbg_root);
/* create debugfs files */
while (dops) {
if (!(dops->name))
break;
debugfs_create_file(dops->name, 0600, qedf->bdf_dentry, qedf,
fops);
dops++;
fops++;
}
}
/*
* qedf_dbg_host_exit - clear out the pf's debugfs entries
*/
void
qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf_dbg)
{
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Destroying debugfs host "
"entry\n");
/* remove debugfs entries of this PF */
debugfs_remove_recursive(qedf_dbg->bdf_dentry);
qedf_dbg->bdf_dentry = NULL;
}
/*
* qedf_dbg_init - start up debugfs for the driver
*/
void
qedf_dbg_init(char *drv_name)
{
QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Creating debugfs root node\n");
/* create qed dir in root of debugfs. NULL means debugfs root */
qedf_dbg_root = debugfs_create_dir(drv_name, NULL);
}
/*
* qedf_dbg_exit - clean out the driver's debugfs entries
*/
void
qedf_dbg_exit(void)
{
QEDF_INFO(NULL, QEDF_LOG_DEBUGFS, "Destroying debugfs root "
"entry\n");
/* remove qed dir in root of debugfs */
debugfs_remove_recursive(qedf_dbg_root);
qedf_dbg_root = NULL;
}
const struct qedf_debugfs_ops qedf_debugfs_ops[] = {
{ "fp_int", NULL },
{ "io_trace", NULL },
{ "debug", NULL },
{ "stop_io_on_error", NULL},
{ "driver_stats", NULL},
{ "clear_stats", NULL},
{ "offload_stats", NULL},
/* This must be last */
{ NULL, NULL }
};
DECLARE_PER_CPU(struct qedf_percpu_iothread_s, qedf_percpu_iothreads);
static ssize_t
qedf_dbg_fp_int_cmd_read(struct file *filp, char __user *buffer, size_t count,
loff_t *ppos)
{
ssize_t ret;
size_t cnt = 0;
char *cbuf;
int id;
struct qedf_fastpath *fp = NULL;
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
struct qedf_ctx *qedf = container_of(qedf_dbg,
struct qedf_ctx, dbg_ctx);
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
cbuf = vmalloc(QEDF_DEBUGFS_LOG_LEN);
if (!cbuf)
return 0;
cnt += scnprintf(cbuf + cnt, QEDF_DEBUGFS_LOG_LEN - cnt, "\nFastpath I/O completions\n\n");
for (id = 0; id < qedf->num_queues; id++) {
fp = &(qedf->fp_array[id]);
if (fp->sb_id == QEDF_SB_ID_NULL)
continue;
cnt += scnprintf(cbuf + cnt, QEDF_DEBUGFS_LOG_LEN - cnt,
"#%d: %lu\n", id, fp->completions);
}
ret = simple_read_from_buffer(buffer, count, ppos, cbuf, cnt);
vfree(cbuf);
return ret;
}
static ssize_t
qedf_dbg_fp_int_cmd_write(struct file *filp, const char __user *buffer,
size_t count, loff_t *ppos)
{
if (!count || *ppos)
return 0;
return count;
}
static ssize_t
qedf_dbg_debug_cmd_read(struct file *filp, char __user *buffer, size_t count,
loff_t *ppos)
{
int cnt;
char cbuf[32];
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "debug mask=0x%x\n", qedf_debug);
cnt = scnprintf(cbuf, sizeof(cbuf), "debug mask = 0x%x\n", qedf_debug);
return simple_read_from_buffer(buffer, count, ppos, cbuf, cnt);
}
static ssize_t
qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer,
size_t count, loff_t *ppos)
{
uint32_t val;
void *kern_buf;
int rval;
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
if (!count || *ppos)
return 0;
kern_buf = memdup_user_nul(buffer, count);
if (IS_ERR(kern_buf))
return PTR_ERR(kern_buf);
rval = kstrtouint(kern_buf, 10, &val);
kfree(kern_buf);
if (rval)
return rval;
if (val == 1)
qedf_debug = QEDF_DEFAULT_LOG_MASK;
else
qedf_debug = val;
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Setting debug=0x%x.\n", val);
return count;
}
static ssize_t
qedf_dbg_stop_io_on_error_cmd_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
int cnt;
char cbuf[7];
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
struct qedf_ctx *qedf = container_of(qedf_dbg,
struct qedf_ctx, dbg_ctx);
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
cnt = scnprintf(cbuf, sizeof(cbuf), "%s\n",
qedf->stop_io_on_error ? "true" : "false");
return simple_read_from_buffer(buffer, count, ppos, cbuf, cnt);
}
static ssize_t
qedf_dbg_stop_io_on_error_cmd_write(struct file *filp,
const char __user *buffer, size_t count,
loff_t *ppos)
{
void *kern_buf;
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx,
dbg_ctx);
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
if (!count || *ppos)
return 0;
kern_buf = memdup_user(buffer, 6);
if (IS_ERR(kern_buf))
return PTR_ERR(kern_buf);
if (strncmp(kern_buf, "false", 5) == 0)
qedf->stop_io_on_error = false;
else if (strncmp(kern_buf, "true", 4) == 0)
qedf->stop_io_on_error = true;
else if (strncmp(kern_buf, "now", 3) == 0)
/* Trigger from user to stop all I/O on this host */
set_bit(QEDF_DBG_STOP_IO, &qedf->flags);
kfree(kern_buf);
return count;
}
static int
qedf_io_trace_show(struct seq_file *s, void *unused)
{
int i, idx = 0;
struct qedf_ctx *qedf = s->private;
struct qedf_dbg_ctx *qedf_dbg = &qedf->dbg_ctx;
struct qedf_io_log *io_log;
unsigned long flags;
if (!qedf_io_tracing) {
seq_puts(s, "I/O tracing not enabled.\n");
goto out;
}
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n");
spin_lock_irqsave(&qedf->io_trace_lock, flags);
idx = qedf->io_trace_idx;
for (i = 0; i < QEDF_IO_TRACE_SIZE; i++) {
io_log = &qedf->io_trace_buf[idx];
seq_printf(s, "%d:", io_log->direction);
seq_printf(s, "0x%x:", io_log->task_id);
seq_printf(s, "0x%06x:", io_log->port_id);
seq_printf(s, "%d:", io_log->lun);
seq_printf(s, "0x%02x:", io_log->op);
seq_printf(s, "0x%02x%02x%02x%02x:", io_log->lba[0],
io_log->lba[1], io_log->lba[2], io_log->lba[3]);
seq_printf(s, "%d:", io_log->bufflen);
seq_printf(s, "%d:", io_log->sg_count);
seq_printf(s, "0x%08x:", io_log->result);
seq_printf(s, "%lu:", io_log->jiffies);
seq_printf(s, "%d:", io_log->refcount);
seq_printf(s, "%d:", io_log->req_cpu);
seq_printf(s, "%d:", io_log->int_cpu);
seq_printf(s, "%d:", io_log->rsp_cpu);
seq_printf(s, "%d\n", io_log->sge_type);
idx++;
if (idx == QEDF_IO_TRACE_SIZE)
idx = 0;
}
spin_unlock_irqrestore(&qedf->io_trace_lock, flags);
out:
return 0;
}
static int
qedf_dbg_io_trace_open(struct inode *inode, struct file *file)
{
struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
struct qedf_ctx *qedf = container_of(qedf_dbg,
struct qedf_ctx, dbg_ctx);
return single_open(file, qedf_io_trace_show, qedf);
}
/* Based on fip_state enum from libfcoe.h */
static char *fip_state_names[] = {
"FIP_ST_DISABLED",
"FIP_ST_LINK_WAIT",
"FIP_ST_AUTO",
"FIP_ST_NON_FIP",
"FIP_ST_ENABLED",
"FIP_ST_VNMP_START",
"FIP_ST_VNMP_PROBE1",
"FIP_ST_VNMP_PROBE2",
"FIP_ST_VNMP_CLAIM",
"FIP_ST_VNMP_UP",
};
/* Based on fc_rport_state enum from libfc.h */
static char *fc_rport_state_names[] = {
"RPORT_ST_INIT",
"RPORT_ST_FLOGI",
"RPORT_ST_PLOGI_WAIT",
"RPORT_ST_PLOGI",
"RPORT_ST_PRLI",
"RPORT_ST_RTV",
"RPORT_ST_READY",
"RPORT_ST_ADISC",
"RPORT_ST_DELETE",
};
static int
qedf_driver_stats_show(struct seq_file *s, void *unused)
{
struct qedf_ctx *qedf = s->private;
struct qedf_rport *fcport;
struct fc_rport_priv *rdata;
seq_printf(s, "Host WWNN/WWPN: %016llx/%016llx\n",
qedf->wwnn, qedf->wwpn);
seq_printf(s, "Host NPortID: %06x\n", qedf->lport->port_id);
seq_printf(s, "Link State: %s\n", atomic_read(&qedf->link_state) ?
"Up" : "Down");
seq_printf(s, "Logical Link State: %s\n", qedf->lport->link_up ?
"Up" : "Down");
seq_printf(s, "FIP state: %s\n", fip_state_names[qedf->ctlr.state]);
seq_printf(s, "FIP VLAN ID: %d\n", qedf->vlan_id & 0xfff);
seq_printf(s, "FIP 802.1Q Priority: %d\n", qedf->prio);
if (qedf->ctlr.sel_fcf) {
seq_printf(s, "FCF WWPN: %016llx\n",
qedf->ctlr.sel_fcf->switch_name);
seq_printf(s, "FCF MAC: %pM\n", qedf->ctlr.sel_fcf->fcf_mac);
} else {
seq_puts(s, "FCF not selected\n");
}
seq_puts(s, "\nSGE stats:\n\n");
seq_printf(s, "cmg_mgr free io_reqs: %d\n",
atomic_read(&qedf->cmd_mgr->free_list_cnt));
seq_printf(s, "slow SGEs: %d\n", qedf->slow_sge_ios);
seq_printf(s, "fast SGEs: %d\n\n", qedf->fast_sge_ios);
seq_puts(s, "Offloaded ports:\n\n");
rcu_read_lock();
list_for_each_entry_rcu(fcport, &qedf->fcports, peers) {
rdata = fcport->rdata;
if (rdata == NULL)
continue;
seq_printf(s, "%016llx/%016llx/%06x: state=%s, free_sqes=%d, num_active_ios=%d\n",
rdata->rport->node_name, rdata->rport->port_name,
rdata->ids.port_id,
fc_rport_state_names[rdata->rp_state],
atomic_read(&fcport->free_sqes),
atomic_read(&fcport->num_active_ios));
}
rcu_read_unlock();
return 0;
}
static int
qedf_dbg_driver_stats_open(struct inode *inode, struct file *file)
{
struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
struct qedf_ctx *qedf = container_of(qedf_dbg,
struct qedf_ctx, dbg_ctx);
return single_open(file, qedf_driver_stats_show, qedf);
}
static ssize_t
qedf_dbg_clear_stats_cmd_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
int cnt = 0;
/* Essentially a read stub */
cnt = min_t(int, count, cnt - *ppos);
*ppos += cnt;
return cnt;
}
static ssize_t
qedf_dbg_clear_stats_cmd_write(struct file *filp,
const char __user *buffer, size_t count,
loff_t *ppos)
{
struct qedf_dbg_ctx *qedf_dbg =
(struct qedf_dbg_ctx *)filp->private_data;
struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx,
dbg_ctx);
QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "Clearing stat counters.\n");
if (!count || *ppos)
return 0;
/* Clear stat counters exposed by 'stats' node */
qedf->slow_sge_ios = 0;
qedf->fast_sge_ios = 0;
return count;
}
static int
qedf_offload_stats_show(struct seq_file *s, void *unused)
{
struct qedf_ctx *qedf = s->private;
struct qed_fcoe_stats *fw_fcoe_stats;
fw_fcoe_stats = kmalloc_obj(struct qed_fcoe_stats);
if (!fw_fcoe_stats) {
QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate memory for "
"fw_fcoe_stats.\n");
goto out;
}
/* Query firmware for offload stats */
qed_ops->get_stats(qedf->cdev, fw_fcoe_stats);
seq_printf(s, "fcoe_rx_byte_cnt=%llu\n"
"fcoe_rx_data_pkt_cnt=%llu\n"
"fcoe_rx_xfer_pkt_cnt=%llu\n"
"fcoe_rx_other_pkt_cnt=%llu\n"
"fcoe_silent_drop_pkt_cmdq_full_cnt=%u\n"
"fcoe_silent_drop_pkt_crc_error_cnt=%u\n"
"fcoe_silent_drop_pkt_task_invalid_cnt=%u\n"
"fcoe_silent_drop_total_pkt_cnt=%u\n"
"fcoe_silent_drop_pkt_rq_full_cnt=%u\n"
"fcoe_tx_byte_cnt=%llu\n"
"fcoe_tx_data_pkt_cnt=%llu\n"
"fcoe_tx_xfer_pkt_cnt=%llu\n"
"fcoe_tx_other_pkt_cnt=%llu\n",
fw_fcoe_stats->fcoe_rx_byte_cnt,
fw_fcoe_stats->fcoe_rx_data_pkt_cnt,
fw_fcoe_stats->fcoe_rx_xfer_pkt_cnt,
fw_fcoe_stats->fcoe_rx_other_pkt_cnt,
fw_fcoe_stats->fcoe_silent_drop_pkt_cmdq_full_cnt,
fw_fcoe_stats->fcoe_silent_drop_pkt_crc_error_cnt,
fw_fcoe_stats->fcoe_silent_drop_pkt_task_invalid_cnt,
fw_fcoe_stats->fcoe_silent_drop_total_pkt_cnt,
fw_fcoe_stats->fcoe_silent_drop_pkt_rq_full_cnt,
fw_fcoe_stats->fcoe_tx_byte_cnt,
fw_fcoe_stats->fcoe_tx_data_pkt_cnt,
fw_fcoe_stats->fcoe_tx_xfer_pkt_cnt,
fw_fcoe_stats->fcoe_tx_other_pkt_cnt);
kfree(fw_fcoe_stats);
out:
return 0;
}
static int
qedf_dbg_offload_stats_open(struct inode *inode, struct file *file)
{
struct qedf_dbg_ctx *qedf_dbg = inode->i_private;
struct qedf_ctx *qedf = container_of(qedf_dbg,
struct qedf_ctx, dbg_ctx);
return single_open(file, qedf_offload_stats_show, qedf);
}
const struct file_operations qedf_dbg_fops[] = {
qedf_dbg_fileops(qedf, fp_int),
qedf_dbg_fileops_seq(qedf, io_trace),
qedf_dbg_fileops(qedf, debug),
qedf_dbg_fileops(qedf, stop_io_on_error),
qedf_dbg_fileops_seq(qedf, driver_stats),
qedf_dbg_fileops(qedf, clear_stats),
qedf_dbg_fileops_seq(qedf, offload_stats),
/* This must be last */
{ },
};
#else /* CONFIG_DEBUG_FS */
void qedf_dbg_host_init(struct qedf_dbg_ctx *);
void qedf_dbg_host_exit(struct qedf_dbg_ctx *);
void qedf_dbg_init(char *);
void qedf_dbg_exit(void);
#endif /* CONFIG_DEBUG_FS */
File diff suppressed because it is too large Load Diff
+301
View File
@@ -0,0 +1,301 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include "qedf.h"
extern const struct qed_fcoe_ops *qed_ops;
/*
* FIP VLAN functions that will eventually move to libfcoe.
*/
void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf)
{
struct sk_buff *skb;
char *eth_fr;
struct fip_vlan *vlan;
#define MY_FIP_ALL_FCF_MACS ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 })
static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS;
unsigned long flags = 0;
int rc;
skb = dev_alloc_skb(sizeof(struct fip_vlan));
if (!skb) {
QEDF_ERR(&qedf->dbg_ctx,
"Failed to allocate skb.\n");
return;
}
eth_fr = (char *)skb->data;
vlan = (struct fip_vlan *)eth_fr;
memset(vlan, 0, sizeof(*vlan));
ether_addr_copy(vlan->eth.h_source, qedf->mac);
ether_addr_copy(vlan->eth.h_dest, my_fcoe_all_fcfs);
vlan->eth.h_proto = htons(ETH_P_FIP);
vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
vlan->fip.fip_op = htons(FIP_OP_VLAN);
vlan->fip.fip_subcode = FIP_SC_VL_REQ;
vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
ether_addr_copy(vlan->desc.mac.fd_mac, qedf->mac);
vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
put_unaligned_be64(qedf->lport->wwnn, &vlan->desc.wwnn.fd_wwn);
skb_put(skb, sizeof(*vlan));
skb->protocol = htons(ETH_P_FIP);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Sending FIP VLAN "
"request.");
if (atomic_read(&qedf->link_state) != QEDF_LINK_UP) {
QEDF_WARN(&(qedf->dbg_ctx), "Cannot send vlan request "
"because link is not up.\n");
kfree_skb(skb);
return;
}
set_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &flags);
rc = qed_ops->ll2->start_xmit(qedf->cdev, skb, flags);
if (rc) {
QEDF_ERR(&qedf->dbg_ctx, "start_xmit failed rc = %d.\n", rc);
kfree_skb(skb);
return;
}
}
static void qedf_fcoe_process_vlan_resp(struct qedf_ctx *qedf,
struct sk_buff *skb)
{
struct fip_header *fiph;
struct fip_desc *desc;
u16 vid = 0;
ssize_t rlen;
size_t dlen;
fiph = (struct fip_header *)(((void *)skb->data) + 2 * ETH_ALEN + 2);
rlen = ntohs(fiph->fip_dl_len) * 4;
desc = (struct fip_desc *)(fiph + 1);
while (rlen > 0) {
dlen = desc->fip_dlen * FIP_BPW;
switch (desc->fip_dtype) {
case FIP_DT_VLAN:
vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
break;
}
desc = (struct fip_desc *)((char *)desc + dlen);
rlen -= dlen;
}
if (atomic_read(&qedf->link_state) == QEDF_LINK_DOWN) {
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"Dropping VLAN response as link is down.\n");
return;
}
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "VLAN response, "
"vid=0x%x.\n", vid);
if (vid > 0 && qedf->vlan_id != vid) {
qedf_set_vlan_id(qedf, vid);
/* Inform waiter that it's ok to call fcoe_ctlr_link up() */
if (!completion_done(&qedf->fipvlan_compl))
complete(&qedf->fipvlan_compl);
}
}
void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
struct qedf_ctx *qedf = container_of(fip, struct qedf_ctx, ctlr);
struct ethhdr *eth_hdr;
struct fip_header *fiph;
u16 op, vlan_tci = 0;
u8 sub;
int rc = -1;
if (!test_bit(QEDF_LL2_STARTED, &qedf->flags)) {
QEDF_WARN(&(qedf->dbg_ctx), "LL2 not started\n");
kfree_skb(skb);
return;
}
fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
op = ntohs(fiph->fip_op);
sub = fiph->fip_subcode;
/*
* Add VLAN tag to non-offload FIP frame based on current stored VLAN
* for FIP/FCoE traffic.
*/
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), qedf->vlan_id);
/* Get VLAN ID from skb for printing purposes */
__vlan_hwaccel_get_tag(skb, &vlan_tci);
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "FIP frame send: "
"dest=%pM op=%x sub=%x vlan=%04x.", eth_hdr->h_dest, op, sub,
vlan_tci);
if (qedf_dump_frames)
print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb->len, false);
rc = qed_ops->ll2->start_xmit(qedf->cdev, skb, 0);
if (rc) {
QEDF_ERR(&qedf->dbg_ctx, "start_xmit failed rc = %d.\n", rc);
kfree_skb(skb);
return;
}
}
static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
/* Process incoming FIP frames. */
void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
{
struct ethhdr *eth_hdr;
struct fip_header *fiph;
struct fip_desc *desc;
struct fip_mac_desc *mp;
struct fip_wwn_desc *wp;
struct fip_vn_desc *vp;
size_t rlen, dlen;
u16 op;
u8 sub;
bool fcf_valid = false;
/* Default is to handle CVL regardless of fabric id descriptor */
bool fabric_id_valid = true;
bool fc_wwpn_valid = false;
u64 switch_name;
u16 vlan = 0;
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
op = ntohs(fiph->fip_op);
sub = fiph->fip_subcode;
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
"FIP frame received: skb=%p fiph=%p source=%pM destn=%pM op=%x sub=%x vlan=%04x",
skb, fiph, eth_hdr->h_source, eth_hdr->h_dest, op,
sub, vlan);
if (qedf_dump_frames)
print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb->len, false);
if (!ether_addr_equal(eth_hdr->h_dest, qedf->mac) &&
!ether_addr_equal(eth_hdr->h_dest, fcoe_all_enode) &&
!ether_addr_equal(eth_hdr->h_dest, qedf->data_src_addr)) {
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
"Dropping FIP type 0x%x pkt due to destination MAC mismatch dest_mac=%pM ctlr.dest_addr=%pM data_src_addr=%pM.\n",
op, eth_hdr->h_dest, qedf->mac,
qedf->data_src_addr);
kfree_skb(skb);
return;
}
/* Handle FIP VLAN resp in the driver */
if (op == FIP_OP_VLAN && sub == FIP_SC_VL_NOTE) {
qedf_fcoe_process_vlan_resp(qedf, skb);
kfree_skb(skb);
} else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) {
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Clear virtual "
"link received.\n");
/* Check that an FCF has been selected by fcoe */
if (qedf->ctlr.sel_fcf == NULL) {
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
"Dropping CVL since FCF has not been selected "
"yet.");
kfree_skb(skb);
return;
}
/*
* We need to loop through the CVL descriptors to determine
* if we want to reset the fcoe link
*/
rlen = ntohs(fiph->fip_dl_len) * FIP_BPW;
desc = (struct fip_desc *)(fiph + 1);
while (rlen >= sizeof(*desc)) {
dlen = desc->fip_dlen * FIP_BPW;
switch (desc->fip_dtype) {
case FIP_DT_MAC:
mp = (struct fip_mac_desc *)desc;
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"Switch fd_mac=%pM.\n", mp->fd_mac);
if (ether_addr_equal(mp->fd_mac,
qedf->ctlr.sel_fcf->fcf_mac))
fcf_valid = true;
break;
case FIP_DT_NAME:
wp = (struct fip_wwn_desc *)desc;
switch_name = get_unaligned_be64(&wp->fd_wwn);
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"Switch fd_wwn=%016llx fcf_switch_name=%016llx.\n",
switch_name,
qedf->ctlr.sel_fcf->switch_name);
if (switch_name ==
qedf->ctlr.sel_fcf->switch_name)
fc_wwpn_valid = true;
break;
case FIP_DT_VN_ID:
fabric_id_valid = false;
vp = (struct fip_vn_desc *)desc;
QEDF_ERR(&qedf->dbg_ctx,
"CVL vx_port fd_fc_id=0x%x fd_mac=%pM fd_wwpn=%016llx.\n",
ntoh24(vp->fd_fc_id), vp->fd_mac,
get_unaligned_be64(&vp->fd_wwpn));
/* Check for vx_port wwpn OR Check vx_port
* fabric ID OR Check vx_port MAC
*/
if ((get_unaligned_be64(&vp->fd_wwpn) ==
qedf->wwpn) ||
(ntoh24(vp->fd_fc_id) ==
qedf->lport->port_id) ||
(ether_addr_equal(vp->fd_mac,
qedf->data_src_addr))) {
fabric_id_valid = true;
}
break;
default:
/* Ignore anything else */
break;
}
desc = (struct fip_desc *)((char *)desc + dlen);
rlen -= dlen;
}
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"fcf_valid=%d fabric_id_valid=%d fc_wwpn_valid=%d.\n",
fcf_valid, fabric_id_valid, fc_wwpn_valid);
if (fcf_valid && fabric_id_valid && fc_wwpn_valid)
qedf_ctx_soft_reset(qedf->lport);
kfree_skb(skb);
} else {
/* Everything else is handled by libfcoe */
__skb_pull(skb, ETH_HLEN);
fcoe_ctlr_recv(&qedf->ctlr, skb);
}
}
u8 *qedf_get_src_mac(struct fc_lport *lport)
{
struct qedf_ctx *qedf = lport_priv(lport);
return qedf->data_src_addr;
}
+351
View File
@@ -0,0 +1,351 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#ifndef __QEDF_HSI__
#define __QEDF_HSI__
/*
* Add include to common target
*/
#include <linux/qed/common_hsi.h>
/*
* Add include to common storage target
*/
#include <linux/qed/storage_common.h>
/*
* Add include to common fcoe target for both eCore and protocol driver
*/
#include <linux/qed/fcoe_common.h>
/*
* FCoE CQ element ABTS information
*/
struct fcoe_abts_info {
u8 r_ctl /* R_CTL in the ABTS response frame */;
u8 reserved0;
__le16 rx_id;
__le32 reserved2[2];
__le32 fc_payload[3] /* ABTS FC payload response frame */;
};
/*
* FCoE class type
*/
enum fcoe_class_type {
FCOE_TASK_CLASS_TYPE_3,
FCOE_TASK_CLASS_TYPE_2,
MAX_FCOE_CLASS_TYPE
};
/*
* FCoE CMDQ element control information
*/
struct fcoe_cmdqe_control {
__le16 conn_id;
u8 num_additional_cmdqes;
u8 cmdType;
/* true for ABTS request cmdqe. used in Target mode */
#define FCOE_CMDQE_CONTROL_ABTSREQCMD_MASK 0x1
#define FCOE_CMDQE_CONTROL_ABTSREQCMD_SHIFT 0
#define FCOE_CMDQE_CONTROL_RESERVED1_MASK 0x7F
#define FCOE_CMDQE_CONTROL_RESERVED1_SHIFT 1
u8 reserved2[4];
};
/*
* FCoE control + payload CMDQ element
*/
struct fcoe_cmdqe {
struct fcoe_cmdqe_control hdr;
u8 fc_header[24];
__le32 fcp_cmd_payload[8];
};
/*
* FCP RSP flags
*/
struct fcoe_fcp_rsp_flags {
u8 flags;
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_MASK 0x1
#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_MASK 0x1
#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_MASK 0x1
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_MASK 0x1
#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_MASK 0x1
#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_MASK 0x7
#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
};
/*
* FCoE CQ element response information
*/
struct fcoe_cqe_rsp_info {
struct fcoe_fcp_rsp_flags rsp_flags;
u8 scsi_status_code;
__le16 retry_delay_timer;
__le32 fcp_resid;
__le32 fcp_sns_len;
__le32 fcp_rsp_len;
__le16 rx_id;
u8 fw_error_flags;
#define FCOE_CQE_RSP_INFO_FW_UNDERRUN_MASK 0x1 /* FW detected underrun */
#define FCOE_CQE_RSP_INFO_FW_UNDERRUN_SHIFT 0
#define FCOE_CQE_RSP_INFO_RESREVED_MASK 0x7F
#define FCOE_CQE_RSP_INFO_RESREVED_SHIFT 1
u8 reserved;
__le32 fw_residual /* Residual bytes calculated by FW */;
};
/*
* FCoE CQ element Target completion information
*/
struct fcoe_cqe_target_info {
__le16 rx_id;
__le16 reserved0;
__le32 reserved1[5];
};
/*
* FCoE error/warning reporting entry
*/
struct fcoe_err_report_entry {
__le32 err_warn_bitmap_lo /* Error bitmap lower 32 bits */;
__le32 err_warn_bitmap_hi /* Error bitmap higher 32 bits */;
/* Buffer offset the beginning of the Sequence last transmitted */
__le32 tx_buf_off;
/* Buffer offset from the beginning of the Sequence last received */
__le32 rx_buf_off;
__le16 rx_id /* RX_ID of the associated task */;
__le16 reserved1;
__le32 reserved2;
};
/*
* FCoE CQ element middle path information
*/
struct fcoe_cqe_midpath_info {
__le32 data_placement_size;
__le16 rx_id;
__le16 reserved0;
__le32 reserved1[4];
};
/*
* FCoE CQ element unsolicited information
*/
struct fcoe_unsolic_info {
/* BD information: Physical address and opaque data */
struct scsi_bd bd_info;
__le16 conn_id /* Connection ID the frame is associated to */;
__le16 pkt_len /* Packet length */;
u8 reserved1[4];
};
/*
* FCoE warning reporting entry
*/
struct fcoe_warning_report_entry {
/* BD information: Physical address and opaque data */
struct scsi_bd bd_info;
/* Buffer offset the beginning of the Sequence last transmitted */
__le32 buf_off;
__le16 rx_id /* RX_ID of the associated task */;
__le16 reserved1;
};
/*
* FCoE CQ element information
*/
union fcoe_cqe_info {
struct fcoe_cqe_rsp_info rsp_info /* Response completion information */;
/* Target completion information */
struct fcoe_cqe_target_info target_info;
/* Error completion information */
struct fcoe_err_report_entry err_info;
struct fcoe_abts_info abts_info /* ABTS completion information */;
/* Middle path completion information */
struct fcoe_cqe_midpath_info midpath_info;
/* Unsolicited packet completion information */
struct fcoe_unsolic_info unsolic_info;
/* Warning completion information (Rec Tov expiration) */
struct fcoe_warning_report_entry warn_info;
};
/*
* FCoE CQ element
*/
struct fcoe_cqe {
__le32 cqe_data;
/* The task identifier (OX_ID) to be completed */
#define FCOE_CQE_TASK_ID_MASK 0xFFFF
#define FCOE_CQE_TASK_ID_SHIFT 0
/*
* The CQE type: 0x0 Indicating on a pending work request completion.
* 0x1 - Indicating on an unsolicited event notification. use enum
* fcoe_cqe_type (use enum fcoe_cqe_type)
*/
#define FCOE_CQE_CQE_TYPE_MASK 0xF
#define FCOE_CQE_CQE_TYPE_SHIFT 16
#define FCOE_CQE_RESERVED0_MASK 0xFFF
#define FCOE_CQE_RESERVED0_SHIFT 20
__le16 reserved1;
__le16 fw_cq_prod;
union fcoe_cqe_info cqe_info;
};
/*
* FCoE CQE type
*/
enum fcoe_cqe_type {
/* solicited response on a R/W or middle-path SQE */
FCOE_GOOD_COMPLETION_CQE_TYPE,
FCOE_UNSOLIC_CQE_TYPE /* unsolicited packet, RQ consumed */,
FCOE_ERROR_DETECTION_CQE_TYPE /* timer expiration, validation error */,
FCOE_WARNING_CQE_TYPE /* rec_tov or rr_tov timer expiration */,
FCOE_EXCH_CLEANUP_CQE_TYPE /* task cleanup completed */,
FCOE_ABTS_CQE_TYPE /* ABTS received and task cleaned */,
FCOE_DUMMY_CQE_TYPE /* just increment SQ CONS */,
/* Task was completed wight after sending a pkt to the target */
FCOE_LOCAL_COMP_CQE_TYPE,
MAX_FCOE_CQE_TYPE
};
/*
* FCoE fast path error codes
*/
enum fcoe_fp_error_warning_code {
FCOE_ERROR_CODE_XFER_OOO_RO /* XFER error codes */,
FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED,
FCOE_ERROR_CODE_XFER_NULL_BURST_LEN,
FCOE_ERROR_CODE_XFER_RO_GREATER_THAN_DATA2TRNS,
FCOE_ERROR_CODE_XFER_INVALID_PAYLOAD_SIZE,
FCOE_ERROR_CODE_XFER_TASK_TYPE_NOT_WRITE,
FCOE_ERROR_CODE_XFER_PEND_XFER_SET,
FCOE_ERROR_CODE_XFER_OPENED_SEQ,
FCOE_ERROR_CODE_XFER_FCTL,
FCOE_ERROR_CODE_FCP_RSP_BIDI_FLAGS_SET /* FCP RSP error codes */,
FCOE_ERROR_CODE_FCP_RSP_INVALID_LENGTH_FIELD,
FCOE_ERROR_CODE_FCP_RSP_INVALID_SNS_FIELD,
FCOE_ERROR_CODE_FCP_RSP_INVALID_PAYLOAD_SIZE,
FCOE_ERROR_CODE_FCP_RSP_PEND_XFER_SET,
FCOE_ERROR_CODE_FCP_RSP_OPENED_SEQ,
FCOE_ERROR_CODE_FCP_RSP_FCTL,
FCOE_ERROR_CODE_FCP_RSP_LAST_SEQ_RESET,
FCOE_ERROR_CODE_FCP_RSP_CONF_REQ_NOT_SUPPORTED_YET,
FCOE_ERROR_CODE_DATA_OOO_RO /* FCP DATA error codes */,
FCOE_ERROR_CODE_DATA_EXCEEDS_DEFINED_MAX_FRAME_SIZE,
FCOE_ERROR_CODE_DATA_EXCEEDS_DATA2TRNS,
FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET,
FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET,
FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET,
FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET,
FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ,
FCOE_ERROR_CODE_DATA_FCTL_INITIATIR,
FCOE_ERROR_CODE_MIDPATH_INVALID_TYPE /* Middle path error codes */,
FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET,
FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET,
FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET,
FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET,
FCOE_ERROR_CODE_MIDPATH_REPLY_FCTL,
FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY,
FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL,
FCOE_ERROR_CODE_COMMON_MIDDLE_FRAME_WITH_PAD /* Common error codes */,
FCOE_ERROR_CODE_COMMON_SEQ_INIT_IN_TCE,
FCOE_ERROR_CODE_COMMON_FC_HDR_RX_ID_MISMATCH,
FCOE_ERROR_CODE_COMMON_INCORRECT_SEQ_CNT,
FCOE_ERROR_CODE_COMMON_DATA_FC_HDR_FCP_TYPE_MISMATCH,
FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES,
FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR,
FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG,
FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED,
FCOE_ERROR_CODE_COMMON_TASK_DDF_RCTL_INFO_FIELD,
FCOE_ERROR_CODE_COMMON_TASK_INVALID_RCTL,
FCOE_ERROR_CODE_COMMON_TASK_RCTL_GENERAL_MISMATCH,
FCOE_ERROR_CODE_E_D_TOV_TIMER_EXPIRATION /* Timer error codes */,
FCOE_WARNING_CODE_REC_TOV_TIMER_EXPIRATION /* Timer error codes */,
FCOE_ERROR_CODE_RR_TOV_TIMER_EXPIRATION /* Timer error codes */,
/* ABTSrsp pckt arrived unexpected */
FCOE_ERROR_CODE_ABTS_REPLY_UNEXPECTED,
FCOE_ERROR_CODE_TARGET_MODE_FCP_RSP,
FCOE_ERROR_CODE_TARGET_MODE_FCP_XFER,
FCOE_ERROR_CODE_TARGET_MODE_DATA_TASK_TYPE_NOT_WRITE,
FCOE_ERROR_CODE_DATA_FCTL_TARGET,
FCOE_ERROR_CODE_TARGET_DATA_SIZE_NO_MATCH_XFER,
FCOE_ERROR_CODE_TARGET_DIF_CRC_CHECKSUM_ERROR,
FCOE_ERROR_CODE_TARGET_DIF_REF_TAG_ERROR,
FCOE_ERROR_CODE_TARGET_DIF_APP_TAG_ERROR,
MAX_FCOE_FP_ERROR_WARNING_CODE
};
/*
* FCoE RESPQ element
*/
struct fcoe_respqe {
__le16 ox_id /* OX_ID that is located in the FCP_RSP FC header */;
__le16 rx_id /* RX_ID that is located in the FCP_RSP FC header */;
__le32 additional_info;
/* PARAM that is located in the FCP_RSP FC header */
#define FCOE_RESPQE_PARAM_MASK 0xFFFFFF
#define FCOE_RESPQE_PARAM_SHIFT 0
/* Indication whther its Target-auto-rsp mode or not */
#define FCOE_RESPQE_TARGET_AUTO_RSP_MASK 0xFF
#define FCOE_RESPQE_TARGET_AUTO_RSP_SHIFT 24
};
/*
* FCoE slow path error codes
*/
enum fcoe_sp_error_code {
/* Error codes for Error Reporting in slow path flows */
FCOE_ERROR_CODE_SLOW_PATH_TOO_MANY_FUNCS,
FCOE_ERROR_SLOW_PATH_CODE_NO_LICENSE,
MAX_FCOE_SP_ERROR_CODE
};
/*
* FCoE task TX state
*/
enum fcoe_task_tx_state {
/* Initiate state after driver has initialized the task */
FCOE_TASK_TX_STATE_NORMAL,
/* Updated by TX path after complete transmitting unsolicited packet */
FCOE_TASK_TX_STATE_UNSOLICITED_COMPLETED,
/*
* Updated by TX path after start processing the task requesting the
* cleanup/abort operation
*/
FCOE_TASK_TX_STATE_CLEAN_REQ,
FCOE_TASK_TX_STATE_ABTS /* Updated by TX path during abort procedure */,
/* Updated by TX path during exchange cleanup procedure */
FCOE_TASK_TX_STATE_EXCLEANUP,
/*
* Updated by TX path during exchange cleanup continuation task
* procedure
*/
FCOE_TASK_TX_STATE_EXCLEANUP_TARGET_WRITE_CONT,
/* Updated by TX path during exchange cleanup first xfer procedure */
FCOE_TASK_TX_STATE_EXCLEANUP_TARGET_WRITE,
/* Updated by TX path during exchange cleanup read task in Target */
FCOE_TASK_TX_STATE_EXCLEANUP_TARGET_READ_OR_RSP,
/* Updated by TX path during target exchange cleanup procedure */
FCOE_TASK_TX_STATE_EXCLEANUP_TARGET_WRITE_LAST_CYCLE,
/* Updated by TX path during sequence recovery procedure */
FCOE_TASK_TX_STATE_SEQRECOVERY,
MAX_FCOE_TASK_TX_STATE
};
#endif /* __QEDF_HSI__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic FCoE Offload Driver
* Copyright (c) 2016-2018 Cavium Inc.
*/
#define QEDF_VERSION "8.42.3.0"
#define QEDF_DRIVER_MAJOR_VER 8
#define QEDF_DRIVER_MINOR_VER 42
#define QEDF_DRIVER_REV_VER 3
#define QEDF_DRIVER_ENG_VER 0