Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/scsi/fc_frame.h
26278 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
* Copyright(c) 2007 Intel Corporation. All rights reserved.
4
*
5
* Maintained at www.Open-FCoE.org
6
*/
7
8
#ifndef _FC_FRAME_H_
9
#define _FC_FRAME_H_
10
11
#include <linux/scatterlist.h>
12
#include <linux/skbuff.h>
13
#include <scsi/scsi_cmnd.h>
14
15
#include <scsi/fc/fc_fs.h>
16
#include <scsi/fc/fc_fcp.h>
17
#include <scsi/fc/fc_encaps.h>
18
19
#include <linux/if_ether.h>
20
21
/* some helpful macros */
22
23
#define ntohll(x) be64_to_cpu(x)
24
#define htonll(x) cpu_to_be64(x)
25
26
static inline u32 ntoh24(const u8 *p)
27
{
28
return (p[0] << 16) | (p[1] << 8) | p[2];
29
}
30
31
static inline void hton24(u8 *p, u32 v)
32
{
33
p[0] = (v >> 16) & 0xff;
34
p[1] = (v >> 8) & 0xff;
35
p[2] = v & 0xff;
36
}
37
38
/*
39
* The fc_frame interface is used to pass frame data between functions.
40
* The frame includes the data buffer, length, and SOF / EOF delimiter types.
41
* A pointer to the port structure of the receiving port is also includeded.
42
*/
43
44
#define FC_FRAME_HEADROOM 32 /* headroom for VLAN + FCoE headers */
45
#define FC_FRAME_TAILROOM 8 /* trailer space for FCoE */
46
47
/* Max number of skb frags allowed, reserving one for fcoe_crc_eof page */
48
#define FC_FRAME_SG_LEN (MAX_SKB_FRAGS - 1)
49
50
#define fp_skb(fp) (&((fp)->skb))
51
#define fr_hdr(fp) ((fp)->skb.data)
52
#define fr_len(fp) ((fp)->skb.len)
53
#define fr_cb(fp) ((struct fcoe_rcv_info *)&((fp)->skb.cb[0]))
54
#define fr_dev(fp) (fr_cb(fp)->fr_dev)
55
#define fr_seq(fp) (fr_cb(fp)->fr_seq)
56
#define fr_sof(fp) (fr_cb(fp)->fr_sof)
57
#define fr_eof(fp) (fr_cb(fp)->fr_eof)
58
#define fr_flags(fp) (fr_cb(fp)->fr_flags)
59
#define fr_encaps(fp) (fr_cb(fp)->fr_encaps)
60
#define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload)
61
#define fr_fsp(fp) (fr_cb(fp)->fr_fsp)
62
#define fr_crc(fp) (fr_cb(fp)->fr_crc)
63
64
struct fc_frame {
65
struct sk_buff skb;
66
};
67
68
struct fcoe_rcv_info {
69
struct fc_lport *fr_dev; /* transport layer private pointer */
70
struct fc_seq *fr_seq; /* for use with exchange manager */
71
struct fc_fcp_pkt *fr_fsp; /* for the corresponding fcp I/O */
72
u32 fr_crc;
73
u16 fr_max_payload; /* max FC payload */
74
u8 fr_sof; /* start of frame delimiter */
75
u8 fr_eof; /* end of frame delimiter */
76
u8 fr_flags; /* flags - see below */
77
u8 fr_encaps; /* LLD encapsulation info (e.g. FIP) */
78
u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */
79
};
80
81
82
/*
83
* Get fc_frame pointer for an skb that's already been imported.
84
*/
85
static inline struct fcoe_rcv_info *fcoe_dev_from_skb(const struct sk_buff *skb)
86
{
87
BUILD_BUG_ON(sizeof(struct fcoe_rcv_info) > sizeof(skb->cb));
88
return (struct fcoe_rcv_info *) skb->cb;
89
}
90
91
/*
92
* fr_flags.
93
*/
94
#define FCPHF_CRC_UNCHECKED 0x01 /* CRC not computed, still appended */
95
96
/*
97
* Initialize a frame.
98
* We don't do a complete memset here for performance reasons.
99
* The caller must set fr_free, fr_hdr, fr_len, fr_sof, and fr_eof eventually.
100
*/
101
static inline void fc_frame_init(struct fc_frame *fp)
102
{
103
fr_dev(fp) = NULL;
104
fr_seq(fp) = NULL;
105
fr_flags(fp) = 0;
106
fr_encaps(fp) = 0;
107
}
108
109
struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len);
110
struct fc_frame *_fc_frame_alloc(size_t payload_len);
111
112
/*
113
* Allocate fc_frame structure and buffer. Set the initial length to
114
* payload_size + sizeof (struct fc_frame_header).
115
*/
116
static inline struct fc_frame *fc_frame_alloc(struct fc_lport *dev, size_t len)
117
{
118
struct fc_frame *fp;
119
120
/*
121
* Note: Since len will often be a constant multiple of 4,
122
* this check will usually be evaluated and eliminated at compile time.
123
*/
124
if (len && len % 4)
125
fp = fc_frame_alloc_fill(dev, len);
126
else
127
fp = _fc_frame_alloc(len);
128
return fp;
129
}
130
131
/*
132
* Free the fc_frame structure and buffer.
133
*/
134
static inline void fc_frame_free(struct fc_frame *fp)
135
{
136
kfree_skb(fp_skb(fp));
137
}
138
139
static inline int fc_frame_is_linear(struct fc_frame *fp)
140
{
141
return !skb_is_nonlinear(fp_skb(fp));
142
}
143
144
/*
145
* Get frame header from message in fc_frame structure.
146
* This version doesn't do a length check.
147
*/
148
static inline
149
struct fc_frame_header *__fc_frame_header_get(const struct fc_frame *fp)
150
{
151
return (struct fc_frame_header *)fr_hdr(fp);
152
}
153
154
/*
155
* Get frame header from message in fc_frame structure.
156
* This hides a cast and provides a place to add some checking.
157
*/
158
static inline
159
struct fc_frame_header *fc_frame_header_get(const struct fc_frame *fp)
160
{
161
WARN_ON(fr_len(fp) < sizeof(struct fc_frame_header));
162
return __fc_frame_header_get(fp);
163
}
164
165
/*
166
* Get source FC_ID (S_ID) from frame header in message.
167
*/
168
static inline u32 fc_frame_sid(const struct fc_frame *fp)
169
{
170
return ntoh24(__fc_frame_header_get(fp)->fh_s_id);
171
}
172
173
/*
174
* Get destination FC_ID (D_ID) from frame header in message.
175
*/
176
static inline u32 fc_frame_did(const struct fc_frame *fp)
177
{
178
return ntoh24(__fc_frame_header_get(fp)->fh_d_id);
179
}
180
181
/*
182
* Get frame payload from message in fc_frame structure.
183
* This hides a cast and provides a place to add some checking.
184
* The len parameter is the minimum length for the payload portion.
185
* Returns NULL if the frame is too short.
186
*
187
* This assumes the interesting part of the payload is in the first part
188
* of the buffer for received data. This may not be appropriate to use for
189
* buffers being transmitted.
190
*/
191
static inline void *fc_frame_payload_get(const struct fc_frame *fp,
192
size_t len)
193
{
194
void *pp = NULL;
195
196
if (fr_len(fp) >= sizeof(struct fc_frame_header) + len)
197
pp = fc_frame_header_get(fp) + 1;
198
return pp;
199
}
200
201
/*
202
* Get frame payload opcode (first byte) from message in fc_frame structure.
203
* This hides a cast and provides a place to add some checking. Return 0
204
* if the frame has no payload.
205
*/
206
static inline u8 fc_frame_payload_op(const struct fc_frame *fp)
207
{
208
u8 *cp;
209
210
cp = fc_frame_payload_get(fp, sizeof(u8));
211
if (!cp)
212
return 0;
213
return *cp;
214
215
}
216
217
/*
218
* Get FC class from frame.
219
*/
220
static inline enum fc_class fc_frame_class(const struct fc_frame *fp)
221
{
222
return fc_sof_class(fr_sof(fp));
223
}
224
225
/*
226
* Check the CRC in a frame.
227
* The CRC immediately follows the last data item *AFTER* the length.
228
* The return value is zero if the CRC matches.
229
*/
230
u32 fc_frame_crc_check(struct fc_frame *);
231
232
static inline u8 fc_frame_rctl(const struct fc_frame *fp)
233
{
234
return fc_frame_header_get(fp)->fh_r_ctl;
235
}
236
237
static inline bool fc_frame_is_cmd(const struct fc_frame *fp)
238
{
239
return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD;
240
}
241
242
/*
243
* Check for leaks.
244
* Print the frame header of any currently allocated frame, assuming there
245
* should be none at this point.
246
*/
247
void fc_frame_leak_check(void);
248
249
static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
250
enum fc_rctl r_ctl,
251
u32 did, u32 sid, enum fc_fh_type type,
252
u32 f_ctl, u32 parm_offset)
253
{
254
WARN_ON(r_ctl == 0);
255
fh->fh_r_ctl = r_ctl;
256
hton24(fh->fh_d_id, did);
257
hton24(fh->fh_s_id, sid);
258
fh->fh_type = type;
259
hton24(fh->fh_f_ctl, f_ctl);
260
fh->fh_cs_ctl = 0;
261
fh->fh_df_ctl = 0;
262
fh->fh_parm_offset = htonl(parm_offset);
263
}
264
265
/**
266
* fill FC header fields in specified fc_frame
267
*/
268
static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
269
u32 did, u32 sid, enum fc_fh_type type,
270
u32 f_ctl, u32 parm_offset)
271
{
272
struct fc_frame_header *fh;
273
274
fh = fc_frame_header_get(fp);
275
__fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset);
276
}
277
278
279
#endif /* _FC_FRAME_H_ */
280
281