All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Smart <James.Smart@Emulex.Com>
To: linux-scsi@vger.kernel.org
Subject: [RFC] FC Transport : Async Events via netlink interface
Date: Mon, 17 Apr 2006 16:44:21 -0400	[thread overview]
Message-ID: <1145306661.4151.0.camel@localhost.localdomain> (raw)

[netdev folks copied to review the use of the netlink interface]

This patch adds HBAAPI async event support to the FC transport.

Events are pushed to userspace via Netlink. This is per the previous
RFC comments given in :
  http://marc.theaimsgroup.com/?l=linux-scsi&m=114062896729418&w=2

This patch contains the following changes:
  - Add Netlink support to the FC transport
  - Creates a new file "include/scsi/scsi_netlink_fc.h", which
    contains the user-space visible portion of the FC transport
    netlink messaging
  - Allow user apps to register to receive async events
  - Add the fc_host_event_post() interface to post async events
  - A couple of misc fixes:
     - From the prior event post: small dev_loss_tmo mods, with the
       main fix to validate the module parameter on load.
     - Fix fc_user_scan() so it safely walks the rport list

Using netlink worked out very well, and solves the multiple receiver issue.
Also looks very extensible for additional HBAAPI function support.

-- james s

PS: Comments on Kconfig change appreciated. I don't have much experience on
  changing the kernel config and build process.



Signed-off-by: James Smart <James.Smart@emulex.com>


diff -upNr a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2006-03-29 11:53:24.000000000 -0500
+++ b/drivers/scsi/Kconfig	2006-04-17 12:03:31.000000000 -0400
@@ -221,7 +221,7 @@ config SCSI_SPI_ATTRS
 
 config SCSI_FC_ATTRS
 	tristate "FiberChannel Transport Attributes"
-	depends on SCSI
+	depends on SCSI && NET && NETFILTER && NETFILTER_NETLINK
 	help
 	  If you wish to export transport-specific information about
 	  each attached FiberChannel device to sysfs, say Y.
diff -upNr a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
--- a/drivers/scsi/scsi_transport_fc.c	2006-04-10 09:02:15.000000000 -0400
+++ b/drivers/scsi/scsi_transport_fc.c	2006-04-17 11:24:53.000000000 -0400
@@ -33,9 +33,17 @@
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_cmnd.h>
 #include "scsi_priv.h"
+#include <linux/time.h>
+#include <linux/jiffies.h>
+#include <linux/security.h>
+#include <net/sock.h>
+#include <net/netlink.h>
 
 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
 
+#define get_list_head_entry(pos, head, member) 		\
+	pos = list_entry((head)->next, typeof(*pos), member)
+
 /*
  * Redefine so that we can have same named attributes in the
  * sdev/starget/host objects.
@@ -132,6 +140,29 @@ fc_enum_name_match(tgtid_bind_type, fc_t
 #define FC_BINDTYPE_MAX_NAMELEN	30
 

+/* Convert fc_host_event_code values to ascii string name */
+static const struct {
+	enum fc_host_event_code		value;
+	char				*name;
+} fc_host_event_code_names[] = {
+	{ FCH_EVT_LIP,			"lip" },
+	{ FCH_EVT_LINKUP,		"link_up" },
+	{ FCH_EVT_LINKDOWN,		"link_down" },
+	{ FCH_EVT_LIPRESET,		"lip_reset" },
+	{ FCH_EVT_RSCN,			"rscn" },
+	{ FCH_EVT_ADAPTER_CHANGE,	"adapter_chg" },
+	{ FCH_EVT_PORT_UNKNOWN,		"port_unknown" },
+	{ FCH_EVT_PORT_ONLINE,		"port_online" },
+	{ FCH_EVT_PORT_OFFLINE,		"port_offline" },
+	{ FCH_EVT_PORT_FABRIC,		"port_fabric" },
+	{ FCH_EVT_LINK_UNKNOWN,		"link_unknown" },
+	{ FCH_EVT_VENDOR_UNIQUE,	"vendor_unique" },
+};
+fc_enum_name_search(host_event_code, fc_host_event_code,
+		fc_host_event_code_names)
+#define FC_HOST_EVENT_CODE_MAX_NAMELEN	30
+
+
 #define fc_bitfield_name_search(title, table)			\
 static ssize_t							\
 get_fc_##title##_names(u32 table_key, char *buf)		\
