aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi/fc_frame.h
diff options
context:
space:
mode:
authorRobert Love <robert.w.love@intel.com>2008-12-09 18:10:17 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:33 -0500
commit42e9a92fe6a9095bd68a379aaec7ad2be0337f7a (patch)
tree344f8d9f72a3d926d652632abb8d319f8e32343a /include/scsi/fc_frame.h
parentf032c2f7cdaae0e8907cd3b26426fc651dc5c275 (diff)
[SCSI] libfc: A modular Fibre Channel library
libFC is composed of 4 blocks supported by an exchange manager and a framing library. The upper 4 layers are fc_lport, fc_disc, fc_rport and fc_fcp. A LLD that uses libfc could choose to either use libfc's block, or using the transport template defined in libfc.h, override one or more blocks with its own implementation. The EM (Exchange Manager) manages exhcanges/sequences for all commands- ELS, CT and FCP. The framing library frames ELS and CT commands. The fc_lport block manages the library's representation of the host's FC enabled ports. The fc_disc block manages discovery of targets as well as handling changes that occur in the FC fabric (via. RSCN events). The fc_rport block manages the library's representation of other entities in the FC fabric. Currently the library uses this block for targets, its peer when in point-to-point mode and the directory server, but can be extended for other entities if needed. The fc_fcp block interacts with the scsi-ml and handles all I/O. Signed-off-by: Robert Love <robert.w.love@intel.com> [jejb: added include of delay.h to fix ppc64 compile prob spotted by sfr] Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'include/scsi/fc_frame.h')
-rw-r--r--include/scsi/fc_frame.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h
new file mode 100644
index 000000000000..04d34a71355f
--- /dev/null
+++ b/include/scsi/fc_frame.h
@@ -0,0 +1,242 @@
1/*
2 * Copyright(c) 2007 Intel Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Maintained at www.Open-FCoE.org
18 */
19
20#ifndef _FC_FRAME_H_
21#define _FC_FRAME_H_
22
23#include <linux/scatterlist.h>
24#include <linux/skbuff.h>
25#include <scsi/scsi_cmnd.h>
26
27#include <scsi/fc/fc_fs.h>
28#include <scsi/fc/fc_fcp.h>
29#include <scsi/fc/fc_encaps.h>
30
31/*
32 * The fc_frame interface is used to pass frame data between functions.
33 * The frame includes the data buffer, length, and SOF / EOF delimiter types.
34 * A pointer to the port structure of the receiving port is also includeded.
35 */
36
37#define FC_FRAME_HEADROOM 32 /* headroom for VLAN + FCoE headers */
38#define FC_FRAME_TAILROOM 8 /* trailer space for FCoE */
39
40/*
41 * Information about an individual fibre channel frame received or to be sent.
42 * The buffer may be in up to 4 additional non-contiguous sections,
43 * but the linear section must hold the frame header.
44 */
45#define FC_FRAME_SG_LEN 4 /* scatter/gather list maximum length */
46
47#define fp_skb(fp) (&((fp)->skb))
48#define fr_hdr(fp) ((fp)->skb.data)
49#define fr_len(fp) ((fp)->skb.len)
50#define fr_cb(fp) ((struct fcoe_rcv_info *)&((fp)->skb.cb[0]))
51#define fr_dev(fp) (fr_cb(fp)->fr_dev)
52#define fr_seq(fp) (fr_cb(fp)->fr_seq)
53#define fr_sof(fp) (fr_cb(fp)->fr_sof)
54#define fr_eof(fp) (fr_cb(fp)->fr_eof)
55#define fr_flags(fp) (fr_cb(fp)->fr_flags)
56#define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload)
57#define fr_cmd(fp) (fr_cb(fp)->fr_cmd)
58#define fr_dir(fp) (fr_cmd(fp)->sc_data_direction)
59#define fr_crc(fp) (fr_cb(fp)->fr_crc)
60
61struct fc_frame {
62 struct sk_buff skb;
63};
64
65struct fcoe_rcv_info {
66 struct packet_type *ptype;
67 struct fc_lport *fr_dev; /* transport layer private pointer */
68 struct fc_seq *fr_seq; /* for use with exchange manager */
69 struct scsi_cmnd *fr_cmd; /* for use of scsi command */
70 u32 fr_crc;
71 u16 fr_max_payload; /* max FC payload */
72 enum fc_sof fr_sof; /* start of frame delimiter */
73 enum fc_eof fr_eof; /* end of frame delimiter */
74 u8 fr_flags; /* flags - see below */
75};
76
77
78/*
79 * Get fc_frame pointer for an skb that's already been imported.
80 */
81static inline struct fcoe_rcv_info *fcoe_dev_from_skb(const struct sk_buff *skb)
82{
83 BUILD_BUG_ON(sizeof(struct fcoe_rcv_info) > sizeof(skb->cb));
84 return (struct fcoe_rcv_info *) skb->cb;
85}
86
87/*
88 * fr_flags.
89 */
90#define FCPHF_CRC_UNCHECKED 0x01 /* CRC not computed, still appended */
91
92/*
93 * Initialize a frame.
94 * We don't do a complete memset here for performance reasons.
95 * The caller must set fr_free, fr_hdr, fr_len, fr_sof, and fr_eof eventually.
96 */
97static inline void fc_frame_init(struct fc_frame *fp)
98{
99 fr_dev(fp) = NULL;
100 fr_seq(fp) = NULL;
101 fr_flags(fp) = 0;
102}
103
104struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len);
105
106struct fc_frame *__fc_frame_alloc(size_t payload_len);
107
108/*
109 * Get frame for sending via port.
110 */
111static inline struct fc_frame *_fc_frame_alloc(struct fc_lport *dev,
112 size_t payload_len)
113{
114 return __fc_frame_alloc(payload_len);
115}
116
117/*
118 * Allocate fc_frame structure and buffer. Set the initial length to
119 * payload_size + sizeof (struct fc_frame_header).
120 */
121static inline struct fc_frame *fc_frame_alloc(struct fc_lport *dev, size_t len)
122{
123 struct fc_frame *fp;
124
125 /*
126 * Note: Since len will often be a constant multiple of 4,
127 * this check will usually be evaluated and eliminated at compile time.
128 */
129 if ((len % 4) != 0)
130 fp = fc_frame_alloc_fill(dev, len);
131 else
132 fp = _fc_frame_alloc(dev, len);
133 return fp;
134}
135
136/*
137 * Free the fc_frame structure and buffer.
138 */
139static inline void fc_frame_free(struct fc_frame *fp)
140{
141 kfree_skb(fp_skb(fp));
142}
143
144static inline int fc_frame_is_linear(struct fc_frame *fp)
145{
146 return !skb_is_nonlinear(fp_skb(fp));
147}
148
149/*
150 * Get frame header from message in fc_frame structure.
151 * This hides a cast and provides a place to add some checking.
152 */
153static inline
154struct fc_frame_header *fc_frame_header_get(const struct fc_frame *fp)
155{
156 WARN_ON(fr_len(fp) < sizeof(struct fc_frame_header));
157 return (struct fc_frame_header *) fr_hdr(fp);
158}
159
160/*
161 * Get frame payload from message in fc_frame structure.
162 * This hides a cast and provides a place to add some checking.
163 * The len parameter is the minimum length for the payload portion.
164 * Returns NULL if the frame is too short.
165 *
166 * This assumes the interesting part of the payload is in the first part
167 * of the buffer for received data. This may not be appropriate to use for
168 * buffers being transmitted.
169 */
170static inline void *fc_frame_payload_get(const struct fc_frame *fp,
171 size_t len)
172{
173 void *pp = NULL;
174
175 if (fr_len(fp) >= sizeof(struct fc_frame_header) + len)
176 pp = fc_frame_header_get(fp) + 1;
177 return pp;
178}
179
180/*
181 * Get frame payload opcode (first byte) from message in fc_frame structure.
182 * This hides a cast and provides a place to add some checking. Return 0
183 * if the frame has no payload.
184 */
185static inline u8 fc_frame_payload_op(const struct fc_frame *fp)
186{
187 u8 *cp;
188
189 cp = fc_frame_payload_get(fp, sizeof(u8));
190 if (!cp)
191 return 0;
192 return *cp;
193
194}
195
196/*
197 * Get FC class from frame.
198 */
199static inline enum fc_class fc_frame_class(const struct fc_frame *fp)
200{
201 return fc_sof_class(fr_sof(fp));
202}
203
204/*
205 * Check the CRC in a frame.
206 * The CRC immediately follows the last data item *AFTER* the length.
207 * The return value is zero if the CRC matches.
208 */
209u32 fc_frame_crc_check(struct fc_frame *);
210
211static inline u8 fc_frame_rctl(const struct fc_frame *fp)
212{
213 return fc_frame_header_get(fp)->fh_r_ctl;
214}
215
216static inline bool fc_frame_is_cmd(const struct fc_frame *fp)
217{
218 return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD;
219}
220
221static inline bool fc_frame_is_read(const struct fc_frame *fp)
222{
223 if (fc_frame_is_cmd(fp) && fr_cmd(fp))
224 return fr_dir(fp) == DMA_FROM_DEVICE;
225 return false;
226}
227
228static inline bool fc_frame_is_write(const struct fc_frame *fp)
229{
230 if (fc_frame_is_cmd(fp) && fr_cmd(fp))
231 return fr_dir(fp) == DMA_TO_DEVICE;
232 return false;
233}
234
235/*
236 * Check for leaks.
237 * Print the frame header of any currently allocated frame, assuming there
238 * should be none at this point.
239 */
240void fc_frame_leak_check(void);
241
242#endif /* _FC_FRAME_H_ */