Blame view

drivers/net/rionet.c 18.8 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
203
204
205
  				if (count)
  					atomic_inc(&skb->users);
  				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
218
219
220
221
  		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).
  			 */
  			dev_kfree_skb_any(skb);
  			ndev->stats.tx_packets++;
  			ndev->stats.tx_bytes += skb->len;
  		}
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;
  }
92444bb36   Aurelien Jacquiot   rapidio/rionet: a...
467
468
469
470
471
472
473
474
475
476
477
  static int rionet_change_mtu(struct net_device *ndev, int new_mtu)
  {
  	if ((new_mtu < 68) || (new_mtu > RIONET_MAX_MTU)) {
  		printk(KERN_ERR "%s: Invalid MTU size %d
  ",
  		       ndev->name, new_mtu);
  		return -EINVAL;
  	}
  	ndev->mtu = new_mtu;
  	return 0;
  }
7282d491e   Jeff Garzik   drivers/net: cons...
478
  static const struct ethtool_ops rionet_ethtool_ops = {
f89efd523   Matt Porter   [PATCH] Add rapid...
479
480
481
482
483
  	.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...
484
485
486
487
  static const struct net_device_ops rionet_netdev_ops = {
  	.ndo_open		= rionet_open,
  	.ndo_stop		= rionet_close,
  	.ndo_start_xmit		= rionet_start_xmit,
92444bb36   Aurelien Jacquiot   rapidio/rionet: a...
488
  	.ndo_change_mtu		= rionet_change_mtu,
a33a2bb3c   Alexander Beregalov   rionet: convert t...
489
490
491
  	.ndo_validate_addr	= eth_validate_addr,
  	.ndo_set_mac_address	= eth_mac_addr,
  };
55caa9241   Yinglin Luan   rionet: fix NULL ...
492
  static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
f89efd523   Matt Porter   [PATCH] Add rapid...
493
494
  {
  	int rc = 0;
f89efd523   Matt Porter   [PATCH] Add rapid...
495
496
  	struct rionet_private *rnet;
  	u16 device_id;
acc656323   Akinobu Mita   rionet: fix page ...
497
498
  	const size_t rionet_active_bytes = sizeof(void *) *
  				RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
f89efd523   Matt Porter   [PATCH] Add rapid...
499

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
500
501
502
  	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...
503
504
505
  		rc = -ENOMEM;
  		goto out;
  	}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
506
  	memset((void *)nets[mport->id].active, 0, rionet_active_bytes);
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
507

f89efd523   Matt Porter   [PATCH] Add rapid...
508
  	/* Set up private area */
4cf1653aa   Wang Chen   netdevice: safe c...
509
  	rnet = netdev_priv(ndev);
f89efd523   Matt Porter   [PATCH] Add rapid...
510
  	rnet->mport = mport;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
511
  	rnet->open = false;
f89efd523   Matt Porter   [PATCH] Add rapid...
512
513
514
515
516
517
518
519
520
  
  	/* 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...
521
  	ndev->netdev_ops = &rionet_netdev_ops;
92444bb36   Aurelien Jacquiot   rapidio/rionet: a...
522
  	ndev->mtu = RIONET_MAX_MTU;
f89efd523   Matt Porter   [PATCH] Add rapid...
523
  	ndev->features = NETIF_F_LLTX;
2aaf308b9   Alexandre Bounine   rapidio: rework d...
524
  	SET_NETDEV_DEV(ndev, &mport->dev);
7ad24ea4b   Wilfried Klaebe   net: get rid of S...
525
  	ndev->ethtool_ops = &rionet_ethtool_ops;
f89efd523   Matt Porter   [PATCH] Add rapid...
526

f89efd523   Matt Porter   [PATCH] Add rapid...
527
528
529
530
531
532
  	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...
533
534
535
  	if (rc != 0) {
  		free_pages((unsigned long)nets[mport->id].active,
  			   get_order(rionet_active_bytes));
f89efd523   Matt Porter   [PATCH] Add rapid...
536
  		goto out;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
537
  	}
f89efd523   Matt Porter   [PATCH] Add rapid...
538

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

2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
560
561
  	if (netid >= RIONET_MAX_NETS)
  		return rc;
f89efd523   Matt Porter   [PATCH] Add rapid...
562
563
  
  	/*
e6161d642   Alexandre Bounine   rapidio/rionet: r...
564
565
566
  	 * 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...
567
  	 */
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
568
  	if (!nets[netid].ndev) {
f89efd523   Matt Porter   [PATCH] Add rapid...
569
570
571
572
  		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 ...
573
  		if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
f89efd523   Matt Porter   [PATCH] Add rapid...
574
  			printk(KERN_ERR
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
575
576
577
  			       "%s: local device %s is not network capable
  ",
  			       DRV_NAME, rdev->net->hport->name);
f89efd523   Matt Porter   [PATCH] Add rapid...
578
579
  			goto out;
  		}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
580
581
582
583
584
585
  		/* 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...
586

55caa9241   Yinglin Luan   rionet: fix NULL ...
587
  		rc = rionet_setup_netdev(rdev->net->hport, ndev);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
588
589
590
591
  		if (rc) {
  			printk(KERN_ERR "%s: failed to setup netdev (rc=%d)
  ",
  			       DRV_NAME, rc);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
592
  			free_netdev(ndev);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
593
594
  			goto out;
  		}
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
595
  		INIT_LIST_HEAD(&nets[netid].peers);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
596
  		spin_lock_init(&nets[netid].lock);
2fb717ec3   Alexandre Bounine   rapidio/rionet: r...
597
  		nets[netid].nact = 0;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
598
599
  		nets[netid].ndev = ndev;
  	}
f89efd523   Matt Porter   [PATCH] Add rapid...
600
601
602
603
604
605
  
  	/*
  	 * 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...
606
607
608
609
610
611
612
  		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...
613
614
615
616
  			rc = -ENOMEM;
  			goto out;
  		}
  		peer->rdev = rdev;
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
617
618
619
620
621
622
623
624
625
626
627
628
  		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...
629
  		list_add_tail(&peer->node, &nets[netid].peers);
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
630
631
632
633
634
635
636
637
  		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...
638
  	}
e6161d642   Alexandre Bounine   rapidio/rionet: r...
639
640
  	return 0;
  out:
f89efd523   Matt Porter   [PATCH] Add rapid...
641
642
  	return rc;
  }
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
643
644
645
  static int rionet_shutdown(struct notifier_block *nb, unsigned long code,
  			   void *unused)
  {
34ed2ebb6   Alexandre Bounine   rapidio/rionet: a...
646
647
  	struct rionet_peer *peer;
  	unsigned long flags;
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
648
649
650
651
652
653
654
655
  	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...
656
657
  		spin_lock_irqsave(&nets[i].lock, flags);
  		list_for_each_entry(peer, &nets[i].peers, node) {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
658
659
660
661
662
663
  			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...
664
  		spin_unlock_irqrestore(&nets[i].lock, flags);
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
665
666
667
668
  	}
  
  	return NOTIFY_DONE;
  }
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  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...
699
  #ifdef MODULE
f89efd523   Matt Porter   [PATCH] Add rapid...
700
  static struct rio_device_id rionet_id_table[] = {
e6161d642   Alexandre Bounine   rapidio/rionet: r...
701
702
  	{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)},
  	{ 0, }	/* terminate list */
f89efd523   Matt Porter   [PATCH] Add rapid...
703
  };
