[openib-general] [PATCH] ping Add IB ping server agent

Roland Dreier roland at topspin.com
Mon Mar 21 07:57:11 PST 2005


A few comments based on a quick read through of the code.

 > Index: ping_priv.h
 > ===================================================================
 > --- ping_priv.h	(revision 0)
 > +++ ping_priv.h	(revision 0)
 > +#include <linux/pci.h>
 > +
 > +#define SPFX "ib_ping: "
 > +
 > +struct ib_ping_send_wr {
 > +	struct list_head send_list;
 > +	struct ib_ah *ah;
 > +	struct ib_mad_private *mad;
 > +	DECLARE_PCI_UNMAP_ADDR(mapping)
 > +};
 > +
 > +struct ib_ping_port_private {
 > +	struct list_head port_list;
 > +	struct list_head send_posted_list;
 > +	spinlock_t send_list_lock;
 > +	int port_num;
 > +	struct ib_mad_agent *pingd_agent;     /* OpenIB Ping class */
 > +};

Is it worth having a separate include file that is only included in
one place for this small amount of declarations?

 > Index: ping.c
 > --- ping.c	(revision 0)
 > +++ ping.c	(revision 0)

 > +#include "mad_priv.h"

It doesn't seem right for a different module to be including the mad
module's private implementation details.

 > +/*
 > + * Caller must hold ib_ping_port_list_lock
 > + */
 > +static inline struct ib_ping_port_private *
 > +__ib_get_ping_port(struct ib_device *device, int port_num,
 > +		   struct ib_mad_agent *mad_agent)
 > +{
 > +	struct ib_ping_port_private *entry;
 > +
 > +	BUG_ON(!(!!device ^ !!mad_agent));  /* Exactly one MUST be (!NULL) */

Why have this complication of having a single function that can look
up by device or mad_agent?  For lookup by mad_agent it seems you
should just use mad_agent->context directly and not even call a
function to do that.

 > +
 > +	if (device) {
 > +		list_for_each_entry(entry, &ib_ping_port_list, port_list) {
 > +			if (entry->pingd_agent->device == device &&
 > +			    entry->port_num == port_num)
 > +				return entry;
 > +		}
 > +	} else {
 > +		list_for_each_entry(entry, &ib_ping_port_list, port_list) {
 > +			if (entry->pingd_agent == mad_agent)
 > +				return entry;
 > +		}
 > +	}
 > +	return NULL;
 > +}

 > +	/* PCI mapping */
 > +	gather_list.addr = dma_map_single(mad_agent->device->dma_device,

Is this comment useful?  It's pretty obvious what's going on here, and
it's not necessarily PCI mapping (the HCA could be on some other type
of bus).

 > +static void pingd_recv_handler(struct ib_mad_agent *mad_agent,
 > +			       struct ib_mad_recv_wc *mad_recv_wc)
 > +{
 > +	struct ib_ping_port_private	*port_priv;
 > +	struct ib_vendor_mad	*vend;
 > +	struct ib_mad_private *recv = container_of(mad_recv_wc,
 > +					struct ib_mad_private,
 > +					header.recv_wc);
 > +
 > +	/* Find matching MAD agent */
 > +	port_priv = ib_get_ping_port(NULL, 0, mad_agent);

just mad_agent->context as I said above.

 > +	if (!port_priv) {
 > +		kmem_cache_free(ib_mad_cache, recv);

should ib_free_recv_mad() -- there's a defined API, we should use it.

 > +		kmem_cache_free(ib_mad_cache, recv);

ditto.

 > +static void pingd_send_handler(struct ib_mad_agent *mad_agent,
 > +			       struct ib_mad_send_wc *mad_send_wc)
 > +{
 > +	struct ib_ping_port_private	*port_priv;
 > +	struct ib_ping_send_wr		*ping_send_wr;
 > +	unsigned long			flags;
 > +
 > +	/* Find matching MAD agent */
 > +	port_priv = ib_get_ping_port(NULL, 0, mad_agent);

mad_agent->context

 > +	/* Unmap PCI */
 > +	dma_unmap_single(mad_agent->device->dma_device,

Inaccurate and not helpful comment again.

 > +	/* Release allocated memory */
 > +	kmem_cache_free(ib_mad_cache, ping_send_wr->mad);

ib_free_recv_mad()

 > +int ib_ping_port_open(struct ib_device *device, int port_num)
 > +{
 > +	int ret;
 > +	struct ib_ping_port_private *port_priv;
 > +	struct ib_mad_reg_req pingd_reg_req;
 > +	unsigned long flags;
 > +
 > +	/* First, check if port already open */
 > +	port_priv = ib_get_ping_port(device, port_num, NULL);

I think you can trust the core not to call you twice for the same
device, no need to check this.

 > +	/* Obtain server MAD agent for OpenIB Ping class (GSI QP) */
 > +	port_priv->pingd_agent = ib_register_mad_agent(device, port_num,
 > +						       IB_QPT_GSI,
 > +						      &pingd_reg_req, 0,
 > +						      &pingd_send_handler,
 > +						      &pingd_recv_handler,
 > +						       NULL);

use port_priv instead of NULL for the context param.

 > +static void ib_ping_init_device(struct ib_device *device)
 > +{
 > +	int ret, num_ports, cur_port, i, ret2;

Why do you need ret and ret2?

 > +
 > +	if (device->node_type == IB_NODE_SWITCH) {
 > +		num_ports = 1;
 > +		cur_port = 0;
 > +	} else {
 > +		num_ports = device->phys_port_cnt;
 > +		cur_port = 1;
 > +	}
 > +
 > +	for (i = 0; i < num_ports; i++, cur_port++) {
 > +		ret = ib_ping_port_open(device, cur_port);
 > +		if (ret) {
 > +			printk(KERN_ERR SPFX "Couldn't open %s port %d\n",
 > +			       device->name, cur_port);
 > +			goto error_device_open;
 > +		}

why not just

		if (ib_ping_port_open(device, cur_port) {

?  You never use the value of ret for anything.

 > +	}
 > +	goto error_device_query;

Just return here -- this is the success case so don't obfuscate it.

 > +
 > +error_device_open:
 > +	while (i > 0) {
 > +		cur_port--;
 > +		ret2 = ib_ping_port_close(device, cur_port);
 > +		if (ret2) {

why not just

		if (ib_ping_port_close(device, cur_port)
			printk(...

 > +			printk(KERN_ERR PFX "Couldn't close %s port %d "
 > +			       "for ping agent\n",
 > +			       device->name, cur_port);
 > +		}
 > +		i--;
 > +	}
 > +
 > +error_device_query:

don't need this label at all.

 > +	return;
 > +}
 > +
 > +static void ib_ping_remove_device(struct ib_device *device)
 > +{
 > +	int ret = 0, i, num_ports, cur_port, ret2;

Why do you need ret or ret2?

 > +
 > +	if (device->node_type == IB_NODE_SWITCH) {
 > +		num_ports = 1;
 > +		cur_port = 0;
 > +	} else {
 > +		num_ports = device->phys_port_cnt;
 > +		cur_port = 1;
 > +	}
 > +	for (i = 0; i < num_ports; i++, cur_port++) {
 > +		ret2 = ib_ping_port_close(device, cur_port);
 > +		if (ret2) {
 > +			printk(KERN_ERR SPFX "Couldn't close %s port %d "
 > +			       "for ping agent\n",
 > +			       device->name, cur_port);
 > +			if (!ret)
 > +				ret = ret2;
 > +		}

How about just

		if (ib_ping_port_close(device, cur_port)
			printk(...

You don't care about the return value in ret2 and you don't do
anything with the value you put in ret as far as I can see.

 > +	}
 > +}
 > +
 > +static struct ib_client ping_client = {
 > +        .name   = "ping",
 > +        .add = ib_ping_init_device,
 > +        .remove = ib_ping_remove_device
 > +};
 > +
 > +static int __init ib_ping_init_module(void)
 > +{
 > +	spin_lock_init(&ib_ping_port_list_lock);
 > +	INIT_LIST_HEAD(&ib_ping_port_list);

INIT_LIST_HEAD() isn't needed if you declare your list with LIST_HEAD().

 > Index: mad.c
 > ===================================================================
 > --- mad.c	(revision 2023)
 > +++ mad.c	(working copy)
 > @@ -45,6 +45,8 @@
 >  
 >  
 >  kmem_cache_t *ib_mad_cache;
 > +EXPORT_SYMBOL(ib_mad_cache);

I don't think we should be exporting internals like this.

 - R.



More information about the general mailing list