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 */
next 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 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).