@@ -368,9 +399,9 @@ static DECLARE_TRANSPORT_CLASS(fc_rport_
  *   should insulate the loss of a remote port.
  *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
  */
-static unsigned int fc_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT;
+static unsigned int fc_modp_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT;
 
-module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
+module_param_named(dev_loss_tmo, fc_modp_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dev_loss_tmo,
 		 "Maximum number of seconds that the FC transport should"
 		 " insulate the loss of a remote port. Once this value is"
@@ -378,19 +409,366 @@ MODULE_PARM_DESC(dev_loss_tmo,
 		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT.");
 

+/**
+ * Netlink Infrastructure
+ **/
+
+#include <scsi/scsi_netlink_fc.h>
+
+struct fc_nl_user {
+	struct list_head ulist;
+	int pid;
+	u32 flags;
+};
+
+/* fc_nl_user flags values */
+#define FC_NL_UF_EVENTS		0x01
+
+static struct sock *fc_nl_sock;
+static DEFINE_SPINLOCK(fc_nl_lock);
+static u32 fc_event_seq;
+static struct list_head fc_nl_user_list;
+
+#define FC_NL_GROUP_CNT		0
+
+static inline struct fc_nl_user *
+fc_find_user(int pid)
+{
+	struct fc_nl_user *nluser;
+
+	list_for_each_entry(nluser, &fc_nl_user_list, ulist)
+		if (nluser->pid == pid)
+			return nluser;
+	return NULL;
+}
+
+static struct fc_nl_user *
+fc_add_user(int pid, int uflag)
+{
+	struct fc_nl_user *nluser, *newuser;
+	unsigned long flags;
+
+	/* pre-guess we need to add a user struct */
+	newuser = kzalloc(sizeof(struct fc_nl_user), GFP_KERNEL);
+
+	spin_lock_irqsave(&fc_nl_lock, flags);
+
+	nluser = fc_find_user(pid);
+	if (!nluser) {
+		if (newuser) {
+			newuser->pid = pid;
+			newuser->flags = uflag;
+			list_add_tail(&newuser->ulist, &fc_nl_user_list);
+		} 
+	} else
+		nluser->flags |= uflag;
+
+	spin_unlock_irqrestore(&fc_nl_lock, flags);
+
+	if (nluser) {
+		kfree(newuser);
+		return nluser;
+	}
+
+	return newuser;
+}
+
+static void
+fc_del_user(int pid, int uflag)
+{
+	struct fc_nl_user *nluser;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fc_nl_lock, flags);
+
+	nluser = fc_find_user(pid);
+	if (nluser) {
+		nluser->flags &= ~uflag;
+		if (!nluser->flags)
+			list_del(&nluser->ulist);
+	}
+
+	spin_unlock_irqrestore(&fc_nl_lock, flags);
+
+	if (nluser && !nluser->flags)
+		kfree(nluser);
+}
+
+static int
+fc_handle_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int rcvlen)
+{
+	struct fc_nl_hdr *fch = NLMSG_DATA(nlh);
+	struct fc_nl_user *nluser;
+	int err = 0, pid;
+
+	pid = nlh->nlmsg_pid;
+
+	switch (fch->msgtype) {
+	case FC_NL_EVENTS_REG:
+		nluser = fc_add_user(pid, FC_NL_UF_EVENTS);
+		if (!nluser) {
+			printk(KERN_WARNING "%s: EVT REG failed\n",
+				__FUNCTION__);
+			err = -ENOMEM;
+		}
+		break;
+
+	case FC_NL_EVENTS_DEREG:
+		fc_del_user(pid, FC_NL_UF_EVENTS);
+		break;
+
+	default:
+		printk(KERN_WARNING "%s: unknown msg type 0x%x len %d\n",
+			 __FUNCTION__, fch->msgtype, rcvlen);
+		err = -EBADR;
+		break;
+	}
+
+	return err;
+}
+
+static void
+fc_nl_rcv_msg(struct sk_buff *skb)
+{
+	struct nlmsghdr *nlh;
+	struct fc_nl_hdr *fch;
+	uint32_t rlen;
+	int err;
+
+	while (skb->len >= NLMSG_SPACE(0)) {
+		err = 0;
+
+		nlh = (struct nlmsghdr *) skb->data;
+		if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*fch))) ||
+		    (skb->len < nlh->nlmsg_len)) {
+			printk(KERN_WARNING "%s: discarding partial skb\n",
+				 __FUNCTION__);
+			return;
+		}
+
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > skb->len)
+			rlen = skb->len;
+
+		if (nlh->nlmsg_type != FC_TRANSPORT_MSG) {
+			err = -EBADMSG;
+			goto next_msg;
+		}
+
+		fch = NLMSG_DATA(nlh);
+		if (fch->version != FC_NETLINK_API_VERSION) {
+			err = -EPROTOTYPE;
+			goto next_msg;
+		}
+
+		if (security_netlink_recv(skb)) {
+			err = -EPERM;
+			goto next_msg;
+		}
+
+		err = fc_handle_nl_rcv_msg(skb, nlh, rlen);
+
+next_msg:
+		if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
+			netlink_ack(skb, nlh, err);
+
+		skb_pull(skb, rlen);
+	}
+}
+
+static void
+fc_nl_rcv(struct sock *sk, int len)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
+		fc_nl_rcv_msg(skb);
+		kfree_skb(skb);
+	}
+}
+
+static int
+fc_nl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct netlink_notify *n = ptr;
+
+	if ((event == NETLINK_URELEASE) &&
+	    (n->protocol == NETLINK_FCTRANSPORT) && (n->pid))
+		fc_del_user(n->pid, 0xFFFFFFFF);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block fc_netlink_notifier = {
+	.notifier_call  = fc_nl_rcv_nl_event,
+};
+
+
+static void
+fc_send_event(struct fc_nl_user *nluser, struct fc_nl_event *event)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr	*nlh;
+	struct fc_nl_event *evt;
+	const char *name, *fn;
+	u32 len = NLMSG_SPACE(sizeof(*event));
+	int err;
+
+	skb = alloc_skb(len, GFP_KERNEL);
+	if (!skb) {
+		err = -ENOBUFS;
+		fn = "alloc_skb";
+		goto send_fail;
+	}
+
+	nlh = nlmsg_put(skb, nluser->pid, 0, FC_TRANSPORT_MSG,
+			len - sizeof(*nlh), 0);
+	if (!nlh) {
+		err = -ENOBUFS;
+		fn = "nlmsg_put";
+		goto send_fail;
+	}
+	evt = NLMSG_DATA(nlh);
+	memcpy(evt, event, sizeof(*event));
+
+	err = nlmsg_unicast(fc_nl_sock, skb, nluser->pid);
+	if (err < 0) {
+		fn = "nlmsg_unicast";
+		goto send_fail;
+	}
+
+	return;
+
+send_fail:
+	name = get_fc_host_event_code_name(event->event_code);
+	printk(KERN_WARNING
+		"%s: Dropped Event to PID %d : %s data 0x%08x : %s : err %d\n",
+		__FUNCTION__, nluser->pid, (name) ? name : "<unknown>",
+		event->event_data, fn, err);
+	return;
+}
+
+/**
+ * fc_host_event_post - called to post an even on an fc_host.
+ *
+ * @shost:	host the event occurred on
+ * @event:	event being posted
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
+ *
+ *      We always reserve one element in the event list so that the
+ *      ring logic is easier (e.g. empty is get=put, full is put+1=get)
+ **/
+void
+fc_host_event_post(struct Scsi_Host *shost,
+		enum fc_host_event_code event_code, u32 event_data)
+{
+	struct fc_nl_user *nluser, *next_nluser;
+	struct fc_nl_event *event;
+	struct timeval tv;
+	unsigned long flags;
+	u32 seq;
+
+	if (!fc_nl_sock || list_empty(&fc_nl_user_list))
+		return;
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (!event) {
+		const char *name = get_fc_host_event_code_name(event_code);
+		printk(KERN_WARNING
+			"%s: Dropped Event : %s data 0x%08x - ENOMEM\n",
+			__FUNCTION__, (name) ? name : "<unknown>", event_data);
+		return;
+	}
+
+	spin_lock_irqsave(&fc_nl_lock, flags);
+	seq = fc_event_seq++;
+	spin_unlock_irqrestore(&fc_nl_lock, flags);
+	do_gettimeofday(&tv);
+
+	event->fcnlh.msgtype = FC_NL_ASYNC_EVENT;
+	event->fcnlh.version = FC_NETLINK_API_VERSION;
+	event->fcnlh.reserved1 = 0;
+	event->fcnlh.reserved2 = 0;
+	event->seq_num = seq;
+	event->host_no = shost->host_no;
+	event->event_code = event_code;
+	event->event_data = event_data;
+	event->tv_sec = tv.tv_sec;
+	event->tv_usec = tv.tv_usec;
+
+	list_for_each_entry_safe(nluser, next_nluser, &fc_nl_user_list, ulist) {
+		if (nluser->flags & FC_NL_UF_EVENTS)
+			fc_send_event(nluser, event);
+	}
+	
+	kfree(event);
+}
+EXPORT_SYMBOL(fc_host_event_post);
+
+
 static __init int fc_transport_init(void)
 {
-	int error = transport_class_register(&fc_host_class);
+	int error;
+
+	/* fix any module parameters */
+
+	if ((fc_modp_dev_loss_tmo < 1) ||
+	    (fc_modp_dev_loss_tmo > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)) {
+		printk(KERN_WARNING
+			"%s: dev_loss_tmo out of range, setting to max (%d)\n",
+			__FUNCTION__, SCSI_DEVICE_BLOCK_MAX_TIMEOUT);
+		fc_modp_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT;
+	}
+
+	INIT_LIST_HEAD(&fc_nl_user_list);
+
+	/* register the transport classes */
+
+	error = transport_class_register(&fc_host_class);
 	if (error)
 		return error;
 	error = transport_class_register(&fc_rport_class);
 	if (error)
-		return error;
-	return transport_class_register(&fc_transport_class);
+		goto rport_class_out;
+	error = transport_class_register(&fc_transport_class);
+	if (error)
+		goto transport_class_out;
+
+	error = netlink_register_notifier(&fc_netlink_notifier);
+	if (error)
+		goto register_out;
+
+	fc_nl_sock = netlink_kernel_create(NETLINK_FCTRANSPORT, FC_NL_GROUP_CNT,
+					fc_nl_rcv, THIS_MODULE);
+	if (!fc_nl_sock) {
+		error = -ENOBUFS;
+	} else
+		return error;		/* successful return */
+
+	netlink_unregister_notifier(&fc_netlink_notifier);
+register_out:
+	transport_class_unregister(&fc_transport_class);
+transport_class_out:
+	transport_class_unregister(&fc_rport_class);
+rport_class_out:
+	transport_class_unregister(&fc_host_class);
+
+	return error;
 }
 
 static void __exit fc_transport_exit(void)
 {
+	struct fc_nl_user *nluser;
+
+	sock_release(fc_nl_sock->sk_socket);
+	netlink_unregister_notifier(&fc_netlink_notifier);
+	while (!list_empty(&fc_nl_user_list)) {
+		get_list_head_entry(nluser, &fc_nl_user_list, ulist);
+		list_del(&nluser->ulist);
+		kfree(nluser);
+	}
 	transport_class_unregister(&fc_transport_class);
 	transport_class_unregister(&fc_rport_class);
 	transport_class_unregister(&fc_host_class);
@@ -874,9 +1252,6 @@ show_fc_private_host_tgtid_bind_type(str
 	return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name);
 }
 
