Blame view

drivers/firewire/net.c 41.4 KB
c76acec6d   Jay Fenlason   firewire: add IPv...
1
2
  /*
   * IPv4 over IEEE 1394, per RFC 2734
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
3
   * IPv6 over IEEE 1394, per RFC 3146
c76acec6d   Jay Fenlason   firewire: add IPv...
4
5
6
7
8
   *
   * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com>
   *
   * based on eth1394 by Ben Collins et al
   */
f91e3bd84   Stefan Richter   firewire: net: st...
9
  #include <linux/bug.h>
bf337b15c   August Lilleaas   firewire: net: re...
10
  #include <linux/compiler.h>
48553011c   Stefan Richter   firewire: net: re...
11
  #include <linux/delay.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
12
  #include <linux/device.h>
c16714704   Stefan Richter   firewire: net: se...
13
  #include <linux/ethtool.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
14
15
16
17
18
  #include <linux/firewire.h>
  #include <linux/firewire-constants.h>
  #include <linux/highmem.h>
  #include <linux/in.h>
  #include <linux/ip.h>
f91e3bd84   Stefan Richter   firewire: net: st...
19
  #include <linux/jiffies.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
20
21
22
  #include <linux/mod_devicetable.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
5a124d382   Stefan Richter   firewire: net: al...
23
  #include <linux/mutex.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
24
25
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
5a124d382   Stefan Richter   firewire: net: al...
27
  #include <linux/spinlock.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
28
29
30
  
  #include <asm/unaligned.h>
  #include <net/arp.h>
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
31
  #include <net/firewire.h>
c76acec6d   Jay Fenlason   firewire: add IPv...
32

b2268830f   Stefan Richter   firewire: net: th...
33
34
35
36
37
38
39
40
  /* rx limits */
  #define FWNET_MAX_FRAGMENTS		30 /* arbitrary, > TX queue depth */
  #define FWNET_ISO_PAGE_COUNT		(PAGE_SIZE < 16*1024 ? 4 : 2)
  
  /* tx limits */
  #define FWNET_MAX_QUEUED_DATAGRAMS	20 /* < 64 = number of tlabels */
  #define FWNET_MIN_QUEUED_DATAGRAMS	10 /* should keep AT DMA busy enough */
  #define FWNET_TX_QUEUE_LEN		FWNET_MAX_QUEUED_DATAGRAMS /* ? */
c76acec6d   Jay Fenlason   firewire: add IPv...
41

f91e3bd84   Stefan Richter   firewire: net: st...
42
43
44
45
  #define IEEE1394_BROADCAST_CHANNEL	31
  #define IEEE1394_ALL_NODES		(0xffc0 | 0x003f)
  #define IEEE1394_MAX_PAYLOAD_S100	512
  #define FWNET_NO_FIFO_ADDR		(~0ULL)
c76acec6d   Jay Fenlason   firewire: add IPv...
46

f91e3bd84   Stefan Richter   firewire: net: st...
47
48
  #define IANA_SPECIFIER_ID		0x00005eU
  #define RFC2734_SW_VERSION		0x000001U
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
49
  #define RFC3146_SW_VERSION		0x000002U
c76acec6d   Jay Fenlason   firewire: add IPv...
50

f91e3bd84   Stefan Richter   firewire: net: st...
51
  #define IEEE1394_GASP_HDR_SIZE	8
c76acec6d   Jay Fenlason   firewire: add IPv...
52

f91e3bd84   Stefan Richter   firewire: net: st...
53
54
55
  #define RFC2374_UNFRAG_HDR_SIZE	4
  #define RFC2374_FRAG_HDR_SIZE	8
  #define RFC2374_FRAG_OVERHEAD	4
c76acec6d   Jay Fenlason   firewire: add IPv...
56

f91e3bd84   Stefan Richter   firewire: net: st...
57
58
59
60
  #define RFC2374_HDR_UNFRAG	0	/* unfragmented		*/
  #define RFC2374_HDR_FIRSTFRAG	1	/* first fragment	*/
  #define RFC2374_HDR_LASTFRAG	2	/* last fragment	*/
  #define RFC2374_HDR_INTFRAG	3	/* interior fragment	*/
c76acec6d   Jay Fenlason   firewire: add IPv...
61

021b97e46   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Sen...
62
63
64
65
  static bool fwnet_hwaddr_is_multicast(u8 *ha)
  {
  	return !!(*ha & 1);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
66
67
  /* IPv4 and IPv6 encapsulation header */
  struct rfc2734_header {
c76acec6d   Jay Fenlason   firewire: add IPv...
68
69
70
  	u32 w0;
  	u32 w1;
  };
f91e3bd84   Stefan Richter   firewire: net: st...
71
72
  #define fwnet_get_hdr_lf(h)		(((h)->w0 & 0xc0000000) >> 30)
  #define fwnet_get_hdr_ether_type(h)	(((h)->w0 & 0x0000ffff))
e9300a4b7   Stefan Richter   firewire: net: fi...
73
  #define fwnet_get_hdr_dg_size(h)	((((h)->w0 & 0x0fff0000) >> 16) + 1)
f91e3bd84   Stefan Richter   firewire: net: st...
74
75
  #define fwnet_get_hdr_fg_off(h)		(((h)->w0 & 0x00000fff))
  #define fwnet_get_hdr_dgl(h)		(((h)->w1 & 0xffff0000) >> 16)
c76acec6d   Jay Fenlason   firewire: add IPv...
76

e9300a4b7   Stefan Richter   firewire: net: fi...
77
  #define fwnet_set_hdr_lf(lf)		((lf) << 30)
f91e3bd84   Stefan Richter   firewire: net: st...
78
  #define fwnet_set_hdr_ether_type(et)	(et)
e9300a4b7   Stefan Richter   firewire: net: fi...
79
  #define fwnet_set_hdr_dg_size(dgs)	(((dgs) - 1) << 16)
f91e3bd84   Stefan Richter   firewire: net: st...
80
  #define fwnet_set_hdr_fg_off(fgo)	(fgo)
c76acec6d   Jay Fenlason   firewire: add IPv...
81

f91e3bd84   Stefan Richter   firewire: net: st...
82
  #define fwnet_set_hdr_dgl(dgl)		((dgl) << 16)
c76acec6d   Jay Fenlason   firewire: add IPv...
83

f91e3bd84   Stefan Richter   firewire: net: st...
84
85
86
87
88
89
  static inline void fwnet_make_uf_hdr(struct rfc2734_header *hdr,
  		unsigned ether_type)
  {
  	hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_UNFRAG)
  		  | fwnet_set_hdr_ether_type(ether_type);
  }
c76acec6d   Jay Fenlason   firewire: add IPv...
90

f91e3bd84   Stefan Richter   firewire: net: st...
91
92
93
94
95
96
97
98
  static inline void fwnet_make_ff_hdr(struct rfc2734_header *hdr,
  		unsigned ether_type, unsigned dg_size, unsigned dgl)
  {
  	hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_FIRSTFRAG)
  		  | fwnet_set_hdr_dg_size(dg_size)
  		  | fwnet_set_hdr_ether_type(ether_type);
  	hdr->w1 = fwnet_set_hdr_dgl(dgl);
  }
c76acec6d   Jay Fenlason   firewire: add IPv...
99

f91e3bd84   Stefan Richter   firewire: net: st...
100
101
102
103
104
105
106
107
  static inline void fwnet_make_sf_hdr(struct rfc2734_header *hdr,
  		unsigned lf, unsigned dg_size, unsigned fg_off, unsigned dgl)
  {
  	hdr->w0 = fwnet_set_hdr_lf(lf)
  		  | fwnet_set_hdr_dg_size(dg_size)
  		  | fwnet_set_hdr_fg_off(fg_off);
  	hdr->w1 = fwnet_set_hdr_dgl(dgl);
  }
c76acec6d   Jay Fenlason   firewire: add IPv...
108
109
  
  /* This list keeps track of what parts of the datagram have been filled in */
f91e3bd84   Stefan Richter   firewire: net: st...
110
111
  struct fwnet_fragment_info {
  	struct list_head fi_link;
c76acec6d   Jay Fenlason   firewire: add IPv...
112
113
114
  	u16 offset;
  	u16 len;
  };
f91e3bd84   Stefan Richter   firewire: net: st...
115
116
117
  struct fwnet_partial_datagram {
  	struct list_head pd_link;
  	struct list_head fi_list;
c76acec6d   Jay Fenlason   firewire: add IPv...
118
119
120
121
122
123
124
  	struct sk_buff *skb;
  	/* FIXME Why not use skb->data? */
  	char *pbuf;
  	u16 datagram_label;
  	u16 ether_type;
  	u16 datagram_size;
  };
5a124d382   Stefan Richter   firewire: net: al...
125
126
  static DEFINE_MUTEX(fwnet_device_mutex);
  static LIST_HEAD(fwnet_device_list);
c76acec6d   Jay Fenlason   firewire: add IPv...
127

f91e3bd84   Stefan Richter   firewire: net: st...
128
  struct fwnet_device {
5a124d382   Stefan Richter   firewire: net: al...
129
  	struct list_head dev_link;
c76acec6d   Jay Fenlason   firewire: add IPv...
130
  	spinlock_t lock;
f91e3bd84   Stefan Richter   firewire: net: st...
131
132
133
134
135
  	enum {
  		FWNET_BROADCAST_ERROR,
  		FWNET_BROADCAST_RUNNING,
  		FWNET_BROADCAST_STOPPED,
  	} broadcast_state;
c76acec6d   Jay Fenlason   firewire: add IPv...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	struct fw_iso_context *broadcast_rcv_context;
  	struct fw_iso_buffer broadcast_rcv_buffer;
  	void **broadcast_rcv_buffer_ptrs;
  	unsigned broadcast_rcv_next_ptr;
  	unsigned num_broadcast_rcv_ptrs;
  	unsigned rcv_buffer_size;
  	/*
  	 * This value is the maximum unfragmented datagram size that can be
  	 * sent by the hardware.  It already has the GASP overhead and the
  	 * unfragmented datagram header overhead calculated into it.
  	 */
  	unsigned broadcast_xmt_max_payload;
  	u16 broadcast_xmt_datagramlabel;
  
  	/*
f91e3bd84   Stefan Richter   firewire: net: st...
151
  	 * The CSR address that remote nodes must send datagrams to for us to
c76acec6d   Jay Fenlason   firewire: add IPv...
152
153
154
155
  	 * receive them.
  	 */
  	struct fw_address_handler handler;
  	u64 local_fifo;
48553011c   Stefan Richter   firewire: net: re...
156
157
  	/* Number of tx datagrams that have been queued but not yet acked */
  	int queued_datagrams;
c76acec6d   Jay Fenlason   firewire: add IPv...
158

c16714704   Stefan Richter   firewire: net: se...
159
  	int peer_count;
5a124d382   Stefan Richter   firewire: net: al...
160
  	struct list_head peer_list;
c76acec6d   Jay Fenlason   firewire: add IPv...
161
  	struct fw_card *card;
5a124d382   Stefan Richter   firewire: net: al...
162
163
164
165
166
167
168
  	struct net_device *netdev;
  };
  
  struct fwnet_peer {
  	struct list_head peer_link;
  	struct fwnet_device *dev;
  	u64 guid;
5a124d382   Stefan Richter   firewire: net: al...
169
170
171
172
173
174
  
  	/* guarded by dev->lock */
  	struct list_head pd_list; /* received partial datagrams */
  	unsigned pdg_size;        /* pd_list size */
  
  	u16 datagram_label;       /* outgoing datagram label */
48553011c   Stefan Richter   firewire: net: re...
175
  	u16 max_payload;          /* includes RFC2374_FRAG_HDR_SIZE overhead */
5a124d382   Stefan Richter   firewire: net: al...
176
177
178
  	int node_id;
  	int generation;
  	unsigned speed;
c76acec6d   Jay Fenlason   firewire: add IPv...
179
180
181
  };
  
  /* This is our task struct. It's used for the packet complete callback.  */
f91e3bd84   Stefan Richter   firewire: net: st...
182
  struct fwnet_packet_task {
c76acec6d   Jay Fenlason   firewire: add IPv...
183
  	struct fw_transaction transaction;
f91e3bd84   Stefan Richter   firewire: net: st...
184
  	struct rfc2734_header hdr;
c76acec6d   Jay Fenlason   firewire: add IPv...
185
  	struct sk_buff *skb;
f91e3bd84   Stefan Richter   firewire: net: st...
186
  	struct fwnet_device *dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
187
  	int outstanding_pkts;
c76acec6d   Jay Fenlason   firewire: add IPv...
188
189
  	u64 fifo_addr;
  	u16 dest_node;
48553011c   Stefan Richter   firewire: net: re...
190
  	u16 max_payload;
c76acec6d   Jay Fenlason   firewire: add IPv...
191
192
  	u8 generation;
  	u8 speed;
48553011c   Stefan Richter   firewire: net: re...
193
  	u8 enqueued;
c76acec6d   Jay Fenlason   firewire: add IPv...
194
  };
