Blame view

drivers/net/rionet.c 18.6 KB
f89efd523   Matt Porter   [PATCH] Add rapid...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * rionet - Ethernet driver over RapidIO messaging services
   *
   * Copyright 2005 MontaVista Software, Inc.
   * Matt Porter <mporter@kernel.crashing.org>
   *
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
  #include <linux/rio.h>
  #include <linux/rio_drv.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
f89efd523   Matt Porter   [PATCH] Add rapid...
20
21
22
23
24
25
26
  #include <linux/rio_ids.h>
  
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/skbuff.h>
  #include <linux/crc32.h>
  #include <linux/ethtool.h>
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
27
  #include <linux/reboot.h>
f89efd523   Matt Porter   [PATCH] Add rapid...
28
29
  
  #define DRV_NAME        "rionet"
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
30
  #define DRV_VERSION     "0.3"
f89efd523   Matt Porter   [PATCH] Add rapid...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  #define DRV_AUTHOR      "Matt Porter <mporter@kernel.crashing.org>"
  #define DRV_DESC        "Ethernet over RapidIO"
  
  MODULE_AUTHOR(DRV_AUTHOR);
  MODULE_DESCRIPTION(DRV_DESC);
  MODULE_LICENSE("GPL");
  
  #define RIONET_DEFAULT_MSGLEVEL \
  			(NETIF_MSG_DRV          | \
  			 NETIF_MSG_LINK         | \
  			 NETIF_MSG_RX_ERR       | \
  			 NETIF_MSG_TX_ERR)
  
  #define RIONET_DOORBELL_JOIN	0x1000
  #define RIONET_DOORBELL_LEAVE	0x1001
  
  #define RIONET_MAILBOX		0
  
  #define RIONET_TX_RING_SIZE	CONFIG_RIONET_TX_SIZE
  #define RIONET_RX_RING_SIZE	CONFIG_RIONET_RX_SIZE
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
51
  #define RIONET_MAX_NETS		8
92444bb36   Aurelien Jacquiot   rapidio/rionet: a...
52
53
  #define RIONET_MSG_SIZE         RIO_MAX_MSG_SIZE
  #define RIONET_MAX_MTU          (RIONET_MSG_SIZE - ETH_HLEN)
f89efd523   Matt Porter   [PATCH] Add rapid...
54
55
56
57
58
  
  struct rionet_private {
  	struct rio_mport *mport;
  	struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
  	struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
f89efd523   Matt Porter   [PATCH] Add rapid...
59
60
61
62
63
64
65
  	int rx_slot;
  	int tx_slot;
  	int tx_cnt;
  	int ack_slot;
  	spinlock_t lock;
  	spinlock_t tx_lock;
  	u32 msg_enable;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
66
  	bool open;
f89efd523   Matt Porter   [PATCH] Add rapid...
67
68
69
70
71
72
73
  };
  
  struct rionet_peer {
  	struct list_head node;
  	struct rio_dev *rdev;
  	struct resource *res;
  };
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
74
75
76
  struct rionet_net {
  	struct net_device *ndev;
  	struct list_head peers;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
77
  	spinlock_t lock;	/* net info access lock */
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
78
79
80
  	struct rio_dev **active;
  	int nact;	/* number of active peers */
  };
f89efd523   Matt Porter   [PATCH] Add rapid...
81

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
82
  static struct rionet_net nets[RIONET_MAX_NETS];
f89efd523   Matt Porter   [PATCH] Add rapid...
83

284fb68d0   Alexandre Bounine   rapidio: fix use ...
84
85
86
  #define is_rionet_capable(src_ops, dst_ops)			\
  			((src_ops & RIO_SRC_OPS_DATA_MSG) &&	\
  			 (dst_ops & RIO_DST_OPS_DATA_MSG) &&	\
f89efd523   Matt Porter   [PATCH] Add rapid...
87
88
89
  			 (src_ops & RIO_SRC_OPS_DOORBELL) &&	\
  			 (dst_ops & RIO_DST_OPS_DOORBELL))
  #define dev_rionet_capable(dev) \
284fb68d0   Alexandre Bounine   rapidio: fix use ...
90
  	is_rionet_capable(dev->src_ops, dev->dst_ops)
f89efd523   Matt Porter   [PATCH] Add rapid...
91

e0c87bd95   Alexandre Bounine   drivers/net/rione...
92
93
  #define RIONET_MAC_MATCH(x)	(!memcmp((x), "\00\01\00\01", 4))
  #define RIONET_GET_DESTID(x)	((*((u8 *)x + 4) << 8) | *((u8 *)x + 5))
