From: Bart Van Assche <bvanassche@acm.org>
To: James Smart <jsmart2021@gmail.com>, linux-scsi@vger.kernel.org
Cc: Ram Vegesna <ram.vegesna@broadcom.com>
Subject: Re: [PATCH 24/32] elx: efct: LIO backend interface routines
Date: Thu, 24 Oct 2019 15:27:47 -0700 [thread overview]
Message-ID: <5eae53c2-daee-f1f3-8586-e92fd61a5544@acm.org> (raw)
In-Reply-To: <20191023215557.12581-25-jsmart2021@gmail.com>
On 10/23/19 2:55 PM, James Smart wrote:
> diff --git a/drivers/scsi/elx/efct/efct_lio.c b/drivers/scsi/elx/efct/efct_lio.c
> new file mode 100644
> index 000000000000..c2661ab3e9c3
> --- /dev/null
> +++ b/drivers/scsi/elx/efct/efct_lio.c
> @@ -0,0 +1,2643 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 Broadcom. All Rights Reserved. The term
> + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
> + */
> +
> +#include "efct_driver.h"
> +
> +#include <scsi/scsi.h>
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_device.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_tcq.h>
> +#include <target/target_core_base.h>
> +#include <target/target_core_fabric.h>
Please do not include SCSI initiator header files in a SCSI target
driver. See also commit ba929992522b ("target: Minimize SCSI header
#include directives").
> +#define FABRIC_NAME "efct"
> +#define FABRIC_NAME_NPIV "efct_npiv"
Some time ago Christoph Hellwig asked not to use the prefix "fabric" but
to use the prefix "target" instead.
> +#define FABRIC_SNPRINTF_LEN 32
"FABRIC_SNPRINTF_LEN" is a bad choice for the name for this constant.
Please change this into a name that refers to what the purpose of this
constant is (wwn string?) instead of how that string is generated.
> +#define FABRIC_SNPRINTF(str, len, pre, wwn) snprintf(str, len, \
> + "%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", pre, \
> + (u8)((wwn >> 56) & 0xff), (u8)((wwn >> 48) & 0xff), \
> + (u8)((wwn >> 40) & 0xff), (u8)((wwn >> 32) & 0xff), \
> + (u8)((wwn >> 24) & 0xff), (u8)((wwn >> 16) & 0xff), \
> + (u8)((wwn >> 8) & 0xff), (u8)((wwn & 0xff)))
Please convert this macro into a function and choose a better name, e.g.
efct_format_wwn().
> +#define ARRAY2WWN(w, a) (w = ((((u64)(a)[0]) << 56) | (((u64)(a)[1]) << 48) | \
> + (((u64)(a)[2]) << 40) | (((u64)(a)[3]) << 32) | \
> + (((u64)(a)[4]) << 24) | (((u64)(a)[5]) << 16) | \
> + (((u64)(a)[6]) << 8) | (((u64)(a)[7]))))
Is this perhaps an open-coded version of get_unaligned_be64()?
> +/* Per-target data for virtual targets */
> +struct efct_lio_vport_data_t {
> + struct list_head list_entry;
> + bool initiator_mode;
> + bool target_mode;
> + u64 phy_wwpn;
> + u64 phy_wwnn;
> + u64 vport_wwpn;
> + u64 vport_wwnn;
> + struct efct_lio_vport *lio_vport;
> +};
> +
> +/* Per-target data for virtual targets */
> +struct efct_lio_vport_list_t {
> + struct list_head list_entry;
> + struct efct_lio_vport *lio_vport;
> +};
Two times the same comment for two different data structures?
Additionally, what is a "virtual target"?
> +/* local prototypes */
> +static char *efct_lio_get_npiv_fabric_wwn(struct se_portal_group *);
> +static char *efct_lio_get_fabric_wwn(struct se_portal_group *);
> +static u16 efct_lio_get_tag(struct se_portal_group *);
> +static u16 efct_lio_get_npiv_tag(struct se_portal_group *);
> +static int efct_lio_check_demo_mode(struct se_portal_group *);
> +static int efct_lio_check_demo_mode_cache(struct se_portal_group *);
> +static int efct_lio_check_demo_write_protect(struct se_portal_group *);
> +static int efct_lio_check_prod_write_protect(struct se_portal_group *);
> +static int efct_lio_npiv_check_demo_write_protect(struct se_portal_group *);
> +static int efct_lio_npiv_check_prod_write_protect(struct se_portal_group *);
> +static u32 efct_lio_tpg_get_inst_index(struct se_portal_group *);
> +static int efct_lio_check_stop_free(struct se_cmd *se_cmd);
> +static void efct_lio_aborted_task(struct se_cmd *se_cmd);
> +static void efct_lio_release_cmd(struct se_cmd *);
> +static void efct_lio_close_session(struct se_session *);
> +static u32 efct_lio_sess_get_index(struct se_session *);
> +static int efct_lio_write_pending(struct se_cmd *);
> +static void efct_lio_set_default_node_attrs(struct se_node_acl *);
> +static int efct_lio_get_cmd_state(struct se_cmd *);
> +static int efct_lio_queue_data_in(struct se_cmd *);
> +static int efct_lio_queue_status(struct se_cmd *);
> +static void efct_lio_queue_tm_rsp(struct se_cmd *);
> +static struct se_wwn *efct_lio_make_sport(struct target_fabric_configfs *,
> + struct config_group *, const char *);
> +static void efct_lio_drop_sport(struct se_wwn *);
> +static void efct_lio_npiv_drop_sport(struct se_wwn *);
> +static int efct_lio_parse_wwn(const char *, u64 *, u8 npiv);
> +static int efct_lio_parse_npiv_wwn(const char *name, size_t size,
> + u64 *wwpn, u64 *wwnn);
> +static struct se_portal_group *efct_lio_make_tpg(struct se_wwn *,
> + const char *);
> +static struct se_portal_group *efct_lio_npiv_make_tpg(struct se_wwn *,
> + const char *);
> +static void efct_lio_drop_tpg(struct se_portal_group *);
> +static struct se_wwn *efct_lio_npiv_make_sport(struct target_fabric_configfs *,
> + struct config_group *,
> + const char *);
> +static int
> +efct_lio_parse_npiv_wwn(const char *name, size_t size, u64 *wwpn, u64 *wwnn);
> +static void efct_lio_npiv_drop_tpg(struct se_portal_group *);
> +static int efct_lio_async_worker(struct efct_s *efct);
> +static void efct_lio_sg_unmap(struct efct_io_s *io);
> +static int efct_lio_abort_tgt_cb(struct efct_io_s *io,
> + enum efct_scsi_io_status_e scsi_status,
> + u32 flags, void *arg);
> +
> +static int efct_lio_init_nodeacl(struct se_node_acl *, const char *);
> +
> +static int efct_lio_check_demo_mode_login_only(struct se_portal_group *);
> +static int efct_lio_npiv_check_demo_mode_login_only(struct se_portal_group *);
Please reorder the code in this file such that most or all of these
function declarations disappear.
> +static ssize_t
> +efct_lio_wwn_version_show(struct config_item *item, char *page)
> +{
> + return sprintf(page, "Emulex EFCT fabric module version %s\n",
> + __stringify(EFCT_LIO_VERSION));
> +}
Version numbers are not useful in upstream code. Please remove this
attribute and also the EFCT_LIO_VERSION constant.
> +static struct efct_lio_tpg *
> +efct_get_vport_tpg(struct efc_node_s *node)
> +{
> + struct efct_s *efct;
> + u64 wwpn = node->sport->wwpn;
> + struct efct_lio_vport_list_t *vport, *next;
> + struct efct_lio_vport *lio_vport = NULL;
> + struct efct_lio_tpg *tpg = NULL;
> + unsigned long flags = 0;
> +
> + efct = node->efc->base;
> + spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);
> + list_for_each_entry_safe(vport, next,
> + &efct->tgt_efct.vport_list, list_entry) {
> + lio_vport = vport->lio_vport;
> + if (wwpn && lio_vport &&
> + lio_vport->npiv_wwpn == wwpn) {
> + efc_log_test(efct, "found tpg on vport\n");
> + tpg = lio_vport->tpg;
> + break;
> + }
> + }
> + spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);
> + return tpg;
> +}
The indentation in this function is wrong. list_for_each_entry() should
occur at the same level as spin_lock_irqsave().
> +/* local static data */
> +/* local static data */
Are these comments useful?
> +#define LIO_IOFMT "[%04x][i:%0*x t:%0*x h:%04x][c:%02x]"
> +#define LIO_TMFIOFMT "[%04x][i:%0*x t:%0*x h:%04x][f:%02x]"
> +#define LIO_IOFMT_ITT_SIZE(efct) 4
> +
> +#define efct_lio_io_printf(io, fmt, ...) \
> + efc_log_debug(io->efct, "[%s]" LIO_IOFMT " " fmt, \
> + io->node->display_name, io->instance_index, \
> + LIO_IOFMT_ITT_SIZE(io->efct), io->init_task_tag, \
> + LIO_IOFMT_ITT_SIZE(io->efct), io->tgt_task_tag, io->hw_tag,\
> + (io->tgt_io.cdb ? io->tgt_io.cdb[0] : 0xFF), ##__VA_ARGS__)
> +#define efct_lio_tmfio_printf(io, fmt, ...) \
> + efc_log_debug(io->efct, "[%s]" LIO_TMFIOFMT " " fmt,\
> + io->node->display_name, io->instance_index, \
> + LIO_IOFMT_ITT_SIZE(io->efct), io->init_task_tag, \
> + LIO_IOFMT_ITT_SIZE(io->efct), io->tgt_task_tag, io->hw_tag,\
> + io->tgt_io.tmf, ##__VA_ARGS__)
Please remove the LIO_IOFMT, LIO_TMFIOFMT and LIO_IOFMT_ITT_SIZE macros
and expand these macros where these are used. I think that will make the
above logging functions much more easy to read.
> +#define efct_lio_io_state_trace(io, value) (io->tgt_io.state |= value)
This macro has "trace" in its name but does not trace anything. Please
either remove this macro or choose a better name.
> +static int efct_lio_tgt_session_data(struct efct_s *efct, u64 wwpn,
> + char *buf, int size)
> +{
> + struct efc_sli_port_s *sport = NULL;
> + struct efc_node_s *node = NULL;
> + struct efc_lport *efc = efct->efcport;
> + u16 loop_id = 0;
> + int off = 0, rc = 0;
> +
> + if (!efc->domain) {
> + efc_log_err(efct, "failed to find efct/domain\n");
> + return -1;
> + }
> +
> + list_for_each_entry(sport, &efc->domain->sport_list, list_entry) {
> + if (sport->wwpn == wwpn) {
> + list_for_each_entry(node, &sport->node_list,
> + list_entry) {
> + /* Dump sessions only remote NPORT
> + * sessions
> + */
> + if (efct_lio_node_is_initiator(node)) {
> + rc = snprintf(buf + off,
> + size - off,
> + "0x%016llx,0x%08x,0x%04x\n",
> + be64_to_cpup((__force __be64 *)
> + node->wwpn),
> + node->rnode.fc_id,
> + loop_id);
> + if (rc < 0)
> + break;
> + off += rc;
> + }
> + }
> + }
> + }
> +
> + buf[size - 1] = '\0';
> + return 0;
> +}
Please use get_unaligned_be64() instead of using __force casts.
> +static const struct file_operations efct_debugfs_session_fops = {
> + .owner = THIS_MODULE,
> + .open = efct_debugfs_session_open,
> + .release = efct_debugfs_session_close,
> + .read = efct_debugfs_session_read,
> + .write = efct_debugfs_session_write,
> + .llseek = default_llseek,
> +};
> +
> +static const struct file_operations efct_npiv_debugfs_session_fops = {
> + .owner = THIS_MODULE,
> + .open = efct_npiv_debugfs_session_open,
> + .release = efct_debugfs_session_close,
> + .read = efct_debugfs_session_read,
> + .write = efct_debugfs_session_write,
> + .llseek = default_llseek,
> +};
Since the information that is exported through debugfs (logged in
initiators) is information that is also useful for other target drivers,
I think this functionality should be implemented in the target core
instead of in this target driver.
> +/* command has been aborted, cleanup here */
> +static void efct_lio_aborted_task(struct se_cmd *se_cmd)
> +{
> + int rc;
> + struct efct_scsi_tgt_io_s *ocp = container_of(se_cmd,
> + struct efct_scsi_tgt_io_s,
> + cmd);
> + struct efct_io_s *io = container_of(ocp, struct efct_io_s, tgt_io);
> +
> + efct_lio_io_trace(io, "%s\n", __func__);
> + efct_lio_io_state_trace(io, EFCT_LIO_STATE_TFO_ABORTED_TASK);
> +
> + if (!(se_cmd->transport_state & CMD_T_ABORTED) || ocp->rsp_sent)
> + return;
> +
> + /*
> + * if io is non-null, take a reference out on it so it isn't
> + * freed until the abort operation is complete.
> + */
> + if (kref_get_unless_zero(&io->ref) == 0) {
> + /* command no longer active */
> + struct efct_s *efct = io->efct;
> +
> + efc_log_test(efct,
> + "success: command no longer active (exists=%d)\n",
> + (io != NULL));
> + return;
> + }
> +
> + efct_lio_io_printf(io, "CMD_T_ABORTED set, aborting=%d\n",
> + ocp->aborting);
> + ocp->aborting = true;
> + /* set to non-success so data moves won't continue */
> + ocp->err = EFCT_SCSI_STATUS_ABORTED;
> +
> + /* wait until abort is complete; once we return, LIO will call
> + * queue_tm_rsp() which will send response to TMF
> + */
> + init_completion(&io->tgt_io.done);
> +
> + rc = efct_scsi_tgt_abort_io(io, efct_lio_abort_tgt_cb, NULL);
> + if (rc == 0) {
> + /* wait for abort to complete before returning */
> + rc = wait_for_completion_timeout(&io->tgt_io.done,
> + usecs_to_jiffies(10000000));
> +
> + /* done with reference on aborted IO */
> + kref_put(&io->ref, io->release);
> +
> + if (rc) {
> + efct_lio_io_printf(io,
> + "abort completed successfully\n");
> + /* check if TASK_ABORTED status should be sent
> + * for this IO
> + */
> + } else {
> + efct_lio_io_printf(io,
> + "timeout waiting for abort completed\n");
> + }
> + } else {
> + efct_lio_io_printf(io, "Failed to abort\n");
> + }
> +}
The .aborted_task() callback function must not wait until the aborted
command has finished but instead must free the resources owned by the
aborted command.
The comment "check if TASK_ABORTED status should be sent for this IO" is
wrong. .aborted_task() is only called if no response will be sent to the
initiator.
> +/**
> + * @brief Housekeeping for LIO SG mapping.
> + *
> + * @param io Pointer to IO context.
> + *
> + * @return count Count returned by pci_map_sg.
> + */
The above comment follows the Doxygen syntax. Kernel function headers
must use the kernel-doc syntax. See also
Documentation/process/kernel-docs.rst.
> +static struct se_wwn *
> +efct_lio_make_sport(struct target_fabric_configfs *tf,
> + struct config_group *group, const char *name)
> +{
> + struct efct_lio_sport *lio_sport;
> + struct efct_s *efct;
> + int efctidx, ret;
> + u64 wwpn;
> + char *sessions_name;
> +
> + ret = efct_lio_parse_wwn(name, &wwpn, 0);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + /* Now search for the HBA that has this WWPN */
> + for (efctidx = 0; efctidx < MAX_EFCT_DEVICES; efctidx++) {
> + u64 pwwn;
> + u8 pn[8];
> +
> + efct = efct_devices[efctidx];
> + if (!efct)
> + continue;
> + memcpy(pn, efct_hw_get_ptr(&efct->hw, EFCT_HW_WWN_PORT),
> + sizeof(pn));
> + ARRAY2WWN(pwwn, pn);
> + if (pwwn == wwpn)
> + break;
> + }
> + if (efctidx == MAX_EFCT_DEVICES) {
> + pr_err("cannot find EFCT for wwpn %s\n", name);
> + return ERR_PTR(-ENXIO);
> + }
> + efct = efct_devices[efctidx];
> + lio_sport = kzalloc(sizeof(*lio_sport), GFP_KERNEL);
> + if (!lio_sport)
> + return ERR_PTR(-ENOMEM);
> + lio_sport->efct = efct;
> + lio_sport->wwpn = wwpn;
> + FABRIC_SNPRINTF(lio_sport->wwpn_str, sizeof(lio_sport->wwpn_str),
> + "naa.", wwpn);
> + efct->tgt_efct.lio_sport = lio_sport;
> +
> + sessions_name = kasprintf(GFP_KERNEL, "efct-sessions-%d",
> + efct->instance_index);
> + if (sessions_name && efct->sess_debugfs_dir)
> + lio_sport->sessions = debugfs_create_file(sessions_name,
> + 0644,
> + efct->sess_debugfs_dir,
> + lio_sport,
> + &efct_debugfs_session_fops);
> + kfree(sessions_name);
> +
> + return &lio_sport->sport_wwn;
> +}
> +
> +static struct se_wwn *
> +efct_lio_npiv_make_sport(struct target_fabric_configfs *tf,
> + struct config_group *group, const char *name)
> +{
> + struct efct_lio_vport *lio_vport;
> + struct efct_s *efct;
> + int efctidx, ret = -1;
> + u64 p_wwpn, npiv_wwpn, npiv_wwnn;
> + char *p, tmp[128];
> + struct efct_lio_vport_list_t *vport_list;
> + char *sessions_name;
> + struct fc_vport *new_fc_vport;
> + struct fc_vport_identifiers vport_id;
> + unsigned long flags = 0;
> +
> + snprintf(tmp, 128, "%s", name);
> +
> + p = strchr(tmp, '@');
> +
> + if (!p) {
> + pr_err("Unable to find separator operator(@)\n");
> + return ERR_PTR(ret);
> + }
> + *p++ = '\0';
> +
> + ret = efct_lio_parse_wwn(tmp, &p_wwpn, 0);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + ret = efct_lio_parse_npiv_wwn(p, strlen(p) + 1, &npiv_wwpn, &npiv_wwnn);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + /* Now search for the HBA that has this WWPN */
> + for (efctidx = 0; efctidx < MAX_EFCT_DEVICES; efctidx++) {
> + u64 pwwn;
> + u8 pn[8];
> +
> + efct = efct_devices[efctidx];
> + if (!efct)
> + continue;
> + if (!efct->xport->req_wwpn) {
> + memcpy(pn, efct_hw_get_ptr(&efct->hw,
> + EFCT_HW_WWN_PORT), sizeof(pn));
> + ARRAY2WWN(pwwn, pn);
> + } else {
> + pwwn = efct->xport->req_wwpn;
> + }
> + if (pwwn == p_wwpn)
> + break;
> + }
> + if (efctidx == MAX_EFCT_DEVICES) {
> + pr_err("cannot find EFCT for base wwpn %s\n", name);
> + return ERR_PTR(-ENXIO);
> + }
> + efct = efct_devices[efctidx];
> + lio_vport = kzalloc(sizeof(*lio_vport), GFP_KERNEL);
> + if (!lio_vport)
> + return ERR_PTR(-ENOMEM);
> +
> + lio_vport->efct = efct;
> + lio_vport->wwpn = p_wwpn;
> + lio_vport->npiv_wwpn = npiv_wwpn;
> + lio_vport->npiv_wwnn = npiv_wwnn;
> +
> + FABRIC_SNPRINTF(lio_vport->wwpn_str, sizeof(lio_vport->wwpn_str),
> + "naa.", npiv_wwpn);
> +
> + vport_list = kmalloc(sizeof(*vport_list), GFP_KERNEL);
> + if (!vport_list) {
> + kfree(lio_vport);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + memset(vport_list, 0, sizeof(struct efct_lio_vport_list_t));
> + vport_list->lio_vport = lio_vport;
> + spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);
> + INIT_LIST_HEAD(&vport_list->list_entry);
> + list_add_tail(&vport_list->list_entry, &efct->tgt_efct.vport_list);
> + spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);
> +
> + sessions_name = kasprintf(GFP_KERNEL, "sessions-npiv-%d",
> + efct->instance_index);
> + if (sessions_name && efct->sess_debugfs_dir)
> + lio_vport->sessions = debugfs_create_file(sessions_name,
> + 0644,
> + efct->sess_debugfs_dir,
> + lio_vport,
> + &efct_npiv_debugfs_session_fops);
> + kfree(sessions_name);
> + memset(&vport_id, 0, sizeof(vport_id));
> + vport_id.port_name = npiv_wwpn;
> + vport_id.node_name = npiv_wwnn;
> + vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR;
> + vport_id.vport_type = FC_PORTTYPE_NPIV;
> + vport_id.disable = false;
> +
> + new_fc_vport = fc_vport_create(efct->shost, 0, &vport_id);
> + if (!new_fc_vport) {
> + efc_log_err(efct, "fc_vport_create failed\n");
> + kfree(lio_vport);
> + kfree(vport_list);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + lio_vport->fc_vport = new_fc_vport;
> +
> + return &lio_vport->vport_wwn;
> +}
Please rework efct_lio_make_sport() and efct_lio_npiv_make_sport() such
that the amount of duplicate code is reduced significantly.
> +
> + /* Create kernel worker thread to service async requests
> + * (new/delete initiator, new cmd/tmf). Previously, a worker thread
> + * was needed to make upcalls into LIO because the HW completion
> + * context ran in an interrupt context (tasklet).
> + * This is no longer necessary now that HW completions run in a
> + * kernel thread context. However, performance is much better when
> + * these types of reqs have their own thread.
> + *
> + * Note: We've seen better performance when IO completion (non-async)
> + * upcalls into LIO are not given an additional kernel thread.
> + * Thus,make such upcalls directly from the HW completion kernel thread
> + */
> +
> + worker = &efct->tgt_efct.async_worker;
> + efct_mqueue_init(efct, &worker->wq);
> +
> + worker->thread = kthread_create((int(*)(void *)) efct_lio_async_worker,
> + efct, "efct_lio_async_worker");
> +
> + if (IS_ERR(worker->thread)) {
> + efc_log_err(efct, "kthread_create failed: %ld\n",
> + PTR_ERR(worker->thread));
> + worker->thread = NULL;
> + return -1;
> + }
> +
> + wake_up_process(worker->thread);
Please use the kernel workqueue infrastructure instead of duplicating it.
> +/**
> + * @brief Worker thread for LIO commands.
> + *
> + * @par Description
> + * This thread is used to make LIO upcalls associated with
> + * asynchronous requests (i.e. new commands received, register
> + * sessions, unregister sessions).
> + *
> + * @param mythread Pointer to the thread object.
> + *
> + * @return Always returns 0.
> + */
> +static int efct_lio_async_worker(struct efct_s *efct)
> +{
> + struct efct_lio_wq_data_s *wq_data;
> + struct efc_node_s *node;
> + struct se_session *se_sess;
> + int done = 0;
> + bool free_data = true;
> + struct efct_scsi_tgt_io_s *ocp;
> + int dir, rc = 0;
> + struct efct_io_s *io;
> + struct efct_io_s *tmfio;
> + struct efct_scsi_tgt_node_s *tgt_node = NULL;
> +
> + while (!done) {
> + /* Poll with a timeout, to keep the kernel from complaining
> + * of not periodically running
> + */
> + wq_data = efct_mqueue_get(&efct->tgt_efct.async_worker.wq,
> + 10000000);
> + if (kthread_should_stop())
> + break;
> +
> + if (!wq_data)
> + continue;
> +
> [ ... ]
> + }
> + if (free_data)
> + kfree(wq_data);
> + }
> +
> + complete(&efct->tgt_efct.async_worker.done);
> +
> + return 0;
> +}
Same comment here: please use the kernel workqueue infrastructure
instead of duplicating it.
> +#define scsi_pack_result(key, code, qualifier) (((key & 0xff) << 16) | \
> + ((code && 0xff) << 8) | (qualifier & 0xff))
Where is this macro used? I haven't found any uses of this macro in this
patch.
> +#define FABRIC_SNPRINTF_LEN 32
Please choose a better name for this constant. Or even better, leave out
this define entirely and use sizeof().
> +static inline int
> +efct_mqueue_init(struct efct_s *efct, struct efct_mqueue_s *q)
> +{
> + memset(q, 0, sizeof(*q));
> + q->efct = efct;
> + spin_lock_init(&q->lock);
> + init_completion(&q->prod);
> + INIT_LIST_HEAD(&q->queue);
> + return 0;
> +}
Functions that are not in the hot path should be defined in a .c file
instead of in a header file.
Thanks,
Bart.
next prev parent reply other threads:[~2019-10-24 22:27 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-23 21:55 [PATCH 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver James Smart
2019-10-23 21:55 ` [PATCH 01/32] elx: libefc_sli: SLI-4 register offsets and field definitions James Smart
2019-10-24 16:22 ` Daniel Wagner
2019-10-25 23:04 ` James Smart
2019-10-23 21:55 ` [PATCH 02/32] elx: libefc_sli: SLI Descriptors and Queue entries James Smart
2019-10-25 9:59 ` Daniel Wagner
2019-10-25 23:00 ` James Smart
2019-10-23 21:55 ` [PATCH 03/32] elx: libefc_sli: Data structures and defines for mbox commands James Smart
2019-10-25 11:19 ` Daniel Wagner
2019-10-25 12:20 ` Steffen Maier
2019-10-25 22:10 ` James Smart
2019-10-25 22:42 ` James Smart
2019-10-23 21:55 ` [PATCH 04/32] elx: libefc_sli: queue create/destroy/parse routines James Smart
2019-10-25 15:35 ` Daniel Wagner
2019-10-25 22:24 ` James Smart
2019-10-23 21:55 ` [PATCH 05/32] elx: libefc_sli: Populate and post different WQEs James Smart
2019-10-23 21:55 ` [PATCH 06/32] elx: libefc_sli: bmbx routines and SLI config commands James Smart
2019-10-23 21:55 ` [PATCH 07/32] elx: libefc_sli: APIs to setup SLI library James Smart
2019-10-23 21:55 ` [PATCH 08/32] elx: libefc: Generic state machine framework James Smart
2019-10-23 21:55 ` [PATCH 09/32] elx: libefc: Emulex FC discovery library APIs and definitions James Smart
2019-10-23 21:55 ` [PATCH 10/32] elx: libefc: FC Domain state machine interfaces James Smart
2019-10-23 21:55 ` [PATCH 11/32] elx: libefc: SLI and FC PORT " James Smart
2019-10-23 21:55 ` [PATCH 12/32] elx: libefc: Remote node " James Smart
2019-10-23 21:55 ` [PATCH 13/32] elx: libefc: Fabric " James Smart
2019-10-23 21:55 ` [PATCH 14/32] elx: libefc: FC node ELS and state handling James Smart
2019-10-23 21:55 ` [PATCH 15/32] elx: efct: Data structures and defines for hw operations James Smart
2019-10-23 21:55 ` [PATCH 16/32] elx: efct: Driver initialization routines James Smart
2019-10-23 21:55 ` [PATCH 17/32] elx: efct: Hardware queues creation and deletion James Smart
2019-10-23 21:55 ` [PATCH 18/32] elx: efct: RQ buffer, memory pool allocation and deallocation APIs James Smart
2019-10-23 21:55 ` [PATCH 19/32] elx: efct: Hardware IO and SGL initialization James Smart
2019-10-23 21:55 ` [PATCH 20/32] elx: efct: Hardware queues processing James Smart
2019-10-23 21:55 ` [PATCH 21/32] elx: efct: Unsolicited FC frame processing routines James Smart
2019-10-23 21:55 ` [PATCH 22/32] elx: efct: Extended link Service IO handling James Smart
2019-10-23 21:55 ` [PATCH 23/32] elx: efct: SCSI IO handling routines James Smart
2019-10-23 21:55 ` [PATCH 24/32] elx: efct: LIO backend interface routines James Smart
2019-10-24 22:27 ` Bart Van Assche [this message]
2019-10-28 17:49 ` James Smart
2019-10-28 18:31 ` Bart Van Assche
2019-10-23 21:55 ` [PATCH 25/32] elx: efct: Hardware IO submission routines James Smart
2019-10-23 21:55 ` [PATCH 26/32] elx: efct: link statistics and SFP data James Smart
2019-10-23 21:55 ` [PATCH 27/32] elx: efct: xport and hardware teardown routines James Smart
2019-10-23 21:55 ` [PATCH 28/32] elx: efct: IO timeout handling routines James Smart
2019-10-23 21:55 ` [PATCH 29/32] elx: efct: Firmware update, async link processing James Smart
2019-10-23 21:55 ` [PATCH 30/32] elx: efct: scsi_transport_fc host interface support James Smart
2019-10-23 21:55 ` [PATCH 31/32] elx: efct: Add Makefile and Kconfig for efct driver James Smart
2019-10-25 15:55 ` Daniel Wagner
2019-10-25 22:47 ` James Smart
2019-10-23 21:55 ` [PATCH 32/32] elx: efct: Tie into kernel Kconfig and build process James Smart
2019-10-26 0:34 ` kbuild test robot
2019-10-26 0:39 ` Randy Dunlap
2019-10-26 14:13 ` kbuild test robot
2019-10-26 14:13 ` [RFC PATCH] elx: efct: efct_libefc_templ can be static kbuild test robot
2019-10-25 15:56 ` [PATCH 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver Daniel Wagner
2019-10-25 22:31 ` James Smart
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5eae53c2-daee-f1f3-8586-e92fd61a5544@acm.org \
--to=bvanassche@acm.org \
--cc=jsmart2021@gmail.com \
--cc=linux-scsi@vger.kernel.org \
--cc=ram.vegesna@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).