f91e3bd84   Stefan Richter   firewire: net: st...
195
  /*
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
196
197
198
199
200
201
202
203
204
   * Get fifo address embedded in hwaddr
   */
  static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
  {
  	return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
  	       | get_unaligned_be32(&ha->uc.fifo_lo);
  }
  
  /*
f91e3bd84   Stefan Richter   firewire: net: st...
205
206
207
208
209
210
211
212
   * saddr == NULL means use device source address.
   * daddr == NULL means leave destination address (eg unresolved arp).
   */
  static int fwnet_header_create(struct sk_buff *skb, struct net_device *net,
  			unsigned short type, const void *daddr,
  			const void *saddr, unsigned len)
  {
  	struct fwnet_header *h;
c76acec6d   Jay Fenlason   firewire: add IPv...
213

d58ff3512   Johannes Berg   networking: make ...
214
  	h = skb_push(skb, sizeof(*h));
f91e3bd84   Stefan Richter   firewire: net: st...
215
  	put_unaligned_be16(type, &h->h_proto);
c76acec6d   Jay Fenlason   firewire: add IPv...
216

f91e3bd84   Stefan Richter   firewire: net: st...
217
218
  	if (net->flags & (IFF_LOOPBACK | IFF_NOARP)) {
  		memset(h->h_dest, 0, net->addr_len);
c76acec6d   Jay Fenlason   firewire: add IPv...
219

f91e3bd84   Stefan Richter   firewire: net: st...
220
  		return net->hard_header_len;
c76acec6d   Jay Fenlason   firewire: add IPv...
221
222
223
  	}
  
  	if (daddr) {
f91e3bd84   Stefan Richter   firewire: net: st...
224
225
226
  		memcpy(h->h_dest, daddr, net->addr_len);
  
  		return net->hard_header_len;
c76acec6d   Jay Fenlason   firewire: add IPv...
227
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
228
  	return -net->hard_header_len;
c76acec6d   Jay Fenlason   firewire: add IPv...
229
  }
f91e3bd84   Stefan Richter   firewire: net: st...
230
  static int fwnet_header_cache(const struct neighbour *neigh,
e69dd336e   David S. Miller   net: Push protoco...
231
  			      struct hh_cache *hh, __be16 type)
f91e3bd84   Stefan Richter   firewire: net: st...
232
233
234
  {
  	struct net_device *net;
  	struct fwnet_header *h;
c76acec6d   Jay Fenlason   firewire: add IPv...
235

e69dd336e   David S. Miller   net: Push protoco...
236
  	if (type == cpu_to_be16(ETH_P_802_3))
c76acec6d   Jay Fenlason   firewire: add IPv...
237
  		return -1;
f91e3bd84   Stefan Richter   firewire: net: st...
238
  	net = neigh->dev;
825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
239
  	h = (struct fwnet_header *)((u8 *)hh->hh_data + HH_DATA_OFF(sizeof(*h)));
e69dd336e   David S. Miller   net: Push protoco...
240
  	h->h_proto = type;
f91e3bd84   Stefan Richter   firewire: net: st...
241
242
  	memcpy(h->h_dest, neigh->ha, net->addr_len);
  	hh->hh_len = FWNET_HLEN;
c76acec6d   Jay Fenlason   firewire: add IPv...
243

c76acec6d   Jay Fenlason   firewire: add IPv...
244
245
246
247
  	return 0;
  }
  
  /* Called by Address Resolution module to notify changes in address. */
f91e3bd84   Stefan Richter   firewire: net: st...
248
249
250
  static void fwnet_header_cache_update(struct hh_cache *hh,
  		const struct net_device *net, const unsigned char *haddr)
  {
825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
251
  	memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len);
c76acec6d   Jay Fenlason   firewire: add IPv...
252
  }
f91e3bd84   Stefan Richter   firewire: net: st...
253
254
255
256
257
  static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  {
  	memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN);
  
  	return FWNET_ALEN;
c76acec6d   Jay Fenlason   firewire: add IPv...
258
  }
f91e3bd84   Stefan Richter   firewire: net: st...
259
260
  static const struct header_ops fwnet_header_ops = {
  	.create         = fwnet_header_create,
f91e3bd84   Stefan Richter   firewire: net: st...
261
262
263
  	.cache		= fwnet_header_cache,
  	.cache_update	= fwnet_header_cache_update,
  	.parse          = fwnet_header_parse,
c76acec6d   Jay Fenlason   firewire: add IPv...
264
  };
c76acec6d   Jay Fenlason   firewire: add IPv...
265
  /* FIXME: is this correct for all cases? */
f91e3bd84   Stefan Richter   firewire: net: st...
266
267
  static bool fwnet_frag_overlap(struct fwnet_partial_datagram *pd,
  			       unsigned offset, unsigned len)
c76acec6d   Jay Fenlason   firewire: add IPv...
268
  {
f91e3bd84   Stefan Richter   firewire: net: st...
269
  	struct fwnet_fragment_info *fi;
c76acec6d   Jay Fenlason   firewire: add IPv...
270
  	unsigned end = offset + len;
f91e3bd84   Stefan Richter   firewire: net: st...
271
272
  	list_for_each_entry(fi, &pd->fi_list, fi_link)
  		if (offset < fi->offset + fi->len && end > fi->offset)
c76acec6d   Jay Fenlason   firewire: add IPv...
273
  			return true;
f91e3bd84   Stefan Richter   firewire: net: st...
274

c76acec6d   Jay Fenlason   firewire: add IPv...
275
276
277
278
  	return false;
  }
  
  /* Assumes that new fragment does not overlap any existing fragments */