f89efd523   Matt Porter   [PATCH] Add rapid...
94

f89efd523   Matt Porter   [PATCH] Add rapid...
95
96
97
98
  static int rionet_rx_clean(struct net_device *ndev)
  {
  	int i;
  	int error = 0;
4cf1653aa   Wang Chen   netdevice: safe c...
99
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
100
101
102
103
104
105
106
107
108
109
110
111
112
  	void *data;
  
  	i = rnet->rx_slot;
  
  	do {
  		if (!rnet->rx_skb[i])
  			continue;
  
  		if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
  			break;
  
  		rnet->rx_skb[i]->data = data;
  		skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
f89efd523   Matt Porter   [PATCH] Add rapid...
113
114
115
116
117
  		rnet->rx_skb[i]->protocol =
  		    eth_type_trans(rnet->rx_skb[i], ndev);
  		error = netif_rx(rnet->rx_skb[i]);
  
  		if (error == NET_RX_DROP) {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
118
  			ndev->stats.rx_dropped++;
f89efd523   Matt Porter   [PATCH] Add rapid...
119
  		} else {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
120
121
  			ndev->stats.rx_packets++;
  			ndev->stats.rx_bytes += RIO_MAX_MSG_SIZE;
f89efd523   Matt Porter   [PATCH] Add rapid...
122
123
124
125
126
127
128
129
130
131
  		}
  
  	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
  
  	return i;
  }
  
  static void rionet_rx_fill(struct net_device *ndev, int end)
  {
  	int i;
4cf1653aa   Wang Chen   netdevice: safe c...
132
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  
  	i = rnet->rx_slot;
  	do {
  		rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
  
  		if (!rnet->rx_skb[i])
  			break;
  
  		rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
  				   rnet->rx_skb[i]->data);
  	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
  
  	rnet->rx_slot = i;
  }
  
  static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
  			       struct rio_dev *rdev)
  {
4cf1653aa   Wang Chen   netdevice: safe c...
151
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
152
153
154
  
  	rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
  	rnet->tx_skb[rnet->tx_slot] = skb;
09f75cd7b   Jeff Garzik   [NET] drivers/net...
155
156
  	ndev->stats.tx_packets++;
  	ndev->stats.tx_bytes += skb->len;
f89efd523   Matt Porter   [PATCH] Add rapid...
157
158
159
160
161
162
163
164
  
  	if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
  		netif_stop_queue(ndev);
  
  	++rnet->tx_slot;
  	rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
  
  	if (netif_msg_tx_queued(rnet))
8df8a4753   David S. Miller   rionet: Remove po...
165
166
167
  		printk(KERN_INFO "%s: queued skb len %8.8x
  ", DRV_NAME,
  		       skb->len);
f89efd523   Matt Porter   [PATCH] Add rapid...
168
169
170
171
172
173
174
  
  	return 0;
  }
  
  static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
  {
  	int i;
4cf1653aa   Wang Chen   netdevice: safe c...
175
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
176
177
178
  	struct ethhdr *eth = (struct ethhdr *)skb->data;
  	u16 destid;
  	unsigned long flags;
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
179
  	int add_num = 1;
f89efd523   Matt Porter   [PATCH] Add rapid...
180

a6086a893   Florian Westphal   drivers: net: rem...
181
  	spin_lock_irqsave(&rnet->tx_lock, flags);
f89efd523   Matt Porter   [PATCH] Add rapid...
182

7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
183
  	if (is_multicast_ether_addr(eth->h_dest))
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
184
  		add_num = nets[rnet->mport->id].nact;
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
185
186
  
  	if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
f89efd523   Matt Porter   [PATCH] Add rapid...
187
188
189
190
191
192
193
  		netif_stop_queue(ndev);
  		spin_unlock_irqrestore(&rnet->tx_lock, flags);
  		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!
  ",
  		       ndev->name);
  		return NETDEV_TX_BUSY;
  	}
abfc89c7b   Tobias Klauser   net: rionet: Use ...
194
  	if (is_multicast_ether_addr(eth->h_dest)) {
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
195
  		int count = 0;
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
196

e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
197
198
  		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
  				i++)
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
199
  			if (nets[rnet->mport->id].active[i]) {
f89efd523   Matt Porter   [PATCH] Add rapid...
200
  				rionet_queue_tx_msg(skb, ndev,
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
201
  					nets[rnet->mport->id].active[i]);
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
202
  				if (count)
633547973   Reshetova, Elena   net: convert sk_b...
203
  					refcount_inc(&skb->users);
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
204
205
  				count++;
  			}
