Blame view

drivers/net/eql.c 14.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   * Equalizer Load-balancer for serial network interfaces.
   *
   * (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
   * NCM: Network and Communications Management, Inc.
   *
   * (c) Copyright 2002 David S. Miller (davem@redhat.com)
   *
   *	This software may be used and distributed according to the terms
   *	of the GNU General Public License, incorporated herein by reference.
6aa20a223   Jeff Garzik   drivers/net: Trim...
11
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   * The author may be reached as simon@ncm.com, or C/O
   *    NCM
   *    Attn: Simon Janes
   *    6803 Whittier Ave
   *    McLean VA 22101
   *    Phone: 1-703-847-0040 ext 103
   */
  
  /*
   * Sources:
   *   skeleton.c by Donald Becker.
   * Inspirations:
   *   The Harried and Overworked Alan Cox
   * Conspiracies:
6aa20a223   Jeff Garzik   drivers/net: Trim...
26
   *   The Alan Cox and Mike McLagan plot to get someone else to do the code,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
   *   which turned out to be me.
   */
  
  /*
   * $Log: eql.c,v $
   * Revision 1.2  1996/04/11 17:51:52  guru
   * Added one-line eql_remove_slave patch.
   *
   * Revision 1.1  1996/04/11 17:44:17  guru
   * Initial revision
   *
   * Revision 3.13  1996/01/21  15:17:18  alan
   * tx_queue_len changes.
   * reformatted.
   *
   * Revision 3.12  1995/03/22  21:07:51  anarchy
   * Added capable() checks on configuration.
   * Moved header file.
   *
   * Revision 3.11  1995/01/19  23:14:31  guru
   * 		      slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
   * 			(priority_Bps) + bytes_queued * 8;
   *
   * Revision 3.10  1995/01/19  23:07:53  guru
   * back to
   * 		      slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
   * 			(priority_Bps) + bytes_queued;
   *
   * Revision 3.9  1995/01/19  22:38:20  guru
   * 		      slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
   * 			(priority_Bps) + bytes_queued * 4;
   *
   * Revision 3.8  1995/01/19  22:30:55  guru
   *       slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
   * 			(priority_Bps) + bytes_queued * 2;
   *
   * Revision 3.7  1995/01/19  21:52:35  guru
   * printk's trimmed out.
   *
   * Revision 3.6  1995/01/19  21:49:56  guru
   * This is working pretty well. I gained 1 K/s in speed.. now it's just
   * robustness and printk's to be diked out.
   *
   * Revision 3.5  1995/01/18  22:29:59  guru
   * still crashes the kernel when the lock_wait thing is woken up.
   *
   * Revision 3.4  1995/01/18  21:59:47  guru
   * Broken set-bit locking snapshot
   *
   * Revision 3.3  1995/01/17  22:09:18  guru
   * infinite sleep in a lock somewhere..
   *
   * Revision 3.2  1995/01/15  16:46:06  guru
   * Log trimmed of non-pertinent 1.x branch messages
   *
   * Revision 3.1  1995/01/15  14:41:45  guru
   * New Scheduler and timer stuff...
   *
   * Revision 1.15  1995/01/15  14:29:02  guru
   * Will make 1.14 (now 1.15) the 3.0 branch, and the 1.12 the 2.0 branch, the one
   * with the dumber scheduler
   *
   * Revision 1.14  1995/01/15  02:37:08  guru
   * shock.. the kept-new-versions could have zonked working
   * stuff.. shudder
   *
   * Revision 1.13  1995/01/15  02:36:31  guru
   * big changes
   *
   * 	scheduler was torn out and replaced with something smarter
   *
   * 	global names not prefixed with eql_ were renamed to protect
   * 	against namespace collisions
   *
   * 	a few more abstract interfaces were added to facilitate any
   * 	potential change of datastructure.  the driver is still using
   * 	a linked list of slaves.  going to a heap would be a bit of
   * 	an overkill.
   *
   * 	this compiles fine with no warnings.
   *
   * 	the locking mechanism and timer stuff must be written however,
   * 	this version will not work otherwise
   *
   * Sorry, I had to rewrite most of this for 2.5.x -DaveM
   */
63f974251   Joe Perches   eql: Convert prin...
113
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
d43c36dc6   Alexey Dobriyan   headers: remove s...
114
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
118
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
  #include <linux/timer.h>
  #include <linux/netdevice.h>
881d966b4   Eric W. Biederman   [NET]: Make the d...
121
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
  
  #include <linux/if.h>
  #include <linux/if_arp.h>
  #include <linux/if_eql.h>
09e79d6ea   Eric Dumazet   eql: dont rely on...
126
  #include <linux/pkt_sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
128
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
  
  static int eql_open(struct net_device *dev);
  static int eql_close(struct net_device *dev);
  static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
424efe9ca   Stephen Hemminger   netdev: convert p...
133
  static netdev_tx_t eql_slave_xmit(struct sk_buff *skb, struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
  
  #define eql_is_slave(dev)	((dev->flags & IFF_SLAVE) == IFF_SLAVE)
  #define eql_is_master(dev)	((dev->flags & IFF_MASTER) == IFF_MASTER)
14a59e182   Loic Le Loarer   [EQL]: Proper num...
137
  static void eql_kill_one_slave(slave_queue_t *queue, slave_t *slave);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138

e99e88a9d   Kees Cook   treewide: setup_t...
139
  static void eql_timer(struct timer_list *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  {
e99e88a9d   Kees Cook   treewide: setup_t...
141
  	equalizer_t *eql = from_timer(eql, t, timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  	struct list_head *this, *tmp, *head;
6aa20a223   Jeff Garzik   drivers/net: Trim...
143

09e79d6ea   Eric Dumazet   eql: dont rely on...
144
  	spin_lock(&eql->queue.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
152
153
  	head = &eql->queue.all_slaves;
  	list_for_each_safe(this, tmp, head) {
  		slave_t *slave = list_entry(this, slave_t, list);
  
  		if ((slave->dev->flags & IFF_UP) == IFF_UP) {
  			slave->bytes_queued -= slave->priority_Bps;
  			if (slave->bytes_queued < 0)
  				slave->bytes_queued = 0;
  		} else {
14a59e182   Loic Le Loarer   [EQL]: Proper num...
154
  			eql_kill_one_slave(&eql->queue, slave);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
  		}
  
  	}
09e79d6ea   Eric Dumazet   eql: dont rely on...
158
  	spin_unlock(&eql->queue.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
  
  	eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL;
  	add_timer(&eql->timer);
  }
aec464bbe   Stephen Hemminger   eql: fix non-cons...
163
  static const char version[] __initconst =
63f974251   Joe Perches   eql: Convert prin...
164
  	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

99921b7e6   Stephen Hemminger   eql: convert to n...
166
167
168
169
170
171
  static const struct net_device_ops eql_netdev_ops = {
  	.ndo_open	= eql_open,
  	.ndo_stop	= eql_close,
  	.ndo_do_ioctl	= eql_ioctl,
  	.ndo_start_xmit	= eql_slave_xmit,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
  static void __init eql_setup(struct net_device *dev)
  {
  	equalizer_t *eql = netdev_priv(dev);
e99e88a9d   Kees Cook   treewide: setup_t...
175
  	timer_setup(&eql->timer, eql_timer, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	eql->timer.expires  	= jiffies + EQL_DEFAULT_RESCHED_IVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
  
  	spin_lock_init(&eql->queue.lock);
  	INIT_LIST_HEAD(&eql->queue.all_slaves);
  	eql->queue.master_dev	= dev;
99921b7e6   Stephen Hemminger   eql: convert to n...
181
  	dev->netdev_ops		= &eql_netdev_ops;
6aa20a223   Jeff Garzik   drivers/net: Trim...
182

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  	/*
  	 *	Now we undo some of the things that eth_setup does
6aa20a223   Jeff Garzik   drivers/net: Trim...
185
  	 * 	that we don't like
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	 */
6aa20a223   Jeff Garzik   drivers/net: Trim...
187

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
  	dev->mtu        	= EQL_DEFAULT_MTU;	/* set to 576 in if_eql.h */
  	dev->flags      	= IFF_MASTER;
  
  	dev->type       	= ARPHRD_SLIP;
  	dev->tx_queue_len 	= 5;		/* Hands them off fast */
028758788   Eric Dumazet   net: better IFF_X...
193
  	netif_keep_dst(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
  }
  
  static int eql_open(struct net_device *dev)
  {
  	equalizer_t *eql = netdev_priv(dev);
  
  	/* XXX We should force this off automatically for the user. */
63f974251   Joe Perches   eql: Convert prin...
201
202
203
  	netdev_info(dev,
  		    "remember to turn off Van-Jacobson compression on your slave devices
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

5d9428de1   Eric Sesterhenn   BUG_ON() Conversi...
205
  	BUG_ON(!list_empty(&eql->queue.all_slaves));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
210
211
212
213
  
  	eql->min_slaves = 1;
  	eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
  
  	add_timer(&eql->timer);
  
  	return 0;
  }
14a59e182   Loic Le Loarer   [EQL]: Proper num...
214
  static void eql_kill_one_slave(slave_queue_t *queue, slave_t *slave)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
  {
  	list_del(&slave->list);
14a59e182   Loic Le Loarer   [EQL]: Proper num...
217
  	queue->num_slaves--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
222
223
  	slave->dev->flags &= ~IFF_SLAVE;
  	dev_put(slave->dev);
  	kfree(slave);
  }
  
  static void eql_kill_slave_queue(slave_queue_t *queue)
6aa20a223   Jeff Garzik   drivers/net: Trim...
224
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
  	struct list_head *head, *tmp, *this;
  
  	spin_lock_bh(&queue->lock);
  
  	head = &queue->all_slaves;
  	list_for_each_safe(this, tmp, head) {
  		slave_t *s = list_entry(this, slave_t, list);
14a59e182   Loic Le Loarer   [EQL]: Proper num...
232
  		eql_kill_one_slave(queue, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
237
238
239
240
241
242
243
  	}
  
  	spin_unlock_bh(&queue->lock);
  }
  
  static int eql_close(struct net_device *dev)
  {
  	equalizer_t *eql = netdev_priv(dev);
  
  	/*
  	 *	The timer has to be stopped first before we start hacking away
6aa20a223   Jeff Garzik   drivers/net: Trim...
244
  	 *	at the data structure it scans every so often...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  	 */
  
  	del_timer_sync(&eql->timer);
  
  	eql_kill_slave_queue(&eql->queue);
  
  	return 0;
  }
  
  static int eql_enslave(struct net_device *dev,  slaving_request_t __user *srq);
  static int eql_emancipate(struct net_device *dev, slaving_request_t __user *srq);
  
  static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *sc);
  static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *sc);
  
  static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mc);
  static int eql_s_master_cfg(struct net_device *dev, master_config_t __user *mc);
  
  static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6aa20a223   Jeff Garzik   drivers/net: Trim...
264
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  	if (cmd != EQL_GETMASTRCFG && cmd != EQL_GETSLAVECFG &&
  	    !capable(CAP_NET_ADMIN))
  	  	return -EPERM;
  
  	switch (cmd) {
  		case EQL_ENSLAVE:
  			return eql_enslave(dev, ifr->ifr_data);
  		case EQL_EMANCIPATE:
  			return eql_emancipate(dev, ifr->ifr_data);
  		case EQL_GETSLAVECFG:
  			return eql_g_slave_cfg(dev, ifr->ifr_data);
  		case EQL_SETSLAVECFG:
  			return eql_s_slave_cfg(dev, ifr->ifr_data);
  		case EQL_GETMASTRCFG:
  			return eql_g_master_cfg(dev, ifr->ifr_data);
  		case EQL_SETMASTRCFG:
  			return eql_s_master_cfg(dev, ifr->ifr_data);
  		default:
  			return -EOPNOTSUPP;
ee289b644   Joe Perches   drivers/net: remo...
284
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  }
  
  /* queue->lock must be held */
  static slave_t *__eql_schedule_slaves(slave_queue_t *queue)
  {
  	unsigned long best_load = ~0UL;
  	struct list_head *this, *tmp, *head;
  	slave_t *best_slave;
  
  	best_slave = NULL;
  
  	/* Make a pass to set the best slave. */
  	head = &queue->all_slaves;
  	list_for_each_safe(this, tmp, head) {
  		slave_t *slave = list_entry(this, slave_t, list);
6aa20a223   Jeff Garzik   drivers/net: Trim...
300
  		unsigned long slave_load, bytes_queued, priority_Bps;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
  
  		/* Go through the slave list once, updating best_slave
  		 * whenever a new best_load is found.
  		 */
  		bytes_queued = slave->bytes_queued;
6aa20a223   Jeff Garzik   drivers/net: Trim...
306
  		priority_Bps = slave->priority_Bps;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  		if ((slave->dev->flags & IFF_UP) == IFF_UP) {
6aa20a223   Jeff Garzik   drivers/net: Trim...
308
  			slave_load = (~0UL - (~0UL / 2)) -
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
316
  				(priority_Bps) + bytes_queued * 8;
  
  			if (slave_load < best_load) {
  				best_load = slave_load;
  				best_slave = slave;
  			}
  		} else {
  			/* We found a dead slave, kill it. */
14a59e182   Loic Le Loarer   [EQL]: Proper num...
317
  			eql_kill_one_slave(queue, slave);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
  		}
  	}
  	return best_slave;
  }
424efe9ca   Stephen Hemminger   netdev: convert p...
322
  static netdev_tx_t eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
328
329
330
331
332
333
  {
  	equalizer_t *eql = netdev_priv(dev);
  	slave_t *slave;
  
  	spin_lock(&eql->queue.lock);
  
  	slave = __eql_schedule_slaves(&eql->queue);
  	if (slave) {
  		struct net_device *slave_dev = slave->dev;
  
  		skb->dev = slave_dev;
09e79d6ea   Eric Dumazet   eql: dont rely on...
334
  		skb->priority = TC_PRIO_FILLER;
6aa20a223   Jeff Garzik   drivers/net: Trim...
335
  		slave->bytes_queued += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  		dev_queue_xmit(skb);
09f75cd7b   Jeff Garzik   [NET] drivers/net...
337
  		dev->stats.tx_packets++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  	} else {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
339
  		dev->stats.tx_dropped++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  		dev_kfree_skb(skb);
6aa20a223   Jeff Garzik   drivers/net: Trim...
341
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  
  	spin_unlock(&eql->queue.lock);
6ed106549   Patrick McHardy   net: use NETDEV_T...
344
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  /*
   *	Private ioctl functions
   */
  
  /* queue->lock must be held */
  static slave_t *__eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev)
  {
  	struct list_head *this, *head;
  
  	head = &queue->all_slaves;
  	list_for_each(this, head) {
  		slave_t *slave = list_entry(this, slave_t, list);
  
  		if (slave->dev == dev)
  			return slave;
  	}
  
  	return NULL;
  }
  
  static inline int eql_is_full(slave_queue_t *queue)
  {
  	equalizer_t *eql = netdev_priv(queue->master_dev);
  
  	if (queue->num_slaves >= eql->max_slaves)
  		return 1;
  	return 0;
  }
  
  /* queue->lock must be held */
  static int __eql_insert_slave(slave_queue_t *queue, slave_t *slave)
  {
  	if (!eql_is_full(queue)) {
  		slave_t *duplicate_slave = NULL;
  
  		duplicate_slave = __eql_find_slave_dev(queue, slave->dev);
37d2e7316   Stephen Hemminger   [EQL]: sparse war...
382
  		if (duplicate_slave)
14a59e182   Loic Le Loarer   [EQL]: Proper num...
383
  			eql_kill_one_slave(queue, duplicate_slave);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384

ebd93a7da   Ying Xue   eql: use __dev_ge...
385
  		dev_hold(slave->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  		list_add(&slave->list, &queue->all_slaves);
  		queue->num_slaves++;
  		slave->dev->flags |= IFF_SLAVE;
  
  		return 0;
  	}
  
  	return -ENOSPC;
  }
  
  static int eql_enslave(struct net_device *master_dev, slaving_request_t __user *srqp)
  {
  	struct net_device *slave_dev;
  	slaving_request_t srq;
  
  	if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
  		return -EFAULT;
ebd93a7da   Ying Xue   eql: use __dev_ge...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  	slave_dev = __dev_get_by_name(&init_net, srq.slave_name);
  	if (!slave_dev)
  		return -ENODEV;
  
  	if ((master_dev->flags & IFF_UP) == IFF_UP) {
  		/* slave is not a master & not already a slave: */
  		if (!eql_is_master(slave_dev) && !eql_is_slave(slave_dev)) {
  			slave_t *s = kmalloc(sizeof(*s), GFP_KERNEL);
  			equalizer_t *eql = netdev_priv(master_dev);
  			int ret;
  
  			if (!s)
  				return -ENOMEM;
  
  			memset(s, 0, sizeof(*s));
  			s->dev = slave_dev;
  			s->priority = srq.priority;
  			s->priority_bps = srq.priority;
  			s->priority_Bps = srq.priority / 8;
  
  			spin_lock_bh(&eql->queue.lock);
  			ret = __eql_insert_slave(&eql->queue, s);
  			if (ret)
  				kfree(s);
  
  			spin_unlock_bh(&eql->queue.lock);
  
  			return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  	}
  
  	return -EINVAL;
  }
  
  static int eql_emancipate(struct net_device *master_dev, slaving_request_t __user *srqp)
  {
  	equalizer_t *eql = netdev_priv(master_dev);
  	struct net_device *slave_dev;
  	slaving_request_t srq;
  	int ret;
  
  	if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
  		return -EFAULT;
ebd93a7da   Ying Xue   eql: use __dev_ge...
446
447
448
  	slave_dev = __dev_get_by_name(&init_net, srq.slave_name);
  	if (!slave_dev)
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449

ebd93a7da   Ying Xue   eql: use __dev_ge...
450
451
452
453
454
455
456
  	ret = -EINVAL;
  	spin_lock_bh(&eql->queue.lock);
  	if (eql_is_slave(slave_dev)) {
  		slave_t *slave = __eql_find_slave_dev(&eql->queue, slave_dev);
  		if (slave) {
  			eql_kill_one_slave(&eql->queue, slave);
  			ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  	}
ebd93a7da   Ying Xue   eql: use __dev_ge...
459
  	spin_unlock_bh(&eql->queue.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  
  	return ret;
  }
  
  static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
  {
  	equalizer_t *eql = netdev_priv(dev);
  	slave_t *slave;
  	struct net_device *slave_dev;
  	slave_config_t sc;
  	int ret;
  
  	if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
  		return -EFAULT;
ebd93a7da   Ying Xue   eql: use __dev_ge...
474
  	slave_dev = __dev_get_by_name(&init_net, sc.slave_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  	if (!slave_dev)
  		return -ENODEV;
  
  	ret = -EINVAL;
  
  	spin_lock_bh(&eql->queue.lock);
  	if (eql_is_slave(slave_dev)) {
  		slave = __eql_find_slave_dev(&eql->queue, slave_dev);
  		if (slave) {
  			sc.priority = slave->priority;
  			ret = 0;
  		}
  	}
  	spin_unlock_bh(&eql->queue.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  	if (!ret && copy_to_user(scp, &sc, sizeof (slave_config_t)))
  		ret = -EFAULT;
  
  	return ret;
  }
  
  static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
  {
  	slave_t *slave;
  	equalizer_t *eql;
  	struct net_device *slave_dev;
  	slave_config_t sc;
  	int ret;
  
  	if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
  		return -EFAULT;
ebd93a7da   Ying Xue   eql: use __dev_ge...
505
  	slave_dev = __dev_get_by_name(&init_net, sc.slave_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  	if (!slave_dev)
  		return -ENODEV;
  
  	ret = -EINVAL;
  
  	eql = netdev_priv(dev);
  	spin_lock_bh(&eql->queue.lock);
  	if (eql_is_slave(slave_dev)) {
  		slave = __eql_find_slave_dev(&eql->queue, slave_dev);
  		if (slave) {
  			slave->priority = sc.priority;
  			slave->priority_bps = sc.priority;
  			slave->priority_Bps = sc.priority / 8;
  			ret = 0;
  		}
  	}
  	spin_unlock_bh(&eql->queue.lock);
  
  	return ret;
  }
  
  static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp)
  {
  	equalizer_t *eql;
  	master_config_t mc;
44467187d   Dan Rosenberg   drivers/net/eql.c...
531
  	memset(&mc, 0, sizeof(master_config_t));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
  	if (eql_is_master(dev)) {
  		eql = netdev_priv(dev);
  		mc.max_slaves = eql->max_slaves;
  		mc.min_slaves = eql->min_slaves;
  		if (copy_to_user(mcp, &mc, sizeof (master_config_t)))
  			return -EFAULT;
  		return 0;
  	}
  	return -EINVAL;
  }
  
  static int eql_s_master_cfg(struct net_device *dev, master_config_t __user *mcp)
  {
  	equalizer_t *eql;
  	master_config_t mc;
  
  	if (copy_from_user(&mc, mcp, sizeof (master_config_t)))
  		return -EFAULT;
  
  	if (eql_is_master(dev)) {
  		eql = netdev_priv(dev);
  		eql->max_slaves = mc.max_slaves;
  		eql->min_slaves = mc.min_slaves;
  		return 0;
  	}
  	return -EINVAL;
  }
  
  static struct net_device *dev_eql;
  
  static int __init eql_init_module(void)
  {
  	int err;
63f974251   Joe Perches   eql: Convert prin...
565
566
  	pr_info("%s
  ", version);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567

c835a6773   Tom Gundersen   net: set name_ass...
568
569
  	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", NET_NAME_UNKNOWN,
  			       eql_setup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
571
572
573
  	if (!dev_eql)
  		return -ENOMEM;
  
  	err = register_netdev(dev_eql);
6aa20a223   Jeff Garzik   drivers/net: Trim...
574
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
579
580
581
582
583
584
585
586
587
  		free_netdev(dev_eql);
  	return err;
  }
  
  static void __exit eql_cleanup_module(void)
  {
  	unregister_netdev(dev_eql);
  	free_netdev(dev_eql);
  }
  
  module_init(eql_init_module);
  module_exit(eql_cleanup_module);
  MODULE_LICENSE("GPL");