aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/Kconfig6
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/scsi.c3
-rw-r--r--drivers/scsi/scsi_netlink.c199
-rw-r--r--drivers/scsi/scsi_priv.h11
-rw-r--r--drivers/scsi/scsi_transport_fc.c200
-rw-r--r--include/linux/netlink.h2
-rw-r--r--include/scsi/scsi_netlink.h86
-rw-r--r--include/scsi/scsi_netlink_fc.h71
-rw-r--r--include/scsi/scsi_transport_fc.h34
10 files changed, 612 insertions, 1 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index c8c606589ea6..4d1998d23f0f 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -27,6 +27,11 @@ config SCSI
27 However, do not compile this as a module if your root file system 27 However, do not compile this as a module if your root file system
28 (the one containing the directory /) is located on a SCSI device. 28 (the one containing the directory /) is located on a SCSI device.
29 29
30config SCSI_NETLINK
31 tristate
32 default n
33 select NET
34
30config SCSI_PROC_FS 35config SCSI_PROC_FS
31 bool "legacy /proc/scsi/ support" 36 bool "legacy /proc/scsi/ support"
32 depends on SCSI && PROC_FS 37 depends on SCSI && PROC_FS
@@ -222,6 +227,7 @@ config SCSI_SPI_ATTRS
222config SCSI_FC_ATTRS 227config SCSI_FC_ATTRS
223 tristate "FiberChannel Transport Attributes" 228 tristate "FiberChannel Transport Attributes"
224 depends on SCSI 229 depends on SCSI
230 select SCSI_NETLINK
225 help 231 help
226 If you wish to export transport-specific information about 232 If you wish to export transport-specific information about
227 each attached FiberChannel device to sysfs, say Y. 233 each attached FiberChannel device to sysfs, say Y.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index fd9aeb1ba07f..8fc2c594b537 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -159,6 +159,7 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
159 scsicam.o scsi_error.o scsi_lib.o \ 159 scsicam.o scsi_error.o scsi_lib.o \
160 scsi_scan.o scsi_sysfs.o \ 160 scsi_scan.o scsi_sysfs.o \
161 scsi_devinfo.o 161 scsi_devinfo.o
162scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
162scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o 163scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
163scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o 164scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
164 165
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 37843927e47f..eedfd059b82b 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1118,6 +1118,8 @@ static int __init init_scsi(void)
1118 for_each_possible_cpu(i) 1118 for_each_possible_cpu(i)
1119 INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); 1119 INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
1120 1120
1121 scsi_netlink_init();
1122
1121 printk(KERN_NOTICE "SCSI subsystem initialized\n"); 1123 printk(KERN_NOTICE "SCSI subsystem initialized\n");
1122 return 0; 1124 return 0;
1123 1125
@@ -1138,6 +1140,7 @@ cleanup_queue:
1138 1140
1139static void __exit exit_scsi(void) 1141static void __exit exit_scsi(void)
1140{ 1142{
1143 scsi_netlink_exit();
1141 scsi_sysfs_unregister(); 1144 scsi_sysfs_unregister();
1142 scsi_exit_sysctl(); 1145 scsi_exit_sysctl();
1143 scsi_exit_hosts(); 1146 scsi_exit_hosts();
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
new file mode 100644
index 000000000000..1b59b27e887f
--- /dev/null
+++ b/drivers/scsi/scsi_netlink.c
@@ -0,0 +1,199 @@
1/*
2 * scsi_netlink.c - SCSI Transport Netlink Interface
3 *
4 * Copyright (C) 2006 James Smart, Emulex Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#include <linux/time.h>
22#include <linux/jiffies.h>
23#include <linux/security.h>
24#include <net/sock.h>
25#include <net/netlink.h>
26
27#include <scsi/scsi_netlink.h>
28#include "scsi_priv.h"
29
30struct sock *scsi_nl_sock = NULL;
31EXPORT_SYMBOL_GPL(scsi_nl_sock);
32
33
34/**
35 * scsi_nl_rcv_msg -
36 * Receive message handler. Extracts message from a receive buffer.
37 * Validates message header and calls appropriate transport message handler
38 *
39 * @skb: socket receive buffer
40 *
41 **/
42static void
43scsi_nl_rcv_msg(struct sk_buff *skb)
44{
45 struct nlmsghdr *nlh;
46 struct scsi_nl_hdr *hdr;
47 uint32_t rlen;
48 int err;
49
50 while (skb->len >= NLMSG_SPACE(0)) {
51 err = 0;
52
53 nlh = (struct nlmsghdr *) skb->data;
54 if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
55 (skb->len < nlh->nlmsg_len)) {
56 printk(KERN_WARNING "%s: discarding partial skb\n",
57 __FUNCTION__);
58 return;
59 }
60
61 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
62 if (rlen > skb->len)
63 rlen = skb->len;
64
65 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
66 err = -EBADMSG;
67 goto next_msg;
68 }
69
70 hdr = NLMSG_DATA(nlh);
71 if ((hdr->version != SCSI_NL_VERSION) ||
72 (hdr->magic != SCSI_NL_MAGIC)) {
73 err = -EPROTOTYPE;
74 goto next_msg;
75 }
76
77 if (security_netlink_recv(skb, CAP_SYS_ADMIN)) {
78 err = -EPERM;
79 goto next_msg;
80 }
81
82 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
83 printk(KERN_WARNING "%s: discarding partial message\n",
84 __FUNCTION__);
85 return;
86 }
87
88 /*
89 * We currently don't support anyone sending us a message
90 */
91
92next_msg:
93 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
94 netlink_ack(skb, nlh, err);
95
96 skb_pull(skb, rlen);
97 }
98}
99
100
101/**
102 * scsi_nl_rcv_msg -
103 * Receive handler for a socket. Extracts a received message buffer from
104 * the socket, and starts message processing.
105 *
106 * @sk: socket
107 * @len: unused
108 *
109 **/
110static void
111scsi_nl_rcv(struct sock *sk, int len)
112{
113 struct sk_buff *skb;
114
115 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
116 scsi_nl_rcv_msg(skb);
117 kfree_skb(skb);
118 }
119}
120
121
122/**
123 * scsi_nl_rcv_event -
124 * Event handler for a netlink socket.
125 *
126 * @this: event notifier block
127 * @event: event type
128 * @ptr: event payload
129 *
130 **/
131static int
132scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
133{
134 struct netlink_notify *n = ptr;
135
136 if (n->protocol != NETLINK_SCSITRANSPORT)
137 return NOTIFY_DONE;
138
139 /*
140 * Currently, we are not tracking PID's, etc. There is nothing
141 * to handle.
142 */
143
144 return NOTIFY_DONE;
145}
146
147static struct notifier_block scsi_netlink_notifier = {
148 .notifier_call = scsi_nl_rcv_event,
149};
150
151
152/**
153 * scsi_netlink_init -
154 * Called by SCSI subsystem to intialize the SCSI transport netlink
155 * interface
156 *
157 **/
158void
159scsi_netlink_init(void)
160{
161 int error;
162
163 error = netlink_register_notifier(&scsi_netlink_notifier);
164 if (error) {
165 printk(KERN_ERR "%s: register of event handler failed - %d\n",
166 __FUNCTION__, error);
167 return;
168 }
169
170 scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT,
171 SCSI_NL_GRP_CNT, scsi_nl_rcv, THIS_MODULE);
172 if (!scsi_nl_sock) {
173 printk(KERN_ERR "%s: register of recieve handler failed\n",
174 __FUNCTION__);
175 netlink_unregister_notifier(&scsi_netlink_notifier);
176 }
177
178 return;
179}
180
181
182/**
183 * scsi_netlink_exit -
184 * Called by SCSI subsystem to disable the SCSI transport netlink
185 * interface
186 *
187 **/
188void
189scsi_netlink_exit(void)
190{
191 if (scsi_nl_sock) {
192 sock_release(scsi_nl_sock->sk_socket);
193 netlink_unregister_notifier(&scsi_netlink_notifier);
194 }
195
196 return;
197}
198
199
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index ae24c85aaeea..5d023d44e5e7 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -8,6 +8,7 @@ struct scsi_cmnd;
8struct scsi_device; 8struct scsi_device;
9struct scsi_host_template; 9struct scsi_host_template;
10struct Scsi_Host; 10struct Scsi_Host;
11struct scsi_nl_hdr;
11 12
12 13
13/* 14/*
@@ -110,6 +111,16 @@ extern void __scsi_remove_device(struct scsi_device *);
110 111
111extern struct bus_type scsi_bus_type; 112extern struct bus_type scsi_bus_type;
112 113
114/* scsi_netlink.c */
115#ifdef CONFIG_SCSI_NETLINK
116extern void scsi_netlink_init(void);
117extern void scsi_netlink_exit(void);
118extern struct sock *scsi_nl_sock;
119#else
120static inline void scsi_netlink_init(void) {}
121static inline void scsi_netlink_exit(void) {}
122#endif
123
113/* 124/*
114 * internal scsi timeout functions: for use by mid-layer and transport 125 * internal scsi timeout functions: for use by mid-layer and transport
115 * classes. 126 * classes.
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 79d31ca2b741..05989f130554 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -32,6 +32,9 @@
32#include <scsi/scsi_transport.h> 32#include <scsi/scsi_transport.h>
33#include <scsi/scsi_transport_fc.h> 33#include <scsi/scsi_transport_fc.h>
34#include <scsi/scsi_cmnd.h> 34#include <scsi/scsi_cmnd.h>
35#include <linux/netlink.h>
36#include <net/netlink.h>
37#include <scsi/scsi_netlink_fc.h>
35#include "scsi_priv.h" 38#include "scsi_priv.h"
36 39
37static int fc_queue_work(struct Scsi_Host *, struct work_struct *); 40static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
@@ -93,6 +96,29 @@ fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
93#define FC_PORTTYPE_MAX_NAMELEN 50 96#define FC_PORTTYPE_MAX_NAMELEN 50
94 97
95 98
99/* Convert fc_host_event_code values to ascii string name */
100static const struct {
101 enum fc_host_event_code value;
102 char *name;
103} fc_host_event_code_names[] = {
104 { FCH_EVT_LIP, "lip" },
105 { FCH_EVT_LINKUP, "link_up" },
106 { FCH_EVT_LINKDOWN, "link_down" },
107 { FCH_EVT_LIPRESET, "lip_reset" },
108 { FCH_EVT_RSCN, "rscn" },
109 { FCH_EVT_ADAPTER_CHANGE, "adapter_chg" },
110 { FCH_EVT_PORT_UNKNOWN, "port_unknown" },
111 { FCH_EVT_PORT_ONLINE, "port_online" },
112 { FCH_EVT_PORT_OFFLINE, "port_offline" },
113 { FCH_EVT_PORT_FABRIC, "port_fabric" },
114 { FCH_EVT_LINK_UNKNOWN, "link_unknown" },
115 { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" },
116};
117fc_enum_name_search(host_event_code, fc_host_event_code,
118 fc_host_event_code_names)
119#define FC_HOST_EVENT_CODE_MAX_NAMELEN 30
120
121
96/* Convert fc_port_state values to ascii string name */ 122/* Convert fc_port_state values to ascii string name */
97static struct { 123static struct {
98 enum fc_port_state value; 124 enum fc_port_state value;
@@ -377,10 +403,182 @@ MODULE_PARM_DESC(dev_loss_tmo,
377 " exceeded, the scsi target is removed. Value should be" 403 " exceeded, the scsi target is removed. Value should be"
378 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT."); 404 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT.");
379 405
406/**
407 * Netlink Infrastructure
408 **/
409
410static atomic_t fc_event_seq;
411
412/**
413 * fc_get_event_number - Obtain the next sequential FC event number
414 *
415 * Notes:
416 * We could have inline'd this, but it would have required fc_event_seq to
417 * be exposed. For now, live with the subroutine call.
418 * Atomic used to avoid lock/unlock...
419 **/
420u32
421fc_get_event_number(void)
422{
423 return atomic_add_return(1, &fc_event_seq);
424}
425EXPORT_SYMBOL(fc_get_event_number);
426
427
428/**
429 * fc_host_post_event - called to post an even on an fc_host.
430 *
431 * @shost: host the event occurred on
432 * @event_number: fc event number obtained from get_fc_event_number()
433 * @event_code: fc_host event being posted
434 * @event_data: 32bits of data for the event being posted
435 *
436 * Notes:
437 * This routine assumes no locks are held on entry.
438 **/
439void
440fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
441 enum fc_host_event_code event_code, u32 event_data)
442{
443 struct sk_buff *skb;
444 struct nlmsghdr *nlh;
445 struct fc_nl_event *event;
446 const char *name;
447 u32 len, skblen;
448 int err;
449
450 if (!scsi_nl_sock) {
451 err = -ENOENT;
452 goto send_fail;
453 }
454
455 len = FC_NL_MSGALIGN(sizeof(*event));
456 skblen = NLMSG_SPACE(len);
457
458 skb = alloc_skb(skblen, GFP_KERNEL);
459 if (!skb) {
460 err = -ENOBUFS;
461 goto send_fail;
462 }
463
464 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
465 skblen - sizeof(*nlh), 0);
466 if (!nlh) {
467 err = -ENOBUFS;
468 goto send_fail_skb;
469 }
470 event = NLMSG_DATA(nlh);
471
472 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
473 FC_NL_ASYNC_EVENT, len);
474 event->seconds = get_seconds();
475 event->vendor_id = 0;
476 event->host_no = shost->host_no;
477 event->event_datalen = sizeof(u32); /* bytes */
478 event->event_num = event_number;
479 event->event_code = event_code;
480 event->event_data = event_data;
481
482 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS);
483 if (err && (err != -ESRCH)) /* filter no recipient errors */
484 /* nlmsg_multicast already kfree_skb'd */
485 goto send_fail;
486
487 return;
488
489send_fail_skb:
490 kfree_skb(skb);
491send_fail:
492 name = get_fc_host_event_code_name(event_code);
493 printk(KERN_WARNING
494 "%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
495 __FUNCTION__, shost->host_no,
496 (name) ? name : "<unknown>", event_data, err);
497 return;
498}
499EXPORT_SYMBOL(fc_host_post_event);
500
501
502/**
503 * fc_host_post_vendor_event - called to post a vendor unique event on
504 * a fc_host
505 *
506 * @shost: host the event occurred on
507 * @event_number: fc event number obtained from get_fc_event_number()
508 * @data_len: amount, in bytes, of vendor unique data
509 * @data_buf: pointer to vendor unique data
510 *
511 * Notes:
512 * This routine assumes no locks are held on entry.
513 **/
514void
515fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
516 u32 data_len, char * data_buf, u32 vendor_id)
517{
518 struct sk_buff *skb;
519 struct nlmsghdr *nlh;
520 struct fc_nl_event *event;
521 u32 len, skblen;
522 int err;
523
524 if (!scsi_nl_sock) {
525 err = -ENOENT;
526 goto send_vendor_fail;
527 }
528
529 len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
530 skblen = NLMSG_SPACE(len);
531
532 skb = alloc_skb(skblen, GFP_KERNEL);
533 if (!skb) {
534 err = -ENOBUFS;
535 goto send_vendor_fail;
536 }
537
538 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
539 skblen - sizeof(*nlh), 0);
540 if (!nlh) {
541 err = -ENOBUFS;
542 goto send_vendor_fail_skb;
543 }
544 event = NLMSG_DATA(nlh);
545
546 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
547 FC_NL_ASYNC_EVENT, len);
548 event->seconds = get_seconds();
549 event->vendor_id = vendor_id;
550 event->host_no = shost->host_no;
551 event->event_datalen = data_len; /* bytes */
552 event->event_num = event_number;
553 event->event_code = FCH_EVT_VENDOR_UNIQUE;
554 memcpy(&event->event_data, data_buf, data_len);
555
556 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS);
557 if (err && (err != -ESRCH)) /* filter no recipient errors */
558 /* nlmsg_multicast already kfree_skb'd */
559 goto send_vendor_fail;
560
561 return;
562
563send_vendor_fail_skb:
564 kfree_skb(skb);
565send_vendor_fail:
566 printk(KERN_WARNING
567 "%s: Dropped Event : host %d vendor_unique - err %d\n",
568 __FUNCTION__, shost->host_no, err);
569 return;
570}
571EXPORT_SYMBOL(fc_host_post_vendor_event);
572
573
380 574
381static __init int fc_transport_init(void) 575static __init int fc_transport_init(void)
382{ 576{
383 int error = transport_class_register(&fc_host_class); 577 int error;
578
579 atomic_set(&fc_event_seq, 0);
580
581 error = transport_class_register(&fc_host_class);
384 if (error) 582 if (error)
385 return error; 583 return error;
386 error = transport_class_register(&fc_rport_class); 584 error = transport_class_register(&fc_rport_class);
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 855b44668caa..66411622e06e 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -21,6 +21,8 @@
21#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ 21#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
22#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ 22#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
23#define NETLINK_GENERIC 16 23#define NETLINK_GENERIC 16
24/* leave room for NETLINK_DM (DM Events) */
25#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
24 26
25#define MAX_LINKS 32 27#define MAX_LINKS 32
26 28
diff --git a/include/scsi/scsi_netlink.h b/include/scsi/scsi_netlink.h
new file mode 100644
index 000000000000..7a3a20e640c0
--- /dev/null
+++ b/include/scsi/scsi_netlink.h
@@ -0,0 +1,86 @@
1/*
2 * SCSI Transport Netlink Interface
3 * Used for the posting of outbound SCSI transport events
4 *
5 * Copyright (C) 2006 James Smart, Emulex Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22#ifndef SCSI_NETLINK_H
23#define SCSI_NETLINK_H
24
25/*
26 * This file intended to be included by both kernel and user space
27 */
28
29/* Single Netlink Message type to send all SCSI Transport messages */
30#define SCSI_TRANSPORT_MSG NLMSG_MIN_TYPE + 1
31
32/* SCSI Transport Broadcast Groups */
33 /* leaving groups 0 and 1 unassigned */
34#define SCSI_NL_GRP_FC_EVENTS (1<<2) /* Group 2 */
35#define SCSI_NL_GRP_CNT 3
36
37
38/* SCSI_TRANSPORT_MSG event message header */
39struct scsi_nl_hdr {
40 uint8_t version;
41 uint8_t transport;
42 uint16_t magic;
43 uint16_t msgtype;
44 uint16_t msglen;
45} __attribute__((aligned(sizeof(uint64_t))));
46
47/* scsi_nl_hdr->version value */
48#define SCSI_NL_VERSION 1
49
50/* scsi_nl_hdr->magic value */
51#define SCSI_NL_MAGIC 0xA1B2
52
53/* scsi_nl_hdr->transport value */
54#define SCSI_NL_TRANSPORT 0
55#define SCSI_NL_TRANSPORT_FC 1
56#define SCSI_NL_MAX_TRANSPORTS 2
57
58/* scsi_nl_hdr->msgtype values are defined in each transport */
59
60
61/*
62 * Vendor ID:
63 * If transports post vendor-unique events, they must pass a well-known
64 * 32-bit vendor identifier. This identifier consists of 8 bits indicating
65 * the "type" of identifier contained, and 24 bits of id data.
66 *
67 * Identifiers for each type:
68 * PCI : ID data is the 16 bit PCI Registered Vendor ID
69 */
70#define SCSI_NL_VID_ID_MASK 0x00FFFFFF
71#define SCSI_NL_VID_TYPE_MASK 0xFF000000
72#define SCSI_NL_VID_TYPE_PCI 0x01000000
73
74
75#define INIT_SCSI_NL_HDR(hdr, t, mtype, mlen) \
76 { \
77 (hdr)->version = SCSI_NL_VERSION; \
78 (hdr)->transport = t; \
79 (hdr)->magic = SCSI_NL_MAGIC; \
80 (hdr)->msgtype = mtype; \
81 (hdr)->msglen = mlen; \
82 }
83
84
85#endif /* SCSI_NETLINK_H */
86
diff --git a/include/scsi/scsi_netlink_fc.h b/include/scsi/scsi_netlink_fc.h
new file mode 100644
index 000000000000..b213d2909fed
--- /dev/null
+++ b/include/scsi/scsi_netlink_fc.h
@@ -0,0 +1,71 @@
1/*
2 * FC Transport Netlink Interface
3 *
4 * Copyright (C) 2006 James Smart, Emulex Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#ifndef SCSI_NETLINK_FC_H
22#define SCSI_NETLINK_FC_H
23
24#include <scsi/scsi_netlink.h>
25
26/*
27 * This file intended to be included by both kernel and user space
28 */
29
30/*
31 * FC Transport Message Types
32 */
33 /* kernel -> user */
34#define FC_NL_ASYNC_EVENT 0x0100
35 /* user -> kernel */
36/* none */
37
38
39/*
40 * Message Structures :
41 */
42
43/* macro to round up message lengths to 8byte boundary */
44#define FC_NL_MSGALIGN(len) (((len) + 7) & ~7)
45
46
47/*
48 * FC Transport Broadcast Event Message :
49 * FC_NL_ASYNC_EVENT
50 *
51 * Note: if Vendor Unique message, &event_data will be start of
52 * vendor unique payload, and the length of the payload is
53 * per event_datalen
54 *
55 * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
56 * formatting requirements specified in scsi_netlink.h
57 */
58struct fc_nl_event {
59 struct scsi_nl_hdr snlh; /* must be 1st element ! */
60 uint64_t seconds;
61 uint32_t vendor_id;
62 uint16_t host_no;
63 uint16_t event_datalen;
64 uint32_t event_num;
65 uint32_t event_code;
66 uint32_t event_data;
67} __attribute__((aligned(sizeof(uint64_t))));
68
69
70#endif /* SCSI_NETLINK_FC_H */
71
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index c74be5dabfeb..f91c5358af3a 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -29,6 +29,7 @@
29 29
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <scsi/scsi.h> 31#include <scsi/scsi.h>
32#include <scsi/scsi_netlink.h>
32 33
33struct scsi_transport_template; 34struct scsi_transport_template;
34 35
@@ -284,6 +285,30 @@ struct fc_host_statistics {
284 285
285 286
286/* 287/*
288 * FC Event Codes - Polled and Async, following FC HBAAPI v2.0 guidelines
289 */
290
291/*
292 * fc_host_event_code: If you alter this, you also need to alter
293 * scsi_transport_fc.c (for the ascii descriptions).
294 */
295enum fc_host_event_code {
296 FCH_EVT_LIP = 0x1,
297 FCH_EVT_LINKUP = 0x2,
298 FCH_EVT_LINKDOWN = 0x3,
299 FCH_EVT_LIPRESET = 0x4,
300 FCH_EVT_RSCN = 0x5,
301 FCH_EVT_ADAPTER_CHANGE = 0x103,
302 FCH_EVT_PORT_UNKNOWN = 0x200,
303 FCH_EVT_PORT_OFFLINE = 0x201,
304 FCH_EVT_PORT_ONLINE = 0x202,
305 FCH_EVT_PORT_FABRIC = 0x204,
306 FCH_EVT_LINK_UNKNOWN = 0x500,
307 FCH_EVT_VENDOR_UNIQUE = 0xffff,
308};
309
310
311/*
287 * FC Local Port (Host) Attributes 312 * FC Local Port (Host) Attributes
288 * 313 *
289 * Attributes are based on HBAAPI V2.0 definitions. 314 * Attributes are based on HBAAPI V2.0 definitions.
@@ -526,5 +551,14 @@ struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
526void fc_remote_port_delete(struct fc_rport *rport); 551void fc_remote_port_delete(struct fc_rport *rport);
527void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); 552void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
528int scsi_is_fc_rport(const struct device *); 553int scsi_is_fc_rport(const struct device *);
554u32 fc_get_event_number(void);
555void fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
556 enum fc_host_event_code event_code, u32 event_data);
557void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
558 u32 data_len, char * data_buf, u32 vendor_id);
559 /* Note: when specifying vendor_id to fc_host_post_vendor_event()
560 * be sure to read the Vendor Type and ID formatting requirements
561 * specified in scsi_netlink.h
562 */
529 563
530#endif /* SCSI_TRANSPORT_FC_H */ 564#endif /* SCSI_TRANSPORT_FC_H */