f89efd523   Matt Porter   [PATCH] Add rapid...
206
207
  	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
  		destid = RIONET_GET_DESTID(eth->h_dest);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
208
209
210
  		if (nets[rnet->mport->id].active[destid])
  			rionet_queue_tx_msg(skb, ndev,
  					nets[rnet->mport->id].active[destid]);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
211
212
213
214
215
216
217
  		else {
  			/*
  			 * If the target device was removed from the list of
  			 * active peers but we still have TX packets targeting
  			 * it just report sending a packet to the target
  			 * (without actual packet transfer).
  			 */
e6161d642   Alexandre Bounine   rapidio/rionet: r...
218
219
  			ndev->stats.tx_packets++;
  			ndev->stats.tx_bytes += skb->len;
720e0d05a   Pan Bian   rapidio/rionet: d...
220
  			dev_kfree_skb_any(skb);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
221
  		}
f89efd523   Matt Porter   [PATCH] Add rapid...
222
223
224
  	}
  
  	spin_unlock_irqrestore(&rnet->tx_lock, flags);
6ed106549   Patrick McHardy   net: use NETDEV_T...
225
  	return NETDEV_TX_OK;
f89efd523   Matt Porter   [PATCH] Add rapid...
226
227
228
229
230
231
  }
  
  static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
  			       u16 info)
  {
  	struct net_device *ndev = dev_id;
4cf1653aa   Wang Chen   netdevice: safe c...
232
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
233
  	struct rionet_peer *peer;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
234
  	unsigned char netid = rnet->mport->id;
f89efd523   Matt Porter   [PATCH] Add rapid...
235
236
237
238
239
  
  	if (netif_msg_intr(rnet))
  		printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
  		       DRV_NAME, sid, tid, info);
  	if (info == RIONET_DOORBELL_JOIN) {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
240
241
242
  		if (!nets[netid].active[sid]) {
  			spin_lock(&nets[netid].lock);
  			list_for_each_entry(peer, &nets[netid].peers, node) {
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
243
  				if (peer->rdev->destid == sid) {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
244
245
  					nets[netid].active[sid] = peer->rdev;
  					nets[netid].nact++;
7c4a6106d   Alexandre Bounine   rapidio/rionet: f...
246
  				}
f89efd523   Matt Porter   [PATCH] Add rapid...
247
  			}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
248
  			spin_unlock(&nets[netid].lock);
f89efd523   Matt Porter   [PATCH] Add rapid...
249
250
251
252
  			rio_mport_send_doorbell(mport, sid,
  						RIONET_DOORBELL_JOIN);
  		}
  	} else if (info == RIONET_DOORBELL_LEAVE) {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
253
254
255
256
257
258
  		spin_lock(&nets[netid].lock);
  		if (nets[netid].active[sid]) {
  			nets[netid].active[sid] = NULL;
  			nets[netid].nact--;
  		}
  		spin_unlock(&nets[netid].lock);
f89efd523   Matt Porter   [PATCH] Add rapid...
259
260
261
262
263
264
265
266
267
268
269
270
  	} else {
  		if (netif_msg_intr(rnet))
  			printk(KERN_WARNING "%s: unhandled doorbell
  ",
  			       DRV_NAME);
  	}
  }
  
  static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
  {
  	int n;
  	struct net_device *ndev = dev_id;
4cf1653aa   Wang Chen   netdevice: safe c...
271
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  
  	if (netif_msg_intr(rnet))
  		printk(KERN_INFO "%s: inbound message event, mbox %d slot %d
  ",
  		       DRV_NAME, mbox, slot);
  
  	spin_lock(&rnet->lock);
  	if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
  		rionet_rx_fill(ndev, n);
  	spin_unlock(&rnet->lock);
  }
  
  static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
  {
  	struct net_device *ndev = dev_id;
4cf1653aa   Wang Chen   netdevice: safe c...
287
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
288

36915976e   Aurelien Jacquiot   rapidio/rionet: f...
289
  	spin_lock(&rnet->tx_lock);
f89efd523   Matt Porter   [PATCH] Add rapid...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  
  	if (netif_msg_intr(rnet))
  		printk(KERN_INFO
  		       "%s: outbound message event, mbox %d slot %d
  ",
  		       DRV_NAME, mbox, slot);
  
  	while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
  		/* dma unmap single */
  		dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
  		rnet->tx_skb[rnet->ack_slot] = NULL;
  		++rnet->ack_slot;
  		rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
  		rnet->tx_cnt--;
  	}
  
  	if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
  		netif_wake_queue(ndev);