-#define get_list_head_entry(pos, head, member) 		\
-	pos = list_entry((head)->next, typeof(*pos), member)
-
 static ssize_t
 store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
 	const char *buf, size_t count)
@@ -1142,14 +1517,24 @@ fc_timed_out(struct scsi_cmnd *scmd)
 }
 
 /*
- * Must be called with shost->host_lock held
+ * fc_user_scan - Sysfs interface to scan
+ *
+ * @shost:	The scsi host scan to occur on
+ * @channel:	Channel # to scan
+ * @id:		Target ID # to scan
+ * @lun:	Lun # to scan
+ *
+ * Notes:
+ *	This routine assumes no locks are held on entry.
  */
-static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+static int
+fc_user_scan(struct Scsi_Host *shost, uint channel,
 		uint id, uint lun)
 {
-	struct fc_rport *rport;
+	struct fc_rport *rport, *next_rport;
 
-	list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+	list_for_each_entry_safe(rport, next_rport,
+			&fc_host_rports(shost), peers) {
 		if (rport->scsi_target_id == -1)
 			continue;
 
@@ -1278,6 +1663,7 @@ void fc_release_transport(struct scsi_tr
 }
 EXPORT_SYMBOL(fc_release_transport);
 
+
 /**
  * fc_queue_work - Queue work to the fc_host workqueue.
  * @shost:	Pointer to Scsi_Host bound to fc_host.
@@ -1514,7 +1900,7 @@ fc_rport_create(struct Scsi_Host *shost,
 
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
-	rport->dev_loss_tmo = fc_dev_loss_tmo;
+	rport->dev_loss_tmo = fc_modp_dev_loss_tmo;
 	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
 	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
 	rport->port_id = ids->port_id;
diff -upNr a/include/linux/netlink.h b/include/linux/netlink.h
--- a/include/linux/netlink.h	2006-04-12 12:52:37.000000000 -0400
+++ b/include/linux/netlink.h	2006-04-12 12:53:01.000000000 -0400
@@ -21,6 +21,8 @@
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
 #define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
 #define NETLINK_GENERIC		16
+/* leave room for NETLINK_DM (DM Events) and NETLINK_TGT (SCSI Target) */
+#define NETLINK_FCTRANSPORT	19	/* SCSI FC Transport */
 
 #define MAX_LINKS 32		
 
diff -upNr a/include/scsi/scsi_netlink_fc.h b/include/scsi/scsi_netlink_fc.h
--- a/include/scsi/scsi_netlink_fc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/scsi/scsi_netlink_fc.h	2006-04-17 09:51:08.000000000 -0400
@@ -0,0 +1,57 @@
+/* 
+ *  FiberChannel transport Netlink Interface
+ *
+ *  Copyright (C) 2006   James Smart, Emulex Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef SCSI_NETLINK_FC_H
+#define SCSI_NETLINK_FC_H
+
+#define FC_NETLINK_API_VERSION		1
+
+/* Single Netlink Message type to send all FC Transport messages */
+#define FC_TRANSPORT_MSG		NLMSG_MIN_TYPE + 1
+
+/* FC transport header - found at the front of all FC_TRANSPORT_MSG messages */
+struct fc_nl_hdr {
+	uint16_t msgtype;
+	uint16_t version;
+	uint16_t reserved1;
+	uint16_t reserved2;
+} __attribute__((aligned(sizeof(uint64_t))));
+
+/* FC Transport Message Types */
+	/* user -> kernel */
+#define FC_NL_EVENTS_REG		0x0001
+#define FC_NL_EVENTS_DEREG		0x0002
+	/* kernel -> user */
+#define FC_NL_ASYNC_EVENT		0x0100
+
+/* Asynchronous Event Message */
+struct fc_nl_event {
+	struct fc_nl_hdr fcnlh;
+	uint32_t seq_num;
+	uint32_t host_no;
+	uint32_t event_code;
+	uint32_t event_data;
+	uint64_t tv_sec;
+	uint64_t tv_usec;
+} __attribute__((aligned(sizeof(uint64_t))));
+
+
+#endif /* SCSI_NETLINK_FC_H */
+
diff -upNr a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
--- a/include/scsi/scsi_transport_fc.h	2006-04-10 08:46:47.000000000 -0400
+++ b/include/scsi/scsi_transport_fc.h	2006-04-17 11:42:20.000000000 -0400
@@ -285,6 +285,30 @@ struct fc_host_statistics {
 

 /*
+ * FC Event Codes - Polled and Async, following FC HBAAPI v2.0 guidelines
+ */
+
+/*
+ * fc_host_event_code: If you alter this, you also need to alter
+ * scsi_transport_fc.c (for the ascii descriptions).
+ */
+enum fc_host_event_code  {
+	FCH_EVT_LIP			= 0x1,
+	FCH_EVT_LINKUP			= 0x2,
+	FCH_EVT_LINKDOWN		= 0x3,
+	FCH_EVT_LIPRESET		= 0x4,
+	FCH_EVT_RSCN			= 0x5,
+	FCH_EVT_ADAPTER_CHANGE		= 0x103,
+	FCH_EVT_PORT_UNKNOWN		= 0x200,
+	FCH_EVT_PORT_OFFLINE		= 0x201,
+	FCH_EVT_PORT_ONLINE		= 0x202,
+	FCH_EVT_PORT_FABRIC		= 0x204,
+	FCH_EVT_LINK_UNKNOWN		= 0x500,
+	FCH_EVT_VENDOR_UNIQUE		= 0xffff,
+};
+
+
+/*
  * FC Local Port (Host) Attributes
  *
  * Attributes are based on HBAAPI V2.0 definitions.
@@ -493,6 +517,15 @@ fc_remote_port_chkready(struct fc_rport 
 }
 

+static inline u64 wwn_to_u64(u8 *wwn)
+{
+	return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 |
+	    (u64)wwn[2] << 40 | (u64)wwn[3] << 32 |
+	    (u64)wwn[4] << 24 | (u64)wwn[5] << 16 |
+	    (u64)wwn[6] <<  8 | (u64)wwn[7];
+}
+
+
 struct scsi_transport_template *fc_attach_transport(
 			struct fc_function_template *);
 void fc_release_transport(struct scsi_transport_template *);
@@ -502,13 +535,8 @@ struct fc_rport *fc_remote_port_add(stru
 void fc_remote_port_delete(struct fc_rport  *rport);
 void fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles);
 int scsi_is_fc_rport(const struct device *);
+void fc_host_event_post(struct Scsi_Host *shost,
+		enum fc_host_event_code event_code, u32 event_data);
 
-static inline u64 wwn_to_u64(u8 *wwn)
-{
-	return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 |
-	    (u64)wwn[2] << 40 | (u64)wwn[3] << 32 |
-	    (u64)wwn[4] << 24 | (u64)wwn[5] << 16 |
-	    (u64)wwn[6] <<  8 | (u64)wwn[7];
-}
 
 #endif /* SCSI_TRANSPORT_FC_H */




             reply	other threads:[~2006-04-17 20:44 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-17 20:44 James Smart [this message]
2006-04-18 16:01 ` [RFC] FC Transport : Async Events via netlink interface Mike Anderson
2006-04-19 12:52   ` James Smart
2006-04-19 12:57   ` [RFC] Netlink and user-space buffer pointers James Smart
2006-04-19 16:22     ` Patrick McHardy
2006-04-19 17:08       ` James Smart
2006-04-19 17:16         ` Patrick McHardy
2006-04-19 16:26     ` Stephen Hemminger
2006-04-19 17:05       ` James Smart
2006-04-19 21:32     ` Mike Christie
2006-04-20 14:33       ` James Smart
2006-04-20 17:45         ` Mike Christie
2006-04-20 17:52           ` Mike Christie
2006-04-20 17:58           ` Mike Christie
2006-04-20 20:03           ` James Smart
2006-04-20 20:35             ` Mike Christie
2006-04-20 20:40               ` Mike Christie
2006-04-20 21:41               ` Mike Christie
2006-04-20 21:51             ` Mike Christie
2006-04-20 23:07               ` Mike Christie
2006-04-20 23:44             ` Andrew Vasquez
2006-04-20 20:18           ` Douglas Gilbert
2006-04-19 14:59 ` [RFC] FC Transport : Async Events via netlink interface Matthew Wilcox
2006-04-19 16:11   ` James Smart
  -- strict thread matches above, loose matches on Subject: below --
2006-04-17 22:46 Moore, Eric

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=1145306661.4151.0.camel@localhost.localdomain \
    --to=james.smart@emulex.com \
    --cc=linux-scsi@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.