e6161d642   Alexandre Bounine   rapidio/rionet: r...
704
705
706
707
708
709
710
711
  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...
712
  };
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
713
714
715
  static struct notifier_block rionet_notifier = {
  	.notifier_call = rionet_shutdown,
  };
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
716
717
718
719
720
721
  /* 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...
722
723
  static int __init rionet_init(void)
  {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
724
725
726
727
728
729
730
731
732
  	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...
733
734
735
736
737
738
739
740
  
  	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...
741
  	return subsys_interface_register(&rionet_interface);
f89efd523   Matt Porter   [PATCH] Add rapid...
742
743
744
745
  }
  
  static void __exit rionet_exit(void)
  {
f41e2472b   Alexandre Bounine   rapidio/rionet: a...
746
  	unregister_reboot_notifier(&rionet_notifier);
e6161d642   Alexandre Bounine   rapidio/rionet: r...
747
  	subsys_interface_unregister(&rionet_interface);
b7dfca8bd   Alexandre Bounine   rapidio/rionet: a...
748
  	class_interface_unregister(&rio_mport_interface);
f89efd523   Matt Porter   [PATCH] Add rapid...
749
  }
2f809985d   Alexandre Bounine   rapidio: modify s...
750
  late_initcall(rionet_init);
f89efd523   Matt Porter   [PATCH] Add rapid...
751
  module_exit(rionet_exit);