36915976e   Aurelien Jacquiot   rapidio/rionet: f...
308
  	spin_unlock(&rnet->tx_lock);
f89efd523   Matt Porter   [PATCH] Add rapid...
309
310
311
312
313
  }
  
  static int rionet_open(struct net_device *ndev)
  {
  	int i, rc = 0;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
314
  	struct rionet_peer *peer;
4cf1653aa   Wang Chen   netdevice: safe c...
315
  	struct rionet_private *rnet = netdev_priv(ndev);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
316
317
  	unsigned char netid = rnet->mport->id;
  	unsigned long flags;
f89efd523   Matt Porter   [PATCH] Add rapid...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
  
  	if (netif_msg_ifup(rnet))
  		printk(KERN_INFO "%s: open
  ", DRV_NAME);
  
  	if ((rc = rio_request_inb_dbell(rnet->mport,
  					(void *)ndev,
  					RIONET_DOORBELL_JOIN,
  					RIONET_DOORBELL_LEAVE,
  					rionet_dbell_event)) < 0)
  		goto out;
  
  	if ((rc = rio_request_inb_mbox(rnet->mport,
  				       (void *)ndev,
  				       RIONET_MAILBOX,
  				       RIONET_RX_RING_SIZE,
  				       rionet_inb_msg_event)) < 0)
  		goto out;
  
  	if ((rc = rio_request_outb_mbox(rnet->mport,
  					(void *)ndev,
  					RIONET_MAILBOX,
  					RIONET_TX_RING_SIZE,
  					rionet_outb_msg_event)) < 0)
  		goto out;
  
  	/* Initialize inbound message ring */
  	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
  		rnet->rx_skb[i] = NULL;
  	rnet->rx_slot = 0;
  	rionet_rx_fill(ndev, 0);
  
  	rnet->tx_slot = 0;
  	rnet->tx_cnt = 0;
  	rnet->ack_slot = 0;
  
  	netif_carrier_on(ndev);
  	netif_start_queue(ndev);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
356
357
  	spin_lock_irqsave(&nets[netid].lock, flags);
  	list_for_each_entry(peer, &nets[netid].peers, node) {
284fb68d0   Alexandre Bounine   rapidio: fix use ...
358
359
  		/* Send a join message */
  		rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
f89efd523   Matt Porter   [PATCH] Add rapid...
360
  	}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
361
362
  	spin_unlock_irqrestore(&nets[netid].lock, flags);
  	rnet->open = true;
f89efd523   Matt Porter   [PATCH] Add rapid...
363
364
365
366
367
368
369
  
        out:
  	return rc;
  }
  
  static int rionet_close(struct net_device *ndev)
  {
4cf1653aa   Wang Chen   netdevice: safe c...
370
  	struct rionet_private *rnet = netdev_priv(ndev);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
371
372
373
  	struct rionet_peer *peer;
  	unsigned char netid = rnet->mport->id;
  	unsigned long flags;
f89efd523   Matt Porter   [PATCH] Add rapid...
374
375
376
  	int i;
  
  	if (netif_msg_ifup(rnet))
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
377
378
  		printk(KERN_INFO "%s: close %s
  ", DRV_NAME, ndev->name);
f89efd523   Matt Porter   [PATCH] Add rapid...
379
380
381
  
  	netif_stop_queue(ndev);
  	netif_carrier_off(ndev);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
382
  	rnet->open = false;
f89efd523   Matt Porter   [PATCH] Add rapid...
383
384
  
  	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
aaff1e190   Wei Yongjun   drivers/net/rione...
385
  		kfree_skb(rnet->rx_skb[i]);
f89efd523   Matt Porter   [PATCH] Add rapid...
386

34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
387
388
389
  	spin_lock_irqsave(&nets[netid].lock, flags);
  	list_for_each_entry(peer, &nets[netid].peers, node) {
  		if (nets[netid].active[peer->rdev->destid]) {
f89efd523   Matt Porter   [PATCH] Add rapid...
390
  			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
391
  			nets[netid].active[peer->rdev->destid] = NULL;
f89efd523   Matt Porter   [PATCH] Add rapid...
392
  		}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
393
394
  		if (peer->res)
  			rio_release_outb_dbell(peer->rdev, peer->res);
f89efd523   Matt Porter   [PATCH] Add rapid...
395
  	}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
396
  	spin_unlock_irqrestore(&nets[netid].lock, flags);
f89efd523   Matt Porter   [PATCH] Add rapid...
397
398
399
400
401
402
403
404
  
  	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
  			      RIONET_DOORBELL_LEAVE);
  	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
  	rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
  
  	return 0;
  }
71db87ba5   Viresh Kumar   bus: subsys: upda...
405
  static void rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
f89efd523   Matt Porter   [PATCH] Add rapid...
406
  {
e6161d642   Alexandre Bounine   rapidio/rionet: r...
407
  	struct rio_dev *rdev = to_rio_dev(dev);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
408
  	unsigned char netid = rdev->net->hport->id;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
409
410
411
  	struct rionet_peer *peer;
  	int state, found = 0;
  	unsigned long flags;
f89efd523   Matt Porter   [PATCH] Add rapid...
412

34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
413
414
415
416
417
418
419
420
421
422
423
424
425
  	if (!dev_rionet_capable(rdev))
  		return;
  
  	spin_lock_irqsave(&nets[netid].lock, flags);
  	list_for_each_entry(peer, &nets[netid].peers, node) {
  		if (peer->rdev == rdev) {
  			list_del(&peer->node);
  			if (nets[netid].active[rdev->destid]) {
  				state = atomic_read(&rdev->state);
  				if (state != RIO_DEVICE_GONE &&
  				    state != RIO_DEVICE_INITIALIZING) {
  					rio_send_doorbell(rdev,
  							RIONET_DOORBELL_LEAVE);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
426
  				}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
427
428
  				nets[netid].active[rdev->destid] = NULL;
  				nets[netid].nact--;
e6161d642   Alexandre Bounine   rapidio/rionet: r...
429
  			}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
430
431
  			found = 1;
  			break;
e6161d642   Alexandre Bounine   rapidio/rionet: r...
432
  		}
f89efd523   Matt Porter   [PATCH] Add rapid...
433
  	}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
434
435
436
437
438
439
440
  	spin_unlock_irqrestore(&nets[netid].lock, flags);
  
  	if (found) {
  		if (peer->res)
  			rio_release_outb_dbell(rdev, peer->res);
  		kfree(peer);
  	}
f89efd523   Matt Porter   [PATCH] Add rapid...
441
442
443
444
445
  }
  
  static void rionet_get_drvinfo(struct net_device *ndev,
  			       struct ethtool_drvinfo *info)
  {
4cf1653aa   Wang Chen   netdevice: safe c...
446
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
447

7826d43f2   Jiri Pirko   ethtool: fix drvi...
448
449
450
451
  	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
  	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
  	strlcpy(info->fw_version, "n/a", sizeof(info->fw_version));
  	strlcpy(info->bus_info, rnet->mport->name, sizeof(info->bus_info));
f89efd523   Matt Porter   [PATCH] Add rapid...
452
453
454
455
  }
  
  static u32 rionet_get_msglevel(struct net_device *ndev)
  {
4cf1653aa   Wang Chen   netdevice: safe c...
456
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
457
458
459
460
461
462
  
  	return rnet->msg_enable;
  }
  
  static void rionet_set_msglevel(struct net_device *ndev, u32 value)
  {
4cf1653aa   Wang Chen   netdevice: safe c...
463
  	struct rionet_private *rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
464
465
466
  
  	rnet->msg_enable = value;
  }
7282d491e   Jeff Garzik   drivers/net: cons...
467
  static const struct ethtool_ops rionet_ethtool_ops = {
f89efd523   Matt Porter   [PATCH] Add rapid...
468
469
470
471
472
  	.get_drvinfo = rionet_get_drvinfo,
  	.get_msglevel = rionet_get_msglevel,
  	.set_msglevel = rionet_set_msglevel,
  	.get_link = ethtool_op_get_link,
  };
a33a2bb3c   Alexander Beregalov   rionet: convert t...
473
474
475
476
  static const struct net_device_ops rionet_netdev_ops = {
  	.ndo_open		= rionet_open,
  	.ndo_stop		= rionet_close,
  	.ndo_start_xmit		= rionet_start_xmit,
a33a2bb3c   Alexander Beregalov   rionet: convert t...
477
478
479
  	.ndo_validate_addr	= eth_validate_addr,
  	.ndo_set_mac_address	= eth_mac_addr,
  };
55caa9241   Yinglin Luan   rionet: fix NULL ...
480
  static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
f89efd523   Matt Porter   [PATCH] Add rapid...
481
482
  {
  	int rc = 0;
f89efd523   Matt Porter   [PATCH] Add rapid...
483
484
  	struct rionet_private *rnet;
  	u16 device_id;
acc656323   Akinobu Mita   rionet: fix page ...
485
486
  	const size_t rionet_active_bytes = sizeof(void *) *
  				RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
f89efd523   Matt Porter   [PATCH] Add rapid...
487

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
488
489
490
  	nets[mport->id].active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
  						get_order(rionet_active_bytes));
  	if (!nets[mport->id].active) {
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
491
492
493
  		rc = -ENOMEM;
  		goto out;
  	}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
494
  	memset((void *)nets[mport->id].active, 0, rionet_active_bytes);
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
495

f89efd523   Matt Porter   [PATCH] Add rapid...
496
  	/* Set up private area */
4cf1653aa   Wang Chen   netdevice: safe c...
497
  	rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
498
  	rnet->mport = mport;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
499
  	rnet->open = false;
f89efd523   Matt Porter   [PATCH] Add rapid...
500
501
502
503
504
505
506
507
508
  
  	/* Set the default MAC address */
  	device_id = rio_local_get_device_id(mport);
  	ndev->dev_addr[0] = 0x00;
  	ndev->dev_addr[1] = 0x01;
  	ndev->dev_addr[2] = 0x00;
  	ndev->dev_addr[3] = 0x01;
  	ndev->dev_addr[4] = device_id >> 8;
  	ndev->dev_addr[5] = device_id & 0xff;
a33a2bb3c   Alexander Beregalov   rionet: convert t...
509
  	ndev->netdev_ops = &rionet_netdev_ops;
92444bb36   Aurelien Jacquiot   rapidio/rionet: a...
510
  	ndev->mtu = RIONET_MAX_MTU;
b3e3893e1   Jarod Wilson   net: use core MTU...
511
512
513
  	/* MTU range: 68 - 4082 */
  	ndev->min_mtu = ETH_MIN_MTU;
  	ndev->max_mtu = RIONET_MAX_MTU;
f89efd523   Matt Porter   [PATCH] Add rapid...
514
  	ndev->features = NETIF_F_LLTX;
2aaf308b9   Alexandre Bounine   rapidio: rework d...
515
  	SET_NETDEV_DEV(ndev, &mport->dev);
7ad24ea4b   Wilfried Klaebe   net: get rid of S...
516
  	ndev->ethtool_ops = &rionet_ethtool_ops;
f89efd523   Matt Porter   [PATCH] Add rapid...
517

f89efd523   Matt Porter   [PATCH] Add rapid...
518
519
520
521
522
523
  	spin_lock_init(&rnet->lock);
  	spin_lock_init(&rnet->tx_lock);
  
  	rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
  
  	rc = register_netdev(ndev);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
524
525
526
  	if (rc != 0) {
  		free_pages((unsigned long)nets[mport->id].active,
  			   get_order(rionet_active_bytes));
f89efd523   Matt Porter   [PATCH] Add rapid...
527
  		goto out;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
528
  	}
f89efd523   Matt Porter   [PATCH] Add rapid...
529

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
530
531
  	printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s
  ",
f89efd523   Matt Porter   [PATCH] Add rapid...
532
533
534
535
  	       ndev->name,
  	       DRV_NAME,
  	       DRV_DESC,
  	       DRV_VERSION,
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
536
537
  	       ndev->dev_addr,
  	       mport->name);