f91e3bd84   Stefan Richter   firewire: net: st...
279
280
281
282
  static struct fwnet_fragment_info *fwnet_frag_new(
  	struct fwnet_partial_datagram *pd, unsigned offset, unsigned len)
  {
  	struct fwnet_fragment_info *fi, *fi2, *new;
c76acec6d   Jay Fenlason   firewire: add IPv...
283
  	struct list_head *list;
f91e3bd84   Stefan Richter   firewire: net: st...
284
285
  	list = &pd->fi_list;
  	list_for_each_entry(fi, &pd->fi_list, fi_link) {
c76acec6d   Jay Fenlason   firewire: add IPv...
286
287
288
  		if (fi->offset + fi->len == offset) {
  			/* The new fragment can be tacked on to the end */
  			/* Did the new fragment plug a hole? */
f91e3bd84   Stefan Richter   firewire: net: st...
289
290
  			fi2 = list_entry(fi->fi_link.next,
  					 struct fwnet_fragment_info, fi_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
291
  			if (fi->offset + fi->len == fi2->offset) {
c76acec6d   Jay Fenlason   firewire: add IPv...
292
293
  				/* glue fragments together */
  				fi->len += len + fi2->len;
f91e3bd84   Stefan Richter   firewire: net: st...
294
  				list_del(&fi2->fi_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
295
296
  				kfree(fi2);
  			} else {
c76acec6d   Jay Fenlason   firewire: add IPv...
297
298
  				fi->len += len;
  			}
f91e3bd84   Stefan Richter   firewire: net: st...
299

c76acec6d   Jay Fenlason   firewire: add IPv...
300
301
302
303
304
  			return fi;
  		}
  		if (offset + len == fi->offset) {
  			/* The new fragment can be tacked on to the beginning */
  			/* Did the new fragment plug a hole? */
f91e3bd84   Stefan Richter   firewire: net: st...
305
306
  			fi2 = list_entry(fi->fi_link.prev,
  					 struct fwnet_fragment_info, fi_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
307
308
  			if (fi2->offset + fi2->len == fi->offset) {
  				/* glue fragments together */
c76acec6d   Jay Fenlason   firewire: add IPv...
309
  				fi2->len += fi->len + len;
f91e3bd84   Stefan Richter   firewire: net: st...
310
  				list_del(&fi->fi_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
311
  				kfree(fi);
f91e3bd84   Stefan Richter   firewire: net: st...
312

c76acec6d   Jay Fenlason   firewire: add IPv...
313
314
  				return fi2;
  			}
c76acec6d   Jay Fenlason   firewire: add IPv...
315
316
  			fi->offset = offset;
  			fi->len += len;
f91e3bd84   Stefan Richter   firewire: net: st...
317

c76acec6d   Jay Fenlason   firewire: add IPv...
318
319
320
  			return fi;
  		}
  		if (offset > fi->offset + fi->len) {
f91e3bd84   Stefan Richter   firewire: net: st...
321
  			list = &fi->fi_link;
c76acec6d   Jay Fenlason   firewire: add IPv...
322
323
324
  			break;
  		}
  		if (offset + len < fi->offset) {
f91e3bd84   Stefan Richter   firewire: net: st...
325
  			list = fi->fi_link.prev;
c76acec6d   Jay Fenlason   firewire: add IPv...
326
327
328
329
330
  			break;
  		}
  	}
  
  	new = kmalloc(sizeof(*new), GFP_ATOMIC);
cfb0c9d1f   Stefan Richter   firewire: remove ...
331
  	if (!new)
c76acec6d   Jay Fenlason   firewire: add IPv...
332
  		return NULL;
c76acec6d   Jay Fenlason   firewire: add IPv...
333
334
335
  
  	new->offset = offset;
  	new->len = len;
f91e3bd84   Stefan Richter   firewire: net: st...
336
  	list_add(&new->fi_link, list);
c76acec6d   Jay Fenlason   firewire: add IPv...
337
338
  	return new;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
339
340
341
342
343
344
  static struct fwnet_partial_datagram *fwnet_pd_new(struct net_device *net,
  		struct fwnet_peer *peer, u16 datagram_label, unsigned dg_size,
  		void *frag_buf, unsigned frag_off, unsigned frag_len)
  {
  	struct fwnet_partial_datagram *new;
  	struct fwnet_fragment_info *fi;
c76acec6d   Jay Fenlason   firewire: add IPv...
345
346
347
348
  
  	new = kmalloc(sizeof(*new), GFP_ATOMIC);
  	if (!new)
  		goto fail;
f91e3bd84   Stefan Richter   firewire: net: st...
349
350
351
352
  
  	INIT_LIST_HEAD(&new->fi_list);
  	fi = fwnet_frag_new(new, frag_off, frag_len);
  	if (fi == NULL)
c76acec6d   Jay Fenlason   firewire: add IPv...
353
  		goto fail_w_new;
f91e3bd84   Stefan Richter   firewire: net: st...
354

c76acec6d   Jay Fenlason   firewire: add IPv...
355
356
  	new->datagram_label = datagram_label;
  	new->datagram_size = dg_size;
825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
357
  	new->skb = dev_alloc_skb(dg_size + LL_RESERVED_SPACE(net));
f91e3bd84   Stefan Richter   firewire: net: st...
358
  	if (new->skb == NULL)
c76acec6d   Jay Fenlason   firewire: add IPv...
359
  		goto fail_w_fi;
f91e3bd84   Stefan Richter   firewire: net: st...
360

825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
361
  	skb_reserve(new->skb, LL_RESERVED_SPACE(net));
c76acec6d   Jay Fenlason   firewire: add IPv...
362
363
  	new->pbuf = skb_put(new->skb, dg_size);
  	memcpy(new->pbuf + frag_off, frag_buf, frag_len);
f91e3bd84   Stefan Richter   firewire: net: st...
364
  	list_add_tail(&new->pd_link, &peer->pd_list);
c76acec6d   Jay Fenlason   firewire: add IPv...
365
366
367
368
369
370
371
  	return new;
  
  fail_w_fi:
  	kfree(fi);
  fail_w_new:
  	kfree(new);
  fail:
c76acec6d   Jay Fenlason   firewire: add IPv...
372
373
  	return NULL;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
374
375
376
377
  static struct fwnet_partial_datagram *fwnet_pd_find(struct fwnet_peer *peer,
  						    u16 datagram_label)
  {
  	struct fwnet_partial_datagram *pd;
c76acec6d   Jay Fenlason   firewire: add IPv...
378

f91e3bd84   Stefan Richter   firewire: net: st...
379
380
  	list_for_each_entry(pd, &peer->pd_list, pd_link)
  		if (pd->datagram_label == datagram_label)
c76acec6d   Jay Fenlason   firewire: add IPv...
381
  			return pd;
f91e3bd84   Stefan Richter   firewire: net: st...
382

c76acec6d   Jay Fenlason   firewire: add IPv...
383
384
  	return NULL;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
385
386
387
  static void fwnet_pd_delete(struct fwnet_partial_datagram *old)
  {
  	struct fwnet_fragment_info *fi, *n;
c76acec6d   Jay Fenlason   firewire: add IPv...
388

f91e3bd84   Stefan Richter   firewire: net: st...
389
  	list_for_each_entry_safe(fi, n, &old->fi_list, fi_link)
c76acec6d   Jay Fenlason   firewire: add IPv...
390
  		kfree(fi);
f91e3bd84   Stefan Richter   firewire: net: st...
391
392
  
  	list_del(&old->pd_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
393
394
395
  	dev_kfree_skb_any(old->skb);
  	kfree(old);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
396
397
398
399
400
  static bool fwnet_pd_update(struct fwnet_peer *peer,
  		struct fwnet_partial_datagram *pd, void *frag_buf,
  		unsigned frag_off, unsigned frag_len)
  {
  	if (fwnet_frag_new(pd, frag_off, frag_len) == NULL)
c76acec6d   Jay Fenlason   firewire: add IPv...
401
  		return false;
f91e3bd84   Stefan Richter   firewire: net: st...
402

c76acec6d   Jay Fenlason   firewire: add IPv...
403
404
405
  	memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
  
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
406
  	 * Move list entry to beginning of list so that oldest partial
c76acec6d   Jay Fenlason   firewire: add IPv...
407
408
  	 * datagrams percolate to the end of the list
  	 */
f91e3bd84   Stefan Richter   firewire: net: st...
409
  	list_move_tail(&pd->pd_link, &peer->pd_list);
c76acec6d   Jay Fenlason   firewire: add IPv...
410
411
  	return true;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
412
413
414
  static bool fwnet_pd_is_complete(struct fwnet_partial_datagram *pd)
  {
  	struct fwnet_fragment_info *fi;
c76acec6d   Jay Fenlason   firewire: add IPv...
415

f91e3bd84   Stefan Richter   firewire: net: st...
416
  	fi = list_entry(pd->fi_list.next, struct fwnet_fragment_info, fi_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
417

f91e3bd84   Stefan Richter   firewire: net: st...
418
  	return fi->len == pd->datagram_size;
c76acec6d   Jay Fenlason   firewire: add IPv...
419
  }
5a124d382   Stefan Richter   firewire: net: al...
420
  /* caller must hold dev->lock */
f91e3bd84   Stefan Richter   firewire: net: st...
421
422
423
  static struct fwnet_peer *fwnet_peer_find_by_guid(struct fwnet_device *dev,
  						  u64 guid)
  {
5a124d382   Stefan Richter   firewire: net: al...
424
  	struct fwnet_peer *peer;
c76acec6d   Jay Fenlason   firewire: add IPv...
425

5a124d382   Stefan Richter   firewire: net: al...
426
427
428
  	list_for_each_entry(peer, &dev->peer_list, peer_link)
  		if (peer->guid == guid)
  			return peer;
c76acec6d   Jay Fenlason   firewire: add IPv...
429

5a124d382   Stefan Richter   firewire: net: al...
430
  	return NULL;
c76acec6d   Jay Fenlason   firewire: add IPv...
431
  }
5a124d382   Stefan Richter   firewire: net: al...
432
  /* caller must hold dev->lock */
f91e3bd84   Stefan Richter   firewire: net: st...
433
  static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev,
5a124d382   Stefan Richter   firewire: net: al...
434
  						int node_id, int generation)
f91e3bd84   Stefan Richter   firewire: net: st...
435
  {
5a124d382   Stefan Richter   firewire: net: al...
436
  	struct fwnet_peer *peer;
c76acec6d   Jay Fenlason   firewire: add IPv...
437

5a124d382   Stefan Richter   firewire: net: al...
438
439
440
441
  	list_for_each_entry(peer, &dev->peer_list, peer_link)
  		if (peer->node_id    == node_id &&
  		    peer->generation == generation)
  			return peer;
f91e3bd84   Stefan Richter   firewire: net: st...
442

5a124d382   Stefan Richter   firewire: net: al...
443
  	return NULL;
c76acec6d   Jay Fenlason   firewire: add IPv...
444
  }
5a124d382   Stefan Richter   firewire: net: al...
445
446
  /* See IEEE 1394-2008 table 6-4, table 8-8, table 16-18. */
  static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
f91e3bd84   Stefan Richter   firewire: net: st...
447
  {
5a124d382   Stefan Richter   firewire: net: al...
448
  	max_rec = min(max_rec, speed + 8);
4ec4a67aa   Stefan Richter   firewire: use cla...
449
  	max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */
5a124d382   Stefan Richter   firewire: net: al...
450
451
  
  	return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
452
  }
5a124d382   Stefan Richter   firewire: net: al...
453

f91e3bd84   Stefan Richter   firewire: net: st...
454
455
456
457
458
  static int fwnet_finish_incoming_packet(struct net_device *net,
  					struct sk_buff *skb, u16 source_node_id,
  					bool is_broadcast, u16 ether_type)
  {
  	struct fwnet_device *dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
459
  	int status;
f91e3bd84   Stefan Richter   firewire: net: st...
460
  	__be64 guid;
c76acec6d   Jay Fenlason   firewire: add IPv...
461

18406d7e4   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Acc...
462
463
464
  	switch (ether_type) {
  	case ETH_P_ARP:
  	case ETH_P_IP:
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
465
466
467
  #if IS_ENABLED(CONFIG_IPV6)
  	case ETH_P_IPV6:
  #endif
18406d7e4   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Acc...
468
469
470
471
  		break;
  	default:
  		goto err;
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
472
  	dev = netdev_priv(net);
c76acec6d   Jay Fenlason   firewire: add IPv...
473
  	/* Write metadata, and then pass to the receive level */
f91e3bd84   Stefan Richter   firewire: net: st...
474
  	skb->dev = net;
b577d7e2a   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Ens...
475
  	skb->ip_summed = CHECKSUM_NONE;
c76acec6d   Jay Fenlason   firewire: add IPv...
476
477
478
  
  	/*
  	 * Parse the encapsulation header. This actually does the job of
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
479
  	 * converting to an ethernet-like pseudo frame header.
c76acec6d   Jay Fenlason   firewire: add IPv...
480
  	 */
f91e3bd84   Stefan Richter   firewire: net: st...
481
482
  	guid = cpu_to_be64(dev->card->guid);
  	if (dev_hard_header(skb, net, ether_type,
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
483
  			   is_broadcast ? net->broadcast : net->dev_addr,
f91e3bd84   Stefan Richter   firewire: net: st...
484
485
  			   NULL, skb->len) >= 0) {
  		struct fwnet_header *eth;
c76acec6d   Jay Fenlason   firewire: add IPv...
486
487
488
489
490
  		u16 *rawp;
  		__be16 protocol;
  
  		skb_reset_mac_header(skb);
  		skb_pull(skb, sizeof(*eth));
f91e3bd84   Stefan Richter   firewire: net: st...
491
  		eth = (struct fwnet_header *)skb_mac_header(skb);
021b97e46   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Sen...
492
  		if (fwnet_hwaddr_is_multicast(eth->h_dest)) {
f91e3bd84   Stefan Richter   firewire: net: st...
493
494
  			if (memcmp(eth->h_dest, net->broadcast,
  				   net->addr_len) == 0)
c76acec6d   Jay Fenlason   firewire: add IPv...
495
  				skb->pkt_type = PACKET_BROADCAST;
c76acec6d   Jay Fenlason   firewire: add IPv...
496
497
498
499
500
  #if 0
  			else
  				skb->pkt_type = PACKET_MULTICAST;
  #endif
  		} else {
156ce867a   Stefan Richter   firewire: net: re...
501
  			if (memcmp(eth->h_dest, net->dev_addr, net->addr_len))
c76acec6d   Jay Fenlason   firewire: add IPv...
502
  				skb->pkt_type = PACKET_OTHERHOST;
c76acec6d   Jay Fenlason   firewire: add IPv...
503
  		}
e5c5d22e8   Simon Horman   net: add ETH_P_80...
504
  		if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN) {
c76acec6d   Jay Fenlason   firewire: add IPv...
505
506
507
  			protocol = eth->h_proto;
  		} else {
  			rawp = (u16 *)skb->data;
f91e3bd84   Stefan Richter   firewire: net: st...
508
  			if (*rawp == 0xffff)
c76acec6d   Jay Fenlason   firewire: add IPv...
509
  				protocol = htons(ETH_P_802_3);
f91e3bd84   Stefan Richter   firewire: net: st...
510
  			else
c76acec6d   Jay Fenlason   firewire: add IPv...
511
  				protocol = htons(ETH_P_802_2);
c76acec6d   Jay Fenlason   firewire: add IPv...
512
513
514
515
  		}
  		skb->protocol = protocol;
  	}
  	status = netif_rx(skb);
f91e3bd84   Stefan Richter   firewire: net: st...
516
517
518
  	if (status == NET_RX_DROP) {
  		net->stats.rx_errors++;
  		net->stats.rx_dropped++;
c76acec6d   Jay Fenlason   firewire: add IPv...
519
  	} else {
f91e3bd84   Stefan Richter   firewire: net: st...
520
521
  		net->stats.rx_packets++;
  		net->stats.rx_bytes += skb->len;
c76acec6d   Jay Fenlason   firewire: add IPv...
522
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
523

c76acec6d   Jay Fenlason   firewire: add IPv...
524
  	return 0;
18406d7e4   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Acc...
525
   err:
f91e3bd84   Stefan Richter   firewire: net: st...
526
527
  	net->stats.rx_errors++;
  	net->stats.rx_dropped++;
c76acec6d   Jay Fenlason   firewire: add IPv...
528
  	dev_kfree_skb_any(skb);
f91e3bd84   Stefan Richter   firewire: net: st...
529

1bf145fed   Stefan Richter   firewire: net: fi...
530
  	return -ENOENT;
c76acec6d   Jay Fenlason   firewire: add IPv...
531
  }
f91e3bd84   Stefan Richter   firewire: net: st...
532
  static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
5a124d382   Stefan Richter   firewire: net: al...
533
534
  				 int source_node_id, int generation,
  				 bool is_broadcast)
f91e3bd84   Stefan Richter   firewire: net: st...
535
  {
c76acec6d   Jay Fenlason   firewire: add IPv...
536
  	struct sk_buff *skb;
5a124d382   Stefan Richter   firewire: net: al...
537
  	struct net_device *net = dev->netdev;
f91e3bd84   Stefan Richter   firewire: net: st...
538
  	struct rfc2734_header hdr;
c76acec6d   Jay Fenlason   firewire: add IPv...
539
540
  	unsigned lf;
  	unsigned long flags;
f91e3bd84   Stefan Richter   firewire: net: st...
541
542
  	struct fwnet_peer *peer;
  	struct fwnet_partial_datagram *pd;
c76acec6d   Jay Fenlason   firewire: add IPv...
543
544
545
546
547
  	int fg_off;
  	int dg_size;
  	u16 datagram_label;
  	int retval;
  	u16 ether_type;
667121ace   Stefan Richter   firewire: net: gu...
548
549
  	if (len <= RFC2374_UNFRAG_HDR_SIZE)
  		return 0;
f91e3bd84   Stefan Richter   firewire: net: st...
550
551
552
  	hdr.w0 = be32_to_cpu(buf[0]);
  	lf = fwnet_get_hdr_lf(&hdr);
  	if (lf == RFC2374_HDR_UNFRAG) {
c76acec6d   Jay Fenlason   firewire: add IPv...
553
554
555
556
557
  		/*
  		 * An unfragmented datagram has been received by the ieee1394
  		 * bus. Build an skbuff around it so we can pass it to the
  		 * high level network layer.
  		 */
f91e3bd84   Stefan Richter   firewire: net: st...
558
  		ether_type = fwnet_get_hdr_ether_type(&hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
559
  		buf++;
f91e3bd84   Stefan Richter   firewire: net: st...
560
  		len -= RFC2374_UNFRAG_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
561

825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
562
  		skb = dev_alloc_skb(len + LL_RESERVED_SPACE(net));
c76acec6d   Jay Fenlason   firewire: add IPv...
563
  		if (unlikely(!skb)) {
f91e3bd84   Stefan Richter   firewire: net: st...
564
  			net->stats.rx_dropped++;
1bf145fed   Stefan Richter   firewire: net: fi...
565
  			return -ENOMEM;
c76acec6d   Jay Fenlason   firewire: add IPv...
566
  		}
825863408   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Use...
567
  		skb_reserve(skb, LL_RESERVED_SPACE(net));
59ae1d127   Johannes Berg   networking: intro...
568
  		skb_put_data(skb, buf, len);
f91e3bd84   Stefan Richter   firewire: net: st...
569
570
571
  
  		return fwnet_finish_incoming_packet(net, skb, source_node_id,
  						    is_broadcast, ether_type);
c76acec6d   Jay Fenlason   firewire: add IPv...
572
  	}
667121ace   Stefan Richter   firewire: net: gu...
573

c76acec6d   Jay Fenlason   firewire: add IPv...
574
  	/* A datagram fragment has been received, now the fun begins. */
667121ace   Stefan Richter   firewire: net: gu...
575
576
577
  
  	if (len <= RFC2374_FRAG_HDR_SIZE)
  		return 0;
c76acec6d   Jay Fenlason   firewire: add IPv...
578
  	hdr.w1 = ntohl(buf[1]);
f91e3bd84   Stefan Richter   firewire: net: st...
579
580
581
582
  	buf += 2;
  	len -= RFC2374_FRAG_HDR_SIZE;
  	if (lf == RFC2374_HDR_FIRSTFRAG) {
  		ether_type = fwnet_get_hdr_ether_type(&hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
583
584
  		fg_off = 0;
  	} else {
f91e3bd84   Stefan Richter   firewire: net: st...
585
586
  		ether_type = 0;
  		fg_off = fwnet_get_hdr_fg_off(&hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
587
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
588
  	datagram_label = fwnet_get_hdr_dgl(&hdr);
e9300a4b7   Stefan Richter   firewire: net: fi...
589
  	dg_size = fwnet_get_hdr_dg_size(&hdr);
f91e3bd84   Stefan Richter   firewire: net: st...
590

667121ace   Stefan Richter   firewire: net: gu...
591
592
  	if (fg_off + len > dg_size)
  		return 0;
f91e3bd84   Stefan Richter   firewire: net: st...
593

5a124d382   Stefan Richter   firewire: net: al...
594
595
596
  	spin_lock_irqsave(&dev->lock, flags);
  
  	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
1bf145fed   Stefan Richter   firewire: net: fi...
597
598
599
600
  	if (!peer) {
  		retval = -ENOENT;
  		goto fail;
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
601
602
  
  	pd = fwnet_pd_find(peer, datagram_label);
c76acec6d   Jay Fenlason   firewire: add IPv...
603
  	if (pd == NULL) {
f91e3bd84   Stefan Richter   firewire: net: st...
604
  		while (peer->pdg_size >= FWNET_MAX_FRAGMENTS) {
c76acec6d   Jay Fenlason   firewire: add IPv...
605
  			/* remove the oldest */
f91e3bd84   Stefan Richter   firewire: net: st...
606
607
608
  			fwnet_pd_delete(list_first_entry(&peer->pd_list,
  				struct fwnet_partial_datagram, pd_link));
  			peer->pdg_size--;
c76acec6d   Jay Fenlason   firewire: add IPv...
609
  		}
f91e3bd84   Stefan Richter   firewire: net: st...
610
611
612
  		pd = fwnet_pd_new(net, peer, datagram_label,
  				  dg_size, buf, fg_off, len);
  		if (pd == NULL) {
c76acec6d   Jay Fenlason   firewire: add IPv...
613
  			retval = -ENOMEM;
1bf145fed   Stefan Richter   firewire: net: fi...
614
  			goto fail;
c76acec6d   Jay Fenlason   firewire: add IPv...
615
  		}
f91e3bd84   Stefan Richter   firewire: net: st...
616
  		peer->pdg_size++;
c76acec6d   Jay Fenlason   firewire: add IPv...
617
  	} else {
f91e3bd84   Stefan Richter   firewire: net: st...
618
619
  		if (fwnet_frag_overlap(pd, fg_off, len) ||
  		    pd->datagram_size != dg_size) {
c76acec6d   Jay Fenlason   firewire: add IPv...
620
621
  			/*
  			 * Differing datagram sizes or overlapping fragments,
f91e3bd84   Stefan Richter   firewire: net: st...
622
  			 * discard old datagram and start a new one.
c76acec6d   Jay Fenlason   firewire: add IPv...
623
  			 */
f91e3bd84   Stefan Richter   firewire: net: st...
624
625
626
627
  			fwnet_pd_delete(pd);
  			pd = fwnet_pd_new(net, peer, datagram_label,
  					  dg_size, buf, fg_off, len);
  			if (pd == NULL) {
f91e3bd84   Stefan Richter   firewire: net: st...
628
  				peer->pdg_size--;
1bf145fed   Stefan Richter   firewire: net: fi...
629
630
  				retval = -ENOMEM;
  				goto fail;
c76acec6d   Jay Fenlason   firewire: add IPv...
631
632
  			}
  		} else {
f91e3bd84   Stefan Richter   firewire: net: st...
633
  			if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
c76acec6d   Jay Fenlason   firewire: add IPv...
634
635
636
637
638
  				/*
  				 * Couldn't save off fragment anyway
  				 * so might as well obliterate the
  				 * datagram now.
  				 */
f91e3bd84   Stefan Richter   firewire: net: st...
639
640
  				fwnet_pd_delete(pd);
  				peer->pdg_size--;
1bf145fed   Stefan Richter   firewire: net: fi...
641
642
  				retval = -ENOMEM;
  				goto fail;
c76acec6d   Jay Fenlason   firewire: add IPv...
643
644
645
  			}
  		}
  	} /* new datagram or add to existing one */
f91e3bd84   Stefan Richter   firewire: net: st...
646
  	if (lf == RFC2374_HDR_FIRSTFRAG)
c76acec6d   Jay Fenlason   firewire: add IPv...
647
  		pd->ether_type = ether_type;
f91e3bd84   Stefan Richter   firewire: net: st...
648
649
  
  	if (fwnet_pd_is_complete(pd)) {
c76acec6d   Jay Fenlason   firewire: add IPv...
650
  		ether_type = pd->ether_type;
f91e3bd84   Stefan Richter   firewire: net: st...
651
  		peer->pdg_size--;
c76acec6d   Jay Fenlason   firewire: add IPv...
652
  		skb = skb_get(pd->skb);
f91e3bd84   Stefan Richter   firewire: net: st...
653
  		fwnet_pd_delete(pd);
5a124d382   Stefan Richter   firewire: net: al...
654
  		spin_unlock_irqrestore(&dev->lock, flags);
f91e3bd84   Stefan Richter   firewire: net: st...
655
656
657
  
  		return fwnet_finish_incoming_packet(net, skb, source_node_id,
  						    false, ether_type);
c76acec6d   Jay Fenlason   firewire: add IPv...
658
659
660
661
662
  	}
  	/*
  	 * Datagram is not complete, we're done for the
  	 * moment.
  	 */
b2268830f   Stefan Richter   firewire: net: th...
663
  	retval = 0;
1bf145fed   Stefan Richter   firewire: net: fi...
664
   fail:
5a124d382   Stefan Richter   firewire: net: al...
665
  	spin_unlock_irqrestore(&dev->lock, flags);
f91e3bd84   Stefan Richter   firewire: net: st...
666

1bf145fed   Stefan Richter   firewire: net: fi...
667
  	return retval;
c76acec6d   Jay Fenlason   firewire: add IPv...
668
  }
f91e3bd84   Stefan Richter   firewire: net: st...
669
670
  static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
  		int tcode, int destination, int source, int generation,
33e553fe2   Stefan Richter   firewire: remove ...
671
672
  		unsigned long long offset, void *payload, size_t length,
  		void *callback_data)
f91e3bd84   Stefan Richter   firewire: net: st...
673
  {
00635b8ee   Stefan Richter   firewire: net: be...
674
675
  	struct fwnet_device *dev = callback_data;
  	int rcode;
c76acec6d   Jay Fenlason   firewire: add IPv...
676

00635b8ee   Stefan Richter   firewire: net: be...
677
678
  	if (destination == IEEE1394_ALL_NODES) {
  		kfree(r);
f91e3bd84   Stefan Richter   firewire: net: st...
679

c76acec6d   Jay Fenlason   firewire: add IPv...
680
681
  		return;
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
682

00635b8ee   Stefan Richter   firewire: net: be...
683
684
685
686
687
688
  	if (offset != dev->handler.offset)
  		rcode = RCODE_ADDRESS_ERROR;
  	else if (tcode != TCODE_WRITE_BLOCK_REQUEST)
  		rcode = RCODE_TYPE_ERROR;
  	else if (fwnet_incoming_packet(dev, payload, length,
  				       source, generation, false) != 0) {
8408dc1c1   Stefan Richter   firewire: net: us...
689
690
  		dev_err(&dev->netdev->dev, "incoming packet failure
  ");
00635b8ee   Stefan Richter   firewire: net: be...
691
692
693
  		rcode = RCODE_CONFLICT_ERROR;
  	} else
  		rcode = RCODE_COMPLETE;
f91e3bd84   Stefan Richter   firewire: net: st...
694

00635b8ee   Stefan Richter   firewire: net: be...
695
  	fw_send_response(card, r, rcode);
c76acec6d   Jay Fenlason   firewire: add IPv...
696
  }
667121ace   Stefan Richter   firewire: net: gu...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  static int gasp_source_id(__be32 *p)
  {
  	return be32_to_cpu(p[0]) >> 16;
  }
  
  static u32 gasp_specifier_id(__be32 *p)
  {
  	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
  	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
  }
  
  static u32 gasp_version(__be32 *p)
  {
  	return be32_to_cpu(p[1]) & 0xffffff;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
712
713
714
715
  static void fwnet_receive_broadcast(struct fw_iso_context *context,
  		u32 cycle, size_t header_length, void *header, void *data)
  {
  	struct fwnet_device *dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
716
  	struct fw_iso_packet packet;
f91e3bd84   Stefan Richter   firewire: net: st...
717
718
  	__be16 *hdr_ptr;
  	__be32 *buf_ptr;
c76acec6d   Jay Fenlason   firewire: add IPv...
719
720
  	int retval;
  	u32 length;
c76acec6d   Jay Fenlason   firewire: add IPv...
721
722
  	unsigned long offset;
  	unsigned long flags;
f91e3bd84   Stefan Richter   firewire: net: st...
723
  	dev = data;
c76acec6d   Jay Fenlason   firewire: add IPv...
724
  	hdr_ptr = header;
f91e3bd84   Stefan Richter   firewire: net: st...
725
726
727
728
729
730
731
732
733
734
  	length = be16_to_cpup(hdr_ptr);
  
  	spin_lock_irqsave(&dev->lock, flags);
  
  	offset = dev->rcv_buffer_size * dev->broadcast_rcv_next_ptr;
  	buf_ptr = dev->broadcast_rcv_buffer_ptrs[dev->broadcast_rcv_next_ptr++];
  	if (dev->broadcast_rcv_next_ptr == dev->num_broadcast_rcv_ptrs)
  		dev->broadcast_rcv_next_ptr = 0;
  
  	spin_unlock_irqrestore(&dev->lock, flags);
c76acec6d   Jay Fenlason   firewire: add IPv...
735

667121ace   Stefan Richter   firewire: net: gu...
736
737
738
  	if (length > IEEE1394_GASP_HDR_SIZE &&
  	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
  	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
739
  #if IS_ENABLED(CONFIG_IPV6)
667121ace   Stefan Richter   firewire: net: gu...
740
  	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
741
  #endif
667121ace   Stefan Richter   firewire: net: gu...
742
743
744
745
  	    ))
  		fwnet_incoming_packet(dev, buf_ptr + 2,
  				      length - IEEE1394_GASP_HDR_SIZE,
  				      gasp_source_id(buf_ptr),
9d2373420   Stephan Gatzka   firewire: net: Fi...
746
  				      context->card->generation, true);
f91e3bd84   Stefan Richter   firewire: net: st...
747
748
  
  	packet.payload_length = dev->rcv_buffer_size;
c76acec6d   Jay Fenlason   firewire: add IPv...
749
750
751
752
  	packet.interrupt = 1;
  	packet.skip = 0;
  	packet.tag = 3;
  	packet.sy = 0;
f91e3bd84   Stefan Richter   firewire: net: st...
753
754
755
  	packet.header_length = IEEE1394_GASP_HDR_SIZE;
  
  	spin_lock_irqsave(&dev->lock, flags);
c76acec6d   Jay Fenlason   firewire: add IPv...
756

f91e3bd84   Stefan Richter   firewire: net: st...
757
758
759
760
  	retval = fw_iso_context_queue(dev->broadcast_rcv_context, &packet,
  				      &dev->broadcast_rcv_buffer, offset);
  
  	spin_unlock_irqrestore(&dev->lock, flags);
13882a82e   Clemens Ladisch   firewire: optimiz...
761
762
763
  	if (retval >= 0)
  		fw_iso_context_queue_flush(dev->broadcast_rcv_context);
  	else
8408dc1c1   Stefan Richter   firewire: net: us...
764
765
  		dev_err(&dev->netdev->dev, "requeue failed
  ");
c76acec6d   Jay Fenlason   firewire: add IPv...
766
  }
f91e3bd84   Stefan Richter   firewire: net: st...
767
  static struct kmem_cache *fwnet_packet_task_cache;
110f82d7a   Stefan Richter   firewire: net: fi...
768
769
770
771
772
  static void fwnet_free_ptask(struct fwnet_packet_task *ptask)
  {
  	dev_kfree_skb_any(ptask->skb);
  	kmem_cache_free(fwnet_packet_task_cache, ptask);
  }
b2268830f   Stefan Richter   firewire: net: th...
773
774
775
776
777
778
  /* Caller must hold dev->lock. */
  static void dec_queued_datagrams(struct fwnet_device *dev)
  {
  	if (--dev->queued_datagrams == FWNET_MIN_QUEUED_DATAGRAMS)
  		netif_wake_queue(dev->netdev);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
779
780
781
782
  static int fwnet_send_packet(struct fwnet_packet_task *ptask);
  
  static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
  {
110f82d7a   Stefan Richter   firewire: net: fi...
783
  	struct fwnet_device *dev = ptask->dev;
902bca00d   Stefan Richter   firewire: net: co...
784
  	struct sk_buff *skb = ptask->skb;
c76acec6d   Jay Fenlason   firewire: add IPv...
785
  	unsigned long flags;
110f82d7a   Stefan Richter   firewire: net: fi...
786
  	bool free;
f91e3bd84   Stefan Richter   firewire: net: st...
787
788
  
  	spin_lock_irqsave(&dev->lock, flags);
f91e3bd84   Stefan Richter   firewire: net: st...
789

110f82d7a   Stefan Richter   firewire: net: fi...
790
791
792
  	ptask->outstanding_pkts--;
  
  	/* Check whether we or the networking TX soft-IRQ is last user. */
48553011c   Stefan Richter   firewire: net: re...
793
  	free = (ptask->outstanding_pkts == 0 && ptask->enqueued);
7ee11fa8d   Stefan Richter   firewire: net: fi...
794
  	if (free)
b2268830f   Stefan Richter   firewire: net: th...
795
  		dec_queued_datagrams(dev);
110f82d7a   Stefan Richter   firewire: net: fi...
796

902bca00d   Stefan Richter   firewire: net: co...
797
  	if (ptask->outstanding_pkts == 0) {
902bca00d   Stefan Richter   firewire: net: co...
798
799
800
  		dev->netdev->stats.tx_packets++;
  		dev->netdev->stats.tx_bytes += skb->len;
  	}
110f82d7a   Stefan Richter   firewire: net: fi...
801
802
  
  	spin_unlock_irqrestore(&dev->lock, flags);
f91e3bd84   Stefan Richter   firewire: net: st...
803
804
  
  	if (ptask->outstanding_pkts > 0) {
c76acec6d   Jay Fenlason   firewire: add IPv...
805
806
807
808
  		u16 dg_size;
  		u16 fg_off;
  		u16 datagram_label;
  		u16 lf;
c76acec6d   Jay Fenlason   firewire: add IPv...
809
810
  
  		/* Update the ptask to point to the next fragment and send it */
f91e3bd84   Stefan Richter   firewire: net: st...
811
  		lf = fwnet_get_hdr_lf(&ptask->hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
812
  		switch (lf) {
f91e3bd84   Stefan Richter   firewire: net: st...
813
814
  		case RFC2374_HDR_LASTFRAG:
  		case RFC2374_HDR_UNFRAG:
c76acec6d   Jay Fenlason   firewire: add IPv...
815
  		default:
8408dc1c1   Stefan Richter   firewire: net: us...
816
817
818
819
820
  			dev_err(&dev->netdev->dev,
  				"outstanding packet %x lf %x, header %x,%x
  ",
  				ptask->outstanding_pkts, lf, ptask->hdr.w0,
  				ptask->hdr.w1);
c76acec6d   Jay Fenlason   firewire: add IPv...
821
  			BUG();
f91e3bd84   Stefan Richter   firewire: net: st...
822
  		case RFC2374_HDR_FIRSTFRAG:
c76acec6d   Jay Fenlason   firewire: add IPv...
823
  			/* Set frag type here for future interior fragments */
f91e3bd84   Stefan Richter   firewire: net: st...
824
825
826
  			dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
  			fg_off = ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
  			datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
827
  			break;
f91e3bd84   Stefan Richter   firewire: net: st...
828
829
830
831
832
  		case RFC2374_HDR_INTFRAG:
  			dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
  			fg_off = fwnet_get_hdr_fg_off(&ptask->hdr)
  				  + ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
  			datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
c76acec6d   Jay Fenlason   firewire: add IPv...
833
834
  			break;
  		}
902bca00d   Stefan Richter   firewire: net: co...
835

9d2373420   Stephan Gatzka   firewire: net: Fi...
836
837
838
839
840
841
  		if (ptask->dest_node == IEEE1394_ALL_NODES) {
  			skb_pull(skb,
  				 ptask->max_payload + IEEE1394_GASP_HDR_SIZE);
  		} else {
  			skb_pull(skb, ptask->max_payload);
  		}
f91e3bd84   Stefan Richter   firewire: net: st...
842
843
844
  		if (ptask->outstanding_pkts > 1) {
  			fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
  					  dg_size, fg_off, datagram_label);
c76acec6d   Jay Fenlason   firewire: add IPv...
845
  		} else {
f91e3bd84   Stefan Richter   firewire: net: st...
846
847
848
  			fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_LASTFRAG,
  					  dg_size, fg_off, datagram_label);
  			ptask->max_payload = skb->len + RFC2374_FRAG_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
849
  		}
f91e3bd84   Stefan Richter   firewire: net: st...
850
  		fwnet_send_packet(ptask);
c76acec6d   Jay Fenlason   firewire: add IPv...
851
  	}
110f82d7a   Stefan Richter   firewire: net: fi...
852
853
854
  
  	if (free)
  		fwnet_free_ptask(ptask);
c76acec6d   Jay Fenlason   firewire: add IPv...
855
  }
7ee11fa8d   Stefan Richter   firewire: net: fi...
856
857
858
859
860
861
862
863
864
865
866
867
  static void fwnet_transmit_packet_failed(struct fwnet_packet_task *ptask)
  {
  	struct fwnet_device *dev = ptask->dev;
  	unsigned long flags;
  	bool free;
  
  	spin_lock_irqsave(&dev->lock, flags);
  
  	/* One fragment failed; don't try to send remaining fragments. */
  	ptask->outstanding_pkts = 0;
  
  	/* Check whether we or the networking TX soft-IRQ is last user. */
48553011c   Stefan Richter   firewire: net: re...
868
  	free = ptask->enqueued;
7ee11fa8d   Stefan Richter   firewire: net: fi...
869
  	if (free)
b2268830f   Stefan Richter   firewire: net: th...
870
  		dec_queued_datagrams(dev);
7ee11fa8d   Stefan Richter   firewire: net: fi...
871
872
873
874
875
876
877
878
879
  
  	dev->netdev->stats.tx_dropped++;
  	dev->netdev->stats.tx_errors++;
  
  	spin_unlock_irqrestore(&dev->lock, flags);
  
  	if (free)
  		fwnet_free_ptask(ptask);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
880
881
882
  static void fwnet_write_complete(struct fw_card *card, int rcode,
  				 void *payload, size_t length, void *data)
  {
c4d6fd40d   Maxim Levitsky   firewire: net: ra...
883
884
885
  	struct fwnet_packet_task *ptask = data;
  	static unsigned long j;
  	static int last_rcode, errors_skipped;
c76acec6d   Jay Fenlason   firewire: add IPv...
886

7ee11fa8d   Stefan Richter   firewire: net: fi...
887
  	if (rcode == RCODE_COMPLETE) {
f91e3bd84   Stefan Richter   firewire: net: st...
888
  		fwnet_transmit_packet_done(ptask);
7ee11fa8d   Stefan Richter   firewire: net: fi...
889
  	} else {
c4d6fd40d   Maxim Levitsky   firewire: net: ra...
890
  		if (printk_timed_ratelimit(&j,  1000) || rcode != last_rcode) {
8408dc1c1   Stefan Richter   firewire: net: us...
891
892
893
894
  			dev_err(&ptask->dev->netdev->dev,
  				"fwnet_write_complete failed: %x (skipped %d)
  ",
  				rcode, errors_skipped);
c4d6fd40d   Maxim Levitsky   firewire: net: ra...
895
896
897
  
  			errors_skipped = 0;
  			last_rcode = rcode;
898758336   Stefan Richter   firewire: net: fi...
898
  		} else {
c4d6fd40d   Maxim Levitsky   firewire: net: ra...
899
  			errors_skipped++;
898758336   Stefan Richter   firewire: net: fi...
900
901
  		}
  		fwnet_transmit_packet_failed(ptask);
7ee11fa8d   Stefan Richter   firewire: net: fi...
902
  	}
c76acec6d   Jay Fenlason   firewire: add IPv...
903
  }
f91e3bd84   Stefan Richter   firewire: net: st...
904
905
906
  static int fwnet_send_packet(struct fwnet_packet_task *ptask)
  {
  	struct fwnet_device *dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
907
  	unsigned tx_len;
f91e3bd84   Stefan Richter   firewire: net: st...
908
  	struct rfc2734_header *bufhdr;
c76acec6d   Jay Fenlason   firewire: add IPv...
909
  	unsigned long flags;
110f82d7a   Stefan Richter   firewire: net: fi...
910
  	bool free;
c76acec6d   Jay Fenlason   firewire: add IPv...
911

f91e3bd84   Stefan Richter   firewire: net: st...
912
  	dev = ptask->dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
913
  	tx_len = ptask->max_payload;
f91e3bd84   Stefan Richter   firewire: net: st...
914
915
  	switch (fwnet_get_hdr_lf(&ptask->hdr)) {
  	case RFC2374_HDR_UNFRAG:
d58ff3512   Johannes Berg   networking: make ...
916
  		bufhdr = skb_push(ptask->skb, RFC2374_UNFRAG_HDR_SIZE);
f91e3bd84   Stefan Richter   firewire: net: st...
917
  		put_unaligned_be32(ptask->hdr.w0, &bufhdr->w0);
c76acec6d   Jay Fenlason   firewire: add IPv...
918
  		break;
f91e3bd84   Stefan Richter   firewire: net: st...
919
920
921
  	case RFC2374_HDR_FIRSTFRAG:
  	case RFC2374_HDR_INTFRAG:
  	case RFC2374_HDR_LASTFRAG:
d58ff3512   Johannes Berg   networking: make ...
922
  		bufhdr = skb_push(ptask->skb, RFC2374_FRAG_HDR_SIZE);
f91e3bd84   Stefan Richter   firewire: net: st...
923
924
  		put_unaligned_be32(ptask->hdr.w0, &bufhdr->w0);
  		put_unaligned_be32(ptask->hdr.w1, &bufhdr->w1);
c76acec6d   Jay Fenlason   firewire: add IPv...
925
926
927
928
929
  		break;
  
  	default:
  		BUG();
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
930
931
  	if (ptask->dest_node == IEEE1394_ALL_NODES) {
  		u8 *p;
c76acec6d   Jay Fenlason   firewire: add IPv...
932
  		int generation;
f91e3bd84   Stefan Richter   firewire: net: st...
933
  		int node_id;
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
934
  		unsigned int sw_version;
c76acec6d   Jay Fenlason   firewire: add IPv...
935
936
  
  		/* ptask->generation may not have been set yet */
f91e3bd84   Stefan Richter   firewire: net: st...
937
  		generation = dev->card->generation;
c76acec6d   Jay Fenlason   firewire: add IPv...
938
  		smp_rmb();
f91e3bd84   Stefan Richter   firewire: net: st...
939
  		node_id = dev->card->node_id;
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
940
941
942
943
944
945
946
947
948
  		switch (ptask->skb->protocol) {
  		default:
  			sw_version = RFC2734_SW_VERSION;
  			break;
  #if IS_ENABLED(CONFIG_IPV6)
  		case htons(ETH_P_IPV6):
  			sw_version = RFC3146_SW_VERSION;
  #endif
  		}
9d2373420   Stephan Gatzka   firewire: net: Fi...
949
  		p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
f91e3bd84   Stefan Richter   firewire: net: st...
950
951
  		put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
  		put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
952
  						| sw_version, &p[4]);
f91e3bd84   Stefan Richter   firewire: net: st...
953
954
955
956
957
958
959
960
  
  		/* We should not transmit if broadcast_channel.valid == 0. */
  		fw_send_request(dev->card, &ptask->transaction,
  				TCODE_STREAM_DATA,
  				fw_stream_packet_destination_id(3,
  						IEEE1394_BROADCAST_CHANNEL, 0),
  				generation, SCODE_100, 0ULL, ptask->skb->data,
  				tx_len + 8, fwnet_write_complete, ptask);
f91e3bd84   Stefan Richter   firewire: net: st...
961
  		spin_lock_irqsave(&dev->lock, flags);
110f82d7a   Stefan Richter   firewire: net: fi...
962
963
  
  		/* If the AT tasklet already ran, we may be last user. */
48553011c   Stefan Richter   firewire: net: re...
964
  		free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
110f82d7a   Stefan Richter   firewire: net: fi...
965
  		if (!free)
48553011c   Stefan Richter   firewire: net: re...
966
967
  			ptask->enqueued = true;
  		else
b2268830f   Stefan Richter   firewire: net: th...
968
  			dec_queued_datagrams(dev);
110f82d7a   Stefan Richter   firewire: net: fi...
969

f91e3bd84   Stefan Richter   firewire: net: st...
970
  		spin_unlock_irqrestore(&dev->lock, flags);
110f82d7a   Stefan Richter   firewire: net: fi...
971
  		goto out;
c76acec6d   Jay Fenlason   firewire: add IPv...
972
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
973
974
975
976
977
  
  	fw_send_request(dev->card, &ptask->transaction,
  			TCODE_WRITE_BLOCK_REQUEST, ptask->dest_node,
  			ptask->generation, ptask->speed, ptask->fifo_addr,
  			ptask->skb->data, tx_len, fwnet_write_complete, ptask);
f91e3bd84   Stefan Richter   firewire: net: st...
978
  	spin_lock_irqsave(&dev->lock, flags);
110f82d7a   Stefan Richter   firewire: net: fi...
979
980
  
  	/* If the AT tasklet already ran, we may be last user. */
48553011c   Stefan Richter   firewire: net: re...
981
  	free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
110f82d7a   Stefan Richter   firewire: net: fi...
982
  	if (!free)
48553011c   Stefan Richter   firewire: net: re...
983
984
  		ptask->enqueued = true;
  	else
b2268830f   Stefan Richter   firewire: net: th...
985
  		dec_queued_datagrams(dev);
110f82d7a   Stefan Richter   firewire: net: fi...
986

f91e3bd84   Stefan Richter   firewire: net: st...
987
  	spin_unlock_irqrestore(&dev->lock, flags);
860e9538a   Florian Westphal   treewide: replace...
988
  	netif_trans_update(dev->netdev);
110f82d7a   Stefan Richter   firewire: net: fi...
989
990
991
   out:
  	if (free)
  		fwnet_free_ptask(ptask);
f91e3bd84   Stefan Richter   firewire: net: st...
992

c76acec6d   Jay Fenlason   firewire: add IPv...
993
994
  	return 0;
  }
9d39c90ab   YOSHIFUJI Hideaki   firewire net: Int...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  static void fwnet_fifo_stop(struct fwnet_device *dev)
  {
  	if (dev->local_fifo == FWNET_NO_FIFO_ADDR)
  		return;
  
  	fw_core_remove_address_handler(&dev->handler);
  	dev->local_fifo = FWNET_NO_FIFO_ADDR;
  }
  
  static int fwnet_fifo_start(struct fwnet_device *dev)
  {
  	int retval;
  
  	if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
  		return 0;
  
  	dev->handler.length = 4096;
  	dev->handler.address_callback = fwnet_receive_packet;
  	dev->handler.callback_data = dev;
  
  	retval = fw_core_add_address_handler(&dev->handler,
  					     &fw_high_memory_region);
  	if (retval < 0)
  		return retval;
  
  	dev->local_fifo = dev->handler.offset;
  
  	return 0;
  }
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  static void __fwnet_broadcast_stop(struct fwnet_device *dev)
  {
  	unsigned u;
  
  	if (dev->broadcast_state != FWNET_BROADCAST_ERROR) {
  		for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++)
  			kunmap(dev->broadcast_rcv_buffer.pages[u]);
  		fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
  	}
  	if (dev->broadcast_rcv_context) {
  		fw_iso_context_destroy(dev->broadcast_rcv_context);
  		dev->broadcast_rcv_context = NULL;
  	}
  	kfree(dev->broadcast_rcv_buffer_ptrs);
  	dev->broadcast_rcv_buffer_ptrs = NULL;
  	dev->broadcast_state = FWNET_BROADCAST_ERROR;
  }
  
  static void fwnet_broadcast_stop(struct fwnet_device *dev)
  {
  	if (dev->broadcast_state == FWNET_BROADCAST_ERROR)
  		return;
  	fw_iso_context_stop(dev->broadcast_rcv_context);
  	__fwnet_broadcast_stop(dev);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1049
1050
  static int fwnet_broadcast_start(struct fwnet_device *dev)
  {
c76acec6d   Jay Fenlason   firewire: add IPv...
1051
1052
1053
1054
1055
1056
  	struct fw_iso_context *context;
  	int retval;
  	unsigned num_packets;
  	unsigned max_receive;
  	struct fw_iso_packet packet;
  	unsigned long offset;
f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1057
  	void **ptrptr;
c76acec6d   Jay Fenlason   firewire: add IPv...
1058
  	unsigned u;
c76acec6d   Jay Fenlason   firewire: add IPv...
1059

2fbd8dfee   YOSHIFUJI Hideaki   firewire net: Che...
1060
1061
  	if (dev->broadcast_state != FWNET_BROADCAST_ERROR)
  		return 0;
f91e3bd84   Stefan Richter   firewire: net: st...
1062
1063
  	max_receive = 1U << (dev->card->max_receive + 1);
  	num_packets = (FWNET_ISO_PAGE_COUNT * PAGE_SIZE) / max_receive;
eac31d58c   YOSHIFUJI Hideaki   firewire net: All...
1064
1065
1066
  	ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
  	if (!ptrptr) {
  		retval = -ENOMEM;
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1067
  		goto failed;
eac31d58c   YOSHIFUJI Hideaki   firewire net: All...
1068
1069
  	}
  	dev->broadcast_rcv_buffer_ptrs = ptrptr;
f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1070
1071
1072
1073
1074
1075
  	context = fw_iso_context_create(dev->card, FW_ISO_CONTEXT_RECEIVE,
  					IEEE1394_BROADCAST_CHANNEL,
  					dev->card->link_speed, 8,
  					fwnet_receive_broadcast, dev);
  	if (IS_ERR(context)) {
  		retval = PTR_ERR(context);
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1076
  		goto failed;
f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1077
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
1078

f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1079
1080
1081
  	retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer, dev->card,
  				    FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE);
  	if (retval < 0)
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1082
1083
1084
  		goto failed;
  
  	dev->broadcast_state = FWNET_BROADCAST_STOPPED;
f91e3bd84   Stefan Richter   firewire: net: st...
1085

f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1086
1087
1088
  	for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) {
  		void *ptr;
  		unsigned v;
c76acec6d   Jay Fenlason   firewire: add IPv...
1089

f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1090
1091
1092
  		ptr = kmap(dev->broadcast_rcv_buffer.pages[u]);
  		for (v = 0; v < num_packets / FWNET_ISO_PAGE_COUNT; v++)
  			*ptrptr++ = (void *) ((char *)ptr + v * max_receive);
f91e3bd84   Stefan Richter   firewire: net: st...
1093
  	}
f2090594d   YOSHIFUJI Hideaki   firewire net: Omi...
1094
  	dev->broadcast_rcv_context = context;
c76acec6d   Jay Fenlason   firewire: add IPv...
1095
1096
1097
1098
1099
1100
  
  	packet.payload_length = max_receive;
  	packet.interrupt = 1;
  	packet.skip = 0;
  	packet.tag = 3;
  	packet.sy = 0;
f91e3bd84   Stefan Richter   firewire: net: st...
1101
  	packet.header_length = IEEE1394_GASP_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
1102
  	offset = 0;
f91e3bd84   Stefan Richter   firewire: net: st...
1103
1104
1105
1106
1107
  
  	for (u = 0; u < num_packets; u++) {
  		retval = fw_iso_context_queue(context, &packet,
  				&dev->broadcast_rcv_buffer, offset);
  		if (retval < 0)
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1108
  			goto failed;
f91e3bd84   Stefan Richter   firewire: net: st...
1109

c76acec6d   Jay Fenlason   firewire: add IPv...
1110
1111
  		offset += max_receive;
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
1112
1113
1114
1115
1116
1117
  	dev->num_broadcast_rcv_ptrs = num_packets;
  	dev->rcv_buffer_size = max_receive;
  	dev->broadcast_rcv_next_ptr = 0U;
  	retval = fw_iso_context_start(context, -1, 0,
  			FW_ISO_CONTEXT_MATCH_ALL_TAGS); /* ??? sync */
  	if (retval < 0)
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1118
  		goto failed;
f91e3bd84   Stefan Richter   firewire: net: st...
1119
1120
1121
1122
1123
  
  	/* FIXME: adjust it according to the min. speed of all known peers? */
  	dev->broadcast_xmt_max_payload = IEEE1394_MAX_PAYLOAD_S100
  			- IEEE1394_GASP_HDR_SIZE - RFC2374_UNFRAG_HDR_SIZE;
  	dev->broadcast_state = FWNET_BROADCAST_RUNNING;
c76acec6d   Jay Fenlason   firewire: add IPv...
1124
  	return 0;
111534cd7   YOSHIFUJI Hideaki   firewire net: Int...
1125
1126
   failed:
  	__fwnet_broadcast_stop(dev);
c76acec6d   Jay Fenlason   firewire: add IPv...
1127
1128
  	return retval;
  }
c16714704   Stefan Richter   firewire: net: se...
1129
1130
1131
1132
1133
1134
1135
  static void set_carrier_state(struct fwnet_device *dev)
  {
  	if (dev->peer_count > 1)
  		netif_carrier_on(dev->netdev);
  	else
  		netif_carrier_off(dev->netdev);
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1136
1137
1138
1139
  /* ifup */
  static int fwnet_open(struct net_device *net)
  {
  	struct fwnet_device *dev = netdev_priv(net);
c76acec6d   Jay Fenlason   firewire: add IPv...
1140
  	int ret;
2fbd8dfee   YOSHIFUJI Hideaki   firewire net: Che...
1141
1142
  	ret = fwnet_broadcast_start(dev);
  	if (ret)
382c4b409   YOSHIFUJI Hideaki / 吉藤英明   firewire net: All...
1143
  		return ret;
2fbd8dfee   YOSHIFUJI Hideaki   firewire net: Che...
1144

f91e3bd84   Stefan Richter   firewire: net: st...
1145
  	netif_start_queue(net);
c16714704   Stefan Richter   firewire: net: se...
1146
1147
1148
  	spin_lock_irq(&dev->lock);
  	set_carrier_state(dev);
  	spin_unlock_irq(&dev->lock);
c76acec6d   Jay Fenlason   firewire: add IPv...
1149
1150
  	return 0;
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1151
1152
  /* ifdown */
  static int fwnet_stop(struct net_device *net)
c76acec6d   Jay Fenlason   firewire: add IPv...
1153
  {
8559e7f06   YOSHIFUJI Hideaki   firewire net: Rel...
1154
  	struct fwnet_device *dev = netdev_priv(net);
f91e3bd84   Stefan Richter   firewire: net: st...
1155
  	netif_stop_queue(net);
8559e7f06   YOSHIFUJI Hideaki   firewire net: Rel...
1156
  	fwnet_broadcast_stop(dev);
c76acec6d   Jay Fenlason   firewire: add IPv...
1157

c76acec6d   Jay Fenlason   firewire: add IPv...
1158
1159
  	return 0;
  }
424efe9ca   Stephen Hemminger   netdev: convert p...
1160
  static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
c76acec6d   Jay Fenlason   firewire: add IPv...
1161
  {
f91e3bd84   Stefan Richter   firewire: net: st...
1162
1163
  	struct fwnet_header hdr_buf;
  	struct fwnet_device *dev = netdev_priv(net);
c76acec6d   Jay Fenlason   firewire: add IPv...
1164
1165
  	__be16 proto;
  	u16 dest_node;
c76acec6d   Jay Fenlason   firewire: add IPv...
1166
1167
1168
  	unsigned max_payload;
  	u16 dg_size;
  	u16 *datagram_label_ptr;
f91e3bd84   Stefan Richter   firewire: net: st...
1169
  	struct fwnet_packet_task *ptask;
5a124d382   Stefan Richter   firewire: net: al...
1170
1171
  	struct fwnet_peer *peer;
  	unsigned long flags;
c76acec6d   Jay Fenlason   firewire: add IPv...
1172

b2268830f   Stefan Richter   firewire: net: th...
1173
1174
1175
1176
1177
1178
1179
1180
  	spin_lock_irqsave(&dev->lock, flags);
  
  	/* Can this happen? */
  	if (netif_queue_stopped(dev->netdev)) {
  		spin_unlock_irqrestore(&dev->lock, flags);
  
  		return NETDEV_TX_BUSY;
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
1181
  	ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC);
c76acec6d   Jay Fenlason   firewire: add IPv...
1182
1183
1184
1185
1186
1187
1188
1189
  	if (ptask == NULL)
  		goto fail;
  
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (!skb)
  		goto fail;
  
  	/*
f91e3bd84   Stefan Richter   firewire: net: st...
1190
  	 * Make a copy of the driver-specific header.
c76acec6d   Jay Fenlason   firewire: add IPv...
1191
1192
1193
  	 * We might need to rebuild the header on tx failure.
  	 */
  	memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
c76acec6d   Jay Fenlason   firewire: add IPv...
1194
  	proto = hdr_buf.h_proto;
18406d7e4   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Acc...
1195
1196
1197
1198
  
  	switch (proto) {
  	case htons(ETH_P_ARP):
  	case htons(ETH_P_IP):
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1199
1200
1201
  #if IS_ENABLED(CONFIG_IPV6)
  	case htons(ETH_P_IPV6):
  #endif
18406d7e4   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Acc...
1202
1203
1204
1205
1206
1207
  		break;
  	default:
  		goto fail;
  	}
  
  	skb_pull(skb, sizeof(hdr_buf));
c76acec6d   Jay Fenlason   firewire: add IPv...
1208
1209
1210
1211
1212
1213
  	dg_size = skb->len;
  
  	/*
  	 * Set the transmission type for the packet.  ARP packets and IP
  	 * broadcast packets are sent via GASP.
  	 */
021b97e46   YOSHIFUJI Hideaki / 吉藤英明   firewire net: Sen...
1214
  	if (fwnet_hwaddr_is_multicast(hdr_buf.h_dest)) {
5a124d382   Stefan Richter   firewire: net: al...
1215
  		max_payload        = dev->broadcast_xmt_max_payload;
f91e3bd84   Stefan Richter   firewire: net: st...
1216
  		datagram_label_ptr = &dev->broadcast_xmt_datagramlabel;
5a124d382   Stefan Richter   firewire: net: al...
1217
1218
1219
1220
  		ptask->fifo_addr   = FWNET_NO_FIFO_ADDR;
  		ptask->generation  = 0;
  		ptask->dest_node   = IEEE1394_ALL_NODES;
  		ptask->speed       = SCODE_100;
c76acec6d   Jay Fenlason   firewire: add IPv...
1221
  	} else {
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1222
1223
  		union fwnet_hwaddr *ha = (union fwnet_hwaddr *)hdr_buf.h_dest;
  		__be64 guid = get_unaligned(&ha->uc.uniq_id);
c76acec6d   Jay Fenlason   firewire: add IPv...
1224
  		u8 generation;
f91e3bd84   Stefan Richter   firewire: net: st...
1225
  		peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1226
  		if (!peer)
b2268830f   Stefan Richter   firewire: net: th...
1227
  			goto fail;
c76acec6d   Jay Fenlason   firewire: add IPv...
1228

5a124d382   Stefan Richter   firewire: net: al...
1229
1230
1231
  		generation         = peer->generation;
  		dest_node          = peer->node_id;
  		max_payload        = peer->max_payload;
f91e3bd84   Stefan Richter   firewire: net: st...
1232
  		datagram_label_ptr = &peer->datagram_label;
c76acec6d   Jay Fenlason   firewire: add IPv...
1233

6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1234
  		ptask->fifo_addr   = fwnet_hwaddr_fifo(ha);
5a124d382   Stefan Richter   firewire: net: al...
1235
1236
1237
  		ptask->generation  = generation;
  		ptask->dest_node   = dest_node;
  		ptask->speed       = peer->speed;
c76acec6d   Jay Fenlason   firewire: add IPv...
1238
  	}
c76acec6d   Jay Fenlason   firewire: add IPv...
1239
1240
1241
  	ptask->hdr.w0 = 0;
  	ptask->hdr.w1 = 0;
  	ptask->skb = skb;
f91e3bd84   Stefan Richter   firewire: net: st...
1242
  	ptask->dev = dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
1243
  	/* Does it all fit in one packet? */
f91e3bd84   Stefan Richter   firewire: net: st...
1244
1245
  	if (dg_size <= max_payload) {
  		fwnet_make_uf_hdr(&ptask->hdr, ntohs(proto));
c76acec6d   Jay Fenlason   firewire: add IPv...
1246
  		ptask->outstanding_pkts = 1;
f91e3bd84   Stefan Richter   firewire: net: st...
1247
  		max_payload = dg_size + RFC2374_UNFRAG_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
1248
1249
  	} else {
  		u16 datagram_label;
f91e3bd84   Stefan Richter   firewire: net: st...
1250
  		max_payload -= RFC2374_FRAG_OVERHEAD;
c76acec6d   Jay Fenlason   firewire: add IPv...
1251
  		datagram_label = (*datagram_label_ptr)++;
f91e3bd84   Stefan Richter   firewire: net: st...
1252
1253
  		fwnet_make_ff_hdr(&ptask->hdr, ntohs(proto), dg_size,
  				  datagram_label);
c76acec6d   Jay Fenlason   firewire: add IPv...
1254
  		ptask->outstanding_pkts = DIV_ROUND_UP(dg_size, max_payload);
f91e3bd84   Stefan Richter   firewire: net: st...
1255
  		max_payload += RFC2374_FRAG_HDR_SIZE;
c76acec6d   Jay Fenlason   firewire: add IPv...
1256
  	}
5a124d382   Stefan Richter   firewire: net: al...
1257

b2268830f   Stefan Richter   firewire: net: th...
1258
1259
  	if (++dev->queued_datagrams == FWNET_MAX_QUEUED_DATAGRAMS)
  		netif_stop_queue(dev->netdev);
48553011c   Stefan Richter   firewire: net: re...
1260

5a124d382   Stefan Richter   firewire: net: al...
1261
  	spin_unlock_irqrestore(&dev->lock, flags);
c76acec6d   Jay Fenlason   firewire: add IPv...
1262
  	ptask->max_payload = max_payload;
48553011c   Stefan Richter   firewire: net: re...
1263
  	ptask->enqueued    = 0;
110f82d7a   Stefan Richter   firewire: net: fi...
1264

f91e3bd84   Stefan Richter   firewire: net: st...
1265
  	fwnet_send_packet(ptask);
c76acec6d   Jay Fenlason   firewire: add IPv...
1266
1267
1268
  	return NETDEV_TX_OK;
  
   fail:
b2268830f   Stefan Richter   firewire: net: th...
1269
  	spin_unlock_irqrestore(&dev->lock, flags);
c76acec6d   Jay Fenlason   firewire: add IPv...
1270
  	if (ptask)
f91e3bd84   Stefan Richter   firewire: net: st...
1271
  		kmem_cache_free(fwnet_packet_task_cache, ptask);
c76acec6d   Jay Fenlason   firewire: add IPv...
1272
1273
1274
  
  	if (skb != NULL)
  		dev_kfree_skb(skb);
f91e3bd84   Stefan Richter   firewire: net: st...
1275
1276
  	net->stats.tx_dropped++;
  	net->stats.tx_errors++;
c76acec6d   Jay Fenlason   firewire: add IPv...
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  
  	/*
  	 * FIXME: According to a patch from 2003-02-26, "returning non-zero
  	 * causes serious problems" here, allegedly.  Before that patch,
  	 * -ERRNO was returned which is not appropriate under Linux 2.6.
  	 * Perhaps more needs to be done?  Stop the queue in serious
  	 * conditions and restart it elsewhere?
  	 */
  	return NETDEV_TX_OK;
  }
18bb36f9f   Maxim Levitsky   firewire: net: ad...
1287
1288
1289
  static const struct ethtool_ops fwnet_ethtool_ops = {
  	.get_link	= ethtool_op_get_link,
  };
f91e3bd84   Stefan Richter   firewire: net: st...
1290
1291
1292
1293
  static const struct net_device_ops fwnet_netdev_ops = {
  	.ndo_open       = fwnet_open,
  	.ndo_stop	= fwnet_stop,
  	.ndo_start_xmit = fwnet_tx,
c76acec6d   Jay Fenlason   firewire: add IPv...
1294
  };
f91e3bd84   Stefan Richter   firewire: net: st...
1295
1296
1297
1298
  static void fwnet_init_dev(struct net_device *net)
  {
  	net->header_ops		= &fwnet_header_ops;
  	net->netdev_ops		= &fwnet_netdev_ops;
1337f8535   Stefan Richter   firewire: net: ad...
1299
  	net->watchdog_timeo	= 2 * HZ;
f91e3bd84   Stefan Richter   firewire: net: st...
1300
1301
1302
1303
1304
  	net->flags		= IFF_BROADCAST | IFF_MULTICAST;
  	net->features		= NETIF_F_HIGHDMA;
  	net->addr_len		= FWNET_ALEN;
  	net->hard_header_len	= FWNET_HLEN;
  	net->type		= ARPHRD_IEEE1394;
b2268830f   Stefan Richter   firewire: net: th...
1305
  	net->tx_queue_len	= FWNET_TX_QUEUE_LEN;
18bb36f9f   Maxim Levitsky   firewire: net: ad...
1306
  	net->ethtool_ops	= &fwnet_ethtool_ops;
c76acec6d   Jay Fenlason   firewire: add IPv...
1307
  }
5a124d382   Stefan Richter   firewire: net: al...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
  /* caller must hold fwnet_device_mutex */
  static struct fwnet_device *fwnet_dev_find(struct fw_card *card)
  {
  	struct fwnet_device *dev;
  
  	list_for_each_entry(dev, &fwnet_device_list, dev_link)
  		if (dev->card == card)
  			return dev;
  
  	return NULL;
  }
  
  static int fwnet_add_peer(struct fwnet_device *dev,
  			  struct fw_unit *unit, struct fw_device *device)
  {
  	struct fwnet_peer *peer;
  
  	peer = kmalloc(sizeof(*peer), GFP_KERNEL);
  	if (!peer)
  		return -ENOMEM;
b01b4babb   Stefan Richter   firewire: net: fi...
1328
  	dev_set_drvdata(&unit->device, peer);
5a124d382   Stefan Richter   firewire: net: al...
1329
1330
  	peer->dev = dev;
  	peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
5a124d382   Stefan Richter   firewire: net: al...
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
  	INIT_LIST_HEAD(&peer->pd_list);
  	peer->pdg_size = 0;
  	peer->datagram_label = 0;
  	peer->speed = device->max_speed;
  	peer->max_payload = fwnet_max_payload(device->max_rec, peer->speed);
  
  	peer->generation = device->generation;
  	smp_rmb();
  	peer->node_id = device->node_id;
  
  	spin_lock_irq(&dev->lock);
  	list_add_tail(&peer->peer_link, &dev->peer_list);
18bb36f9f   Maxim Levitsky   firewire: net: ad...
1343
  	dev->peer_count++;
c16714704   Stefan Richter   firewire: net: se...
1344
  	set_carrier_state(dev);
5a124d382   Stefan Richter   firewire: net: al...
1345
1346
1347
1348
  	spin_unlock_irq(&dev->lock);
  
  	return 0;
  }
94a87157c   Stefan Richter   firewire: introdu...
1349
1350
  static int fwnet_probe(struct fw_unit *unit,
  		       const struct ieee1394_device_id *id)
f91e3bd84   Stefan Richter   firewire: net: st...
1351
  {
f91e3bd84   Stefan Richter   firewire: net: st...
1352
1353
1354
  	struct fw_device *device = fw_parent_device(unit);
  	struct fw_card *card = device->card;
  	struct net_device *net;
b01b4babb   Stefan Richter   firewire: net: fi...
1355
  	bool allocated_netdev = false;
f91e3bd84   Stefan Richter   firewire: net: st...
1356
  	struct fwnet_device *dev;
5a124d382   Stefan Richter   firewire: net: al...
1357
  	int ret;
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1358
  	union fwnet_hwaddr *ha;
c76acec6d   Jay Fenlason   firewire: add IPv...
1359

5a124d382   Stefan Richter   firewire: net: al...
1360
  	mutex_lock(&fwnet_device_mutex);
c76acec6d   Jay Fenlason   firewire: add IPv...
1361

5a124d382   Stefan Richter   firewire: net: al...
1362
1363
  	dev = fwnet_dev_find(card);
  	if (dev) {
5a124d382   Stefan Richter   firewire: net: al...
1364
1365
  		net = dev->netdev;
  		goto have_dev;
c76acec6d   Jay Fenlason   firewire: add IPv...
1366
  	}
5a124d382   Stefan Richter   firewire: net: al...
1367

c835a6773   Tom Gundersen   net: set name_ass...
1368
1369
  	net = alloc_netdev(sizeof(*dev), "firewire%d", NET_NAME_UNKNOWN,
  			   fwnet_init_dev);
f91e3bd84   Stefan Richter   firewire: net: st...
1370
  	if (net == NULL) {
1118f8d04   Daeseok Youn   firewire: net: fi...
1371
1372
  		mutex_unlock(&fwnet_device_mutex);
  		return -ENOMEM;
c76acec6d   Jay Fenlason   firewire: add IPv...
1373
  	}
b01b4babb   Stefan Richter   firewire: net: fi...
1374
  	allocated_netdev = true;
f91e3bd84   Stefan Richter   firewire: net: st...
1375
1376
  	SET_NETDEV_DEV(net, card->device);
  	dev = netdev_priv(net);
c76acec6d   Jay Fenlason   firewire: add IPv...
1377

f91e3bd84   Stefan Richter   firewire: net: st...
1378
1379
1380
1381
1382
  	spin_lock_init(&dev->lock);
  	dev->broadcast_state = FWNET_BROADCAST_ERROR;
  	dev->broadcast_rcv_context = NULL;
  	dev->broadcast_xmt_max_payload = 0;
  	dev->broadcast_xmt_datagramlabel = 0;
f91e3bd84   Stefan Richter   firewire: net: st...
1383
  	dev->local_fifo = FWNET_NO_FIFO_ADDR;
48553011c   Stefan Richter   firewire: net: re...
1384
  	dev->queued_datagrams = 0;
5a124d382   Stefan Richter   firewire: net: al...
1385
  	INIT_LIST_HEAD(&dev->peer_list);
f91e3bd84   Stefan Richter   firewire: net: st...
1386
  	dev->card = card;
5a124d382   Stefan Richter   firewire: net: al...
1387
  	dev->netdev = net;
c76acec6d   Jay Fenlason   firewire: add IPv...
1388

382c4b409   YOSHIFUJI Hideaki / 吉藤英明   firewire net: All...
1389
1390
1391
1392
  	ret = fwnet_fifo_start(dev);
  	if (ret < 0)
  		goto out;
  	dev->local_fifo = dev->handler.offset;
89ab88b01   Stefan Richter   firewire: net: se...
1393
  	net->mtu = 1500U;
b3e3893e1   Jarod Wilson   net: use core MTU...
1394
  	net->min_mtu = ETH_MIN_MTU;
357f4aae8   Stefan Richter   firewire: net: re...
1395
  	net->max_mtu = 0xfff;
c76acec6d   Jay Fenlason   firewire: add IPv...
1396
1397
  
  	/* Set our hardware address while we're at it */
6752c8db8   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1398
1399
1400
1401
1402
1403
1404
1405
  	ha = (union fwnet_hwaddr *)net->dev_addr;
  	put_unaligned_be64(card->guid, &ha->uc.uniq_id);
  	ha->uc.max_rec = dev->card->max_receive;
  	ha->uc.sspd = dev->card->link_speed;
  	put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
  	put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
  
  	memset(net->broadcast, -1, net->addr_len);
5a124d382   Stefan Richter   firewire: net: al...
1406
  	ret = register_netdev(net);
8408dc1c1   Stefan Richter   firewire: net: us...
1407
  	if (ret)
c76acec6d   Jay Fenlason   firewire: add IPv...
1408
  		goto out;
c76acec6d   Jay Fenlason   firewire: add IPv...
1409

5a124d382   Stefan Richter   firewire: net: al...
1410
  	list_add_tail(&dev->dev_link, &fwnet_device_list);
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1411
1412
  	dev_notice(&net->dev, "IP over IEEE 1394 on card %s
  ",
8408dc1c1   Stefan Richter   firewire: net: us...
1413
  		   dev_name(card->device));
5a124d382   Stefan Richter   firewire: net: al...
1414
1415
   have_dev:
  	ret = fwnet_add_peer(dev, unit, device);
b01b4babb   Stefan Richter   firewire: net: fi...
1416
  	if (ret && allocated_netdev) {
5a124d382   Stefan Richter   firewire: net: al...
1417
1418
  		unregister_netdev(net);
  		list_del(&dev->dev_link);
c76acec6d   Jay Fenlason   firewire: add IPv...
1419
   out:
382c4b409   YOSHIFUJI Hideaki / 吉藤英明   firewire net: All...
1420
  		fwnet_fifo_stop(dev);
f91e3bd84   Stefan Richter   firewire: net: st...
1421
  		free_netdev(net);
382c4b409   YOSHIFUJI Hideaki / 吉藤英明   firewire net: All...
1422
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
1423

5a124d382   Stefan Richter   firewire: net: al...
1424
1425
1426
1427
  	mutex_unlock(&fwnet_device_mutex);
  
  	return ret;
  }
94a87157c   Stefan Richter   firewire: introdu...
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
  /*
   * FIXME abort partially sent fragmented datagrams,
   * discard partially received fragmented datagrams
   */
  static void fwnet_update(struct fw_unit *unit)
  {
  	struct fw_device *device = fw_parent_device(unit);
  	struct fwnet_peer *peer = dev_get_drvdata(&unit->device);
  	int generation;
  
  	generation = device->generation;
  
  	spin_lock_irq(&peer->dev->lock);
  	peer->node_id    = device->node_id;
  	peer->generation = generation;
  	spin_unlock_irq(&peer->dev->lock);
  }
c16714704   Stefan Richter   firewire: net: se...
1445
  static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev)
5a124d382   Stefan Richter   firewire: net: al...
1446
1447
  {
  	struct fwnet_partial_datagram *pd, *pd_next;
c16714704   Stefan Richter   firewire: net: se...
1448
  	spin_lock_irq(&dev->lock);
5a124d382   Stefan Richter   firewire: net: al...
1449
  	list_del(&peer->peer_link);
c16714704   Stefan Richter   firewire: net: se...
1450
1451
1452
  	dev->peer_count--;
  	set_carrier_state(dev);
  	spin_unlock_irq(&dev->lock);
5a124d382   Stefan Richter   firewire: net: al...
1453
1454
1455
1456
1457
  
  	list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
  		fwnet_pd_delete(pd);
  
  	kfree(peer);
c76acec6d   Jay Fenlason   firewire: add IPv...
1458
  }
94a87157c   Stefan Richter   firewire: introdu...
1459
  static void fwnet_remove(struct fw_unit *unit)
f91e3bd84   Stefan Richter   firewire: net: st...
1460
  {
94a87157c   Stefan Richter   firewire: introdu...
1461
  	struct fwnet_peer *peer = dev_get_drvdata(&unit->device);
5a124d382   Stefan Richter   firewire: net: al...
1462
  	struct fwnet_device *dev = peer->dev;
f91e3bd84   Stefan Richter   firewire: net: st...
1463
  	struct net_device *net;
48553011c   Stefan Richter   firewire: net: re...
1464
  	int i;
f91e3bd84   Stefan Richter   firewire: net: st...
1465

5a124d382   Stefan Richter   firewire: net: al...
1466
  	mutex_lock(&fwnet_device_mutex);
c76acec6d   Jay Fenlason   firewire: add IPv...
1467

74a145049   Maxim Levitsky   firewire: net: in...
1468
  	net = dev->netdev;
74a145049   Maxim Levitsky   firewire: net: in...
1469

c16714704   Stefan Richter   firewire: net: se...
1470
  	fwnet_remove_peer(peer, dev);
18bb36f9f   Maxim Levitsky   firewire: net: ad...
1471

5a124d382   Stefan Richter   firewire: net: al...
1472
  	if (list_empty(&dev->peer_list)) {
f91e3bd84   Stefan Richter   firewire: net: st...
1473
  		unregister_netdev(net);
382c4b409   YOSHIFUJI Hideaki / 吉藤英明   firewire net: All...
1474
  		fwnet_fifo_stop(dev);
48553011c   Stefan Richter   firewire: net: re...
1475
1476
1477
  		for (i = 0; dev->queued_datagrams && i < 5; i++)
  			ssleep(1);
  		WARN_ON(dev->queued_datagrams);
b01b4babb   Stefan Richter   firewire: net: fi...
1478
  		list_del(&dev->dev_link);
f91e3bd84   Stefan Richter   firewire: net: st...
1479
  		free_netdev(net);
c76acec6d   Jay Fenlason   firewire: add IPv...
1480
  	}
f91e3bd84   Stefan Richter   firewire: net: st...
1481

5a124d382   Stefan Richter   firewire: net: al...
1482
  	mutex_unlock(&fwnet_device_mutex);
c76acec6d   Jay Fenlason   firewire: add IPv...
1483
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1484
1485
1486
1487
1488
1489
1490
  static const struct ieee1394_device_id fwnet_id_table[] = {
  	{
  		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
  				IEEE1394_MATCH_VERSION,
  		.specifier_id = IANA_SPECIFIER_ID,
  		.version      = RFC2734_SW_VERSION,
  	},
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1491
1492
1493
1494
1495
1496
1497
1498
  #if IS_ENABLED(CONFIG_IPV6)
  	{
  		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
  				IEEE1394_MATCH_VERSION,
  		.specifier_id = IANA_SPECIFIER_ID,
  		.version      = RFC3146_SW_VERSION,
  	},
  #endif
f91e3bd84   Stefan Richter   firewire: net: st...
1499
1500
1501
1502
  	{ }
  };
  
  static struct fw_driver fwnet_driver = {
c76acec6d   Jay Fenlason   firewire: add IPv...
1503
  	.driver = {
f91e3bd84   Stefan Richter   firewire: net: st...
1504
  		.owner  = THIS_MODULE,
59759ff6f   Stefan Richter   firewire: net: id...
1505
  		.name   = KBUILD_MODNAME,
f91e3bd84   Stefan Richter   firewire: net: st...
1506
  		.bus    = &fw_bus_type,
c76acec6d   Jay Fenlason   firewire: add IPv...
1507
  	},
94a87157c   Stefan Richter   firewire: introdu...
1508
  	.probe    = fwnet_probe,
f91e3bd84   Stefan Richter   firewire: net: st...
1509
  	.update   = fwnet_update,
94a87157c   Stefan Richter   firewire: introdu...
1510
  	.remove   = fwnet_remove,
f91e3bd84   Stefan Richter   firewire: net: st...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
  	.id_table = fwnet_id_table,
  };
  
  static const u32 rfc2374_unit_directory_data[] = {
  	0x00040000,	/* directory_length		*/
  	0x1200005e,	/* unit_specifier_id: IANA	*/
  	0x81000003,	/* textual descriptor offset	*/
  	0x13000001,	/* unit_sw_version: RFC 2734	*/
  	0x81000005,	/* textual descriptor offset	*/
  	0x00030000,	/* descriptor_length		*/
  	0x00000000,	/* text				*/
  	0x00000000,	/* minimal ASCII, en		*/
  	0x49414e41,	/* I A N A			*/
  	0x00030000,	/* descriptor_length		*/
  	0x00000000,	/* text				*/
  	0x00000000,	/* minimal ASCII, en		*/
  	0x49507634,	/* I P v 4			*/
  };
  
  static struct fw_descriptor rfc2374_unit_directory = {
  	.length = ARRAY_SIZE(rfc2374_unit_directory_data),
  	.key    = (CSR_DIRECTORY | CSR_UNIT) << 24,
  	.data   = rfc2374_unit_directory_data
c76acec6d   Jay Fenlason   firewire: add IPv...
1534
  };
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
  #if IS_ENABLED(CONFIG_IPV6)
  static const u32 rfc3146_unit_directory_data[] = {
  	0x00040000,	/* directory_length		*/
  	0x1200005e,	/* unit_specifier_id: IANA	*/
  	0x81000003,	/* textual descriptor offset	*/
  	0x13000002,	/* unit_sw_version: RFC 3146	*/
  	0x81000005,	/* textual descriptor offset	*/
  	0x00030000,	/* descriptor_length		*/
  	0x00000000,	/* text				*/
  	0x00000000,	/* minimal ASCII, en		*/
  	0x49414e41,	/* I A N A			*/
  	0x00030000,	/* descriptor_length		*/
  	0x00000000,	/* text				*/
  	0x00000000,	/* minimal ASCII, en		*/
  	0x49507636,	/* I P v 6			*/
  };
  
  static struct fw_descriptor rfc3146_unit_directory = {
  	.length = ARRAY_SIZE(rfc3146_unit_directory_data),
  	.key    = (CSR_DIRECTORY | CSR_UNIT) << 24,
  	.data   = rfc3146_unit_directory_data
  };
  #endif
f91e3bd84   Stefan Richter   firewire: net: st...
1558
1559
1560
1561
1562
1563
1564
  static int __init fwnet_init(void)
  {
  	int err;
  
  	err = fw_core_add_descriptor(&rfc2374_unit_directory);
  	if (err)
  		return err;
c76acec6d   Jay Fenlason   firewire: add IPv...
1565

cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1566
1567
1568
1569
1570
  #if IS_ENABLED(CONFIG_IPV6)
  	err = fw_core_add_descriptor(&rfc3146_unit_directory);
  	if (err)
  		goto out;
  #endif
f91e3bd84   Stefan Richter   firewire: net: st...
1571
1572
1573
1574
  	fwnet_packet_task_cache = kmem_cache_create("packet_task",
  			sizeof(struct fwnet_packet_task), 0, 0, NULL);
  	if (!fwnet_packet_task_cache) {
  		err = -ENOMEM;
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1575
  		goto out2;
f91e3bd84   Stefan Richter   firewire: net: st...
1576
1577
1578
1579
1580
1581
1582
  	}
  
  	err = driver_register(&fwnet_driver.driver);
  	if (!err)
  		return 0;
  
  	kmem_cache_destroy(fwnet_packet_task_cache);
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1583
1584
1585
  out2:
  #if IS_ENABLED(CONFIG_IPV6)
  	fw_core_remove_descriptor(&rfc3146_unit_directory);
f91e3bd84   Stefan Richter   firewire: net: st...
1586
  out:
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1587
  #endif
f91e3bd84   Stefan Richter   firewire: net: st...
1588
1589
1590
  	fw_core_remove_descriptor(&rfc2374_unit_directory);
  
  	return err;
c76acec6d   Jay Fenlason   firewire: add IPv...
1591
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1592
  module_init(fwnet_init);
c76acec6d   Jay Fenlason   firewire: add IPv...
1593

f91e3bd84   Stefan Richter   firewire: net: st...
1594
1595
1596
1597
  static void __exit fwnet_cleanup(void)
  {
  	driver_unregister(&fwnet_driver.driver);
  	kmem_cache_destroy(fwnet_packet_task_cache);
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1598
1599
1600
  #if IS_ENABLED(CONFIG_IPV6)
  	fw_core_remove_descriptor(&rfc3146_unit_directory);
  #endif
f91e3bd84   Stefan Richter   firewire: net: st...
1601
  	fw_core_remove_descriptor(&rfc2374_unit_directory);
c76acec6d   Jay Fenlason   firewire: add IPv...
1602
  }
f91e3bd84   Stefan Richter   firewire: net: st...
1603
  module_exit(fwnet_cleanup);
c76acec6d   Jay Fenlason   firewire: add IPv...
1604

f91e3bd84   Stefan Richter   firewire: net: st...
1605
  MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>");
cb6bf3550   YOSHIFUJI Hideaki / 吉藤英明   firewire net, ipv...
1606
  MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146");
f91e3bd84   Stefan Richter   firewire: net: st...
1607
1608
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);