linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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.

  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).