f89efd523   Matt Porter   [PATCH] Add rapid...
538
539
540
541
  
        out:
  	return rc;
  }
e6161d642   Alexandre Bounine   rapidio/rionet: r...
542
  static int rionet_add_dev(struct device *dev, struct subsys_interface *sif)
f89efd523   Matt Porter   [PATCH] Add rapid...
543
544
  {
  	int rc = -ENODEV;
284fb68d0   Alexandre Bounine   rapidio: fix use ...
545
  	u32 lsrc_ops, ldst_ops;
f89efd523   Matt Porter   [PATCH] Add rapid...
546
  	struct rionet_peer *peer;
55caa9241   Yinglin Luan   rionet: fix NULL ...
547
  	struct net_device *ndev = NULL;
e6161d642   Alexandre Bounine   rapidio/rionet: r...
548
  	struct rio_dev *rdev = to_rio_dev(dev);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
549
  	unsigned char netid = rdev->net->hport->id;
f89efd523   Matt Porter   [PATCH] Add rapid...
550

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
551
552
  	if (netid >= RIONET_MAX_NETS)
  		return rc;
f89efd523   Matt Porter   [PATCH] Add rapid...
553
554
  
  	/*
e6161d642   Alexandre Bounine   rapidio/rionet: r...
555
556
557
  	 * If first time through this net, make sure local device is rionet
  	 * capable and setup netdev (this step will be skipped in later probes
  	 * on the same net).
f89efd523   Matt Porter   [PATCH] Add rapid...
558
  	 */
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
559
  	if (!nets[netid].ndev) {
f89efd523   Matt Porter   [PATCH] Add rapid...
560
561
562
563
  		rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
  					 &lsrc_ops);
  		rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
  					 &ldst_ops);
284fb68d0   Alexandre Bounine   rapidio: fix use ...
564
  		if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
f89efd523   Matt Porter   [PATCH] Add rapid...
565
  			printk(KERN_ERR
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
566
567
568
  			       "%s: local device %s is not network capable
  ",
  			       DRV_NAME, rdev->net->hport->name);
f89efd523   Matt Porter   [PATCH] Add rapid...
569
570
  			goto out;
  		}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
571
572
573
574
575
576
  		/* Allocate our net_device structure */
  		ndev = alloc_etherdev(sizeof(struct rionet_private));
  		if (ndev == NULL) {
  			rc = -ENOMEM;
  			goto out;
  		}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
577

55caa9241   Yinglin Luan   rionet: fix NULL ...
578
  		rc = rionet_setup_netdev(rdev->net->hport, ndev);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
579
580
581
582
  		if (rc) {
  			printk(KERN_ERR "%s: failed to setup netdev (rc=%d)
  ",
  			       DRV_NAME, rc);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
583
  			free_netdev(ndev);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
584
585
  			goto out;
  		}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
586
  		INIT_LIST_HEAD(&nets[netid].peers);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
587
  		spin_lock_init(&nets[netid].lock);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
588
  		nets[netid].nact = 0;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
589
590
  		nets[netid].ndev = ndev;
  	}
f89efd523   Matt Porter   [PATCH] Add rapid...
591
592
593
594
595
596
  
  	/*
  	 * If the remote device has mailbox/doorbell capabilities,
  	 * add it to the peer list.
  	 */
  	if (dev_rionet_capable(rdev)) {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
597
598
599
600
601
602
603
  		struct rionet_private *rnet;
  		unsigned long flags;
  
  		rnet = netdev_priv(nets[netid].ndev);
  
  		peer = kzalloc(sizeof(*peer), GFP_KERNEL);
  		if (!peer) {
f89efd523   Matt Porter   [PATCH] Add rapid...
604
605
606
607
  			rc = -ENOMEM;
  			goto out;
  		}
  		peer->rdev = rdev;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
608
609
610
611
612
613
614
615
616
617
618
619
  		peer->res = rio_request_outb_dbell(peer->rdev,
  						RIONET_DOORBELL_JOIN,
  						RIONET_DOORBELL_LEAVE);
  		if (!peer->res) {
  			pr_err("%s: error requesting doorbells
  ", DRV_NAME);
  			kfree(peer);
  			rc = -ENOMEM;
  			goto out;
  		}
  
  		spin_lock_irqsave(&nets[netid].lock, flags);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
620
  		list_add_tail(&peer->node, &nets[netid].peers);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
621
622
623
624
625
626
627
628
  		spin_unlock_irqrestore(&nets[netid].lock, flags);
  		pr_debug("%s: %s add peer %s
  ",
  			 DRV_NAME, __func__, rio_name(rdev));
  
  		/* If netdev is already opened, send join request to new peer */
  		if (rnet->open)
  			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
f89efd523   Matt Porter   [PATCH] Add rapid...
629
  	}
e6161d642   Alexandre Bounine   rapidio/rionet: r...
630
631
  	return 0;
  out:
f89efd523   Matt Porter   [PATCH] Add rapid...
632
633
  	return rc;
  }
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
634
635
636
  static int rionet_shutdown(struct notifier_block *nb, unsigned long code,
  			   void *unused)
  {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
637
638
  	struct rionet_peer *peer;
  	unsigned long flags;
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
639
640
641
642
643
644
645
646
  	int i;
  
  	pr_debug("%s: %s
  ", DRV_NAME, __func__);
  
  	for (i = 0; i < RIONET_MAX_NETS; i++) {
  		if (!nets[i].ndev)
  			continue;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
647
648
  		spin_lock_irqsave(&nets[i].lock, flags);
  		list_for_each_entry(peer, &nets[i].peers, node) {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
649
650
651
652
653
654
  			if (nets[i].active[peer->rdev->destid]) {
  				rio_send_doorbell(peer->rdev,
  						  RIONET_DOORBELL_LEAVE);
  				nets[i].active[peer->rdev->destid] = NULL;
  			}
  		}
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
655
  		spin_unlock_irqrestore(&nets[i].lock, flags);
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
656
657
658
659
  	}
  
  	return NOTIFY_DONE;
  }
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  static void rionet_remove_mport(struct device *dev,
  				struct class_interface *class_intf)
  {
  	struct rio_mport *mport = to_rio_mport(dev);
  	struct net_device *ndev;
  	int id = mport->id;
  
  	pr_debug("%s %s
  ", __func__, mport->name);
  
  	WARN(nets[id].nact, "%s called when connected to %d peers
  ",
  	     __func__, nets[id].nact);
  	WARN(!nets[id].ndev, "%s called for mport without NDEV
  ",
  	     __func__);
  
  	if (nets[id].ndev) {
  		ndev = nets[id].ndev;
  		netif_stop_queue(ndev);
  		unregister_netdev(ndev);
  
  		free_pages((unsigned long)nets[id].active,
  			   get_order(sizeof(void *) *
  			   RIO_MAX_ROUTE_ENTRIES(mport->sys_size)));
  		nets[id].active = NULL;
  		free_netdev(ndev);
  		nets[id].ndev = NULL;
  	}
  }
e6161d642   Alexandre Bounine   rapidio/rionet: r...
690
  #ifdef MODULE
f89efd523   Matt Porter   [PATCH] Add rapid...
691
  static struct rio_device_id rionet_id_table[] = {
e6161d642   Alexandre Bounine   rapidio/rionet: r...
692
693
  	{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)},
  	{ 0, }	/* terminate list */
f89efd523   Matt Porter   [PATCH] Add rapid...
694
  };
e6161d642   Alexandre Bounine   rapidio/rionet: r...
695
696
697
698
699
700
701
702
  MODULE_DEVICE_TABLE(rapidio, rionet_id_table);
  #endif
  
  static struct subsys_interface rionet_interface = {
  	.name		= "rionet",
  	.subsys		= &rio_bus_type,
  	.add_dev	= rionet_add_dev,
  	.remove_dev	= rionet_remove_dev,
f89efd523   Matt Porter   [PATCH] Add rapid...
703
  };
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
704
705
706
  static struct notifier_block rionet_notifier = {
  	.notifier_call = rionet_shutdown,
  };
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
707
708
709
710
711
712
  /* the rio_mport_interface is used to handle local mport devices */
  static struct class_interface rio_mport_interface __refdata = {
  	.class = &rio_mport_class,
  	.add_dev = NULL,
  	.remove_dev = rionet_remove_mport,
  };
f89efd523   Matt Porter   [PATCH] Add rapid...
713
714
  static int __init rionet_init(void)
  {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
715
716
717
718
719
720
721
722
723
  	int ret;
  
  	ret = register_reboot_notifier(&rionet_notifier);
  	if (ret) {
  		pr_err("%s: failed to register reboot notifier (err=%d)
  ",
  		       DRV_NAME, ret);
  		return ret;
  	}
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
724
725
726
727
728
729
730
731
  
  	ret = class_interface_register(&rio_mport_interface);
  	if (ret) {
  		pr_err("%s: class_interface_register error: %d
  ",
  		       DRV_NAME, ret);
  		return ret;
  	}
e6161d642   Alexandre Bounine   rapidio/rionet: r...
732
  	return subsys_interface_register(&rionet_interface);
f89efd523   Matt Porter   [PATCH] Add rapid...
733
734
735
736
  }
  
  static void __exit rionet_exit(void)
  {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
737
  	unregister_reboot_notifier(&rionet_notifier);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
738
  	subsys_interface_unregister(&rionet_interface);
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
739
  	class_interface_unregister(&rio_mport_interface);
f89efd523   Matt Porter   [PATCH] Add rapid...
740
  }
2f809985d   Alexandre Bounine   rapidio: modify s...
741
  late_initcall(rionet_init);
f89efd523   Matt Porter   [PATCH] Add rapid...
742
  module_exit(rionet_exit);