• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * IPWireless 3G PCMCIA Network Driver
3  *
4  * Original code
5  *   by Stephen Blackheath <stephen@blacksapphire.com>,
6  *      Ben Martel <benm@symmetric.co.nz>
7  *
8  * Copyrighted as follows:
9  *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
10  *
11  * Various driver changes and rewrites, port to new kernels
12  *   Copyright (C) 2006-2007 Jiri Kosina
13  *
14  * Misc code cleanups and updates
15  *   Copyright (C) 2007 David Sterba
16  */
17 
18 #include <linux/interrupt.h>
19 #include <linux/kernel.h>
20 #include <linux/mutex.h>
21 #include <linux/netdevice.h>
22 #include <linux/ppp_channel.h>
23 #include <linux/ppp_defs.h>
24 #include <linux/if_ppp.h>
25 #include <linux/skbuff.h>
26 
27 #include "network.h"
28 #include "hardware.h"
29 #include "main.h"
30 #include "tty.h"
31 
32 #define MAX_ASSOCIATED_TTYS 2
33 
34 #define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
35 
36 struct ipw_network {
37 	/* Hardware context, used for calls to hardware layer. */
38 	struct ipw_hardware *hardware;
39 	/* Context for kernel 'generic_ppp' functionality */
40 	struct ppp_channel *ppp_channel;
41 	/* tty context connected with IPW console */
42 	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
43 	/* True if ppp needs waking up once we're ready to xmit */
44 	int ppp_blocked;
45 	/* Number of packets queued up in hardware module. */
46 	int outgoing_packets_queued;
47 	/* Spinlock to avoid interrupts during shutdown */
48 	spinlock_t lock;
49 	struct mutex close_lock;
50 
51 	/* PPP ioctl data, not actually used anywere */
52 	unsigned int flags;
53 	unsigned int rbits;
54 	u32 xaccm[8];
55 	u32 raccm;
56 	int mru;
57 
58 	int shutting_down;
59 	unsigned int ras_control_lines;
60 
61 	struct work_struct work_go_online;
62 	struct work_struct work_go_offline;
63 };
64 
notify_packet_sent(void * callback_data,unsigned int packet_length)65 static void notify_packet_sent(void *callback_data, unsigned int packet_length)
66 {
67 	struct ipw_network *network = callback_data;
68 	unsigned long flags;
69 
70 	spin_lock_irqsave(&network->lock, flags);
71 	network->outgoing_packets_queued--;
72 	if (network->ppp_channel != NULL) {
73 		if (network->ppp_blocked) {
74 			network->ppp_blocked = 0;
75 			spin_unlock_irqrestore(&network->lock, flags);
76 			ppp_output_wakeup(network->ppp_channel);
77 			if (ipwireless_debug)
78 				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
79 				       ": ppp unblocked\n");
80 		} else
81 			spin_unlock_irqrestore(&network->lock, flags);
82 	} else
83 		spin_unlock_irqrestore(&network->lock, flags);
84 }
85 
86 /*
87  * Called by the ppp system when it has a packet to send to the hardware.
88  */
ipwireless_ppp_start_xmit(struct ppp_channel * ppp_channel,struct sk_buff * skb)89 static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
90 				     struct sk_buff *skb)
91 {
92 	struct ipw_network *network = ppp_channel->private;
93 	unsigned long flags;
94 
95 	spin_lock_irqsave(&network->lock, flags);
96 	if (network->outgoing_packets_queued < ipwireless_out_queue) {
97 		unsigned char *buf;
98 		static unsigned char header[] = {
99 			PPP_ALLSTATIONS, /* 0xff */
100 			PPP_UI,		 /* 0x03 */
101 		};
102 		int ret;
103 
104 		network->outgoing_packets_queued++;
105 		spin_unlock_irqrestore(&network->lock, flags);
106 
107 		/*
108 		 * If we have the requested amount of headroom in the skb we
109 		 * were handed, then we can add the header efficiently.
110 		 */
111 		if (skb_headroom(skb) >= 2) {
112 			memcpy(skb_push(skb, 2), header, 2);
113 			ret = ipwireless_send_packet(network->hardware,
114 					       IPW_CHANNEL_RAS, skb->data,
115 					       skb->len,
116 					       notify_packet_sent,
117 					       network);
118 			if (ret == -1) {
119 				skb_pull(skb, 2);
120 				return 0;
121 			}
122 		} else {
123 			/* Otherwise (rarely) we do it inefficiently. */
124 			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
125 			if (!buf)
126 				return 0;
127 			memcpy(buf + 2, skb->data, skb->len);
128 			memcpy(buf, header, 2);
129 			ret = ipwireless_send_packet(network->hardware,
130 					       IPW_CHANNEL_RAS, buf,
131 					       skb->len + 2,
132 					       notify_packet_sent,
133 					       network);
134 			kfree(buf);
135 			if (ret == -1)
136 				return 0;
137 		}
138 		kfree_skb(skb);
139 		return 1;
140 	} else {
141 		/*
142 		 * Otherwise reject the packet, and flag that the ppp system
143 		 * needs to be unblocked once we are ready to send.
144 		 */
145 		network->ppp_blocked = 1;
146 		spin_unlock_irqrestore(&network->lock, flags);
147 		if (ipwireless_debug)
148 			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
149 		return 0;
150 	}
151 }
152 
153 /* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
ipwireless_ppp_ioctl(struct ppp_channel * ppp_channel,unsigned int cmd,unsigned long arg)154 static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
155 				unsigned int cmd, unsigned long arg)
156 {
157 	struct ipw_network *network = ppp_channel->private;
158 	int err, val;
159 	u32 accm[8];
160 	int __user *user_arg = (int __user *) arg;
161 
162 	err = -EFAULT;
163 	switch (cmd) {
164 	case PPPIOCGFLAGS:
165 		val = network->flags | network->rbits;
166 		if (put_user(val, user_arg))
167 			break;
168 		err = 0;
169 		break;
170 
171 	case PPPIOCSFLAGS:
172 		if (get_user(val, user_arg))
173 			break;
174 		network->flags = val & ~SC_RCV_BITS;
175 		network->rbits = val & SC_RCV_BITS;
176 		err = 0;
177 		break;
178 
179 	case PPPIOCGASYNCMAP:
180 		if (put_user(network->xaccm[0], user_arg))
181 			break;
182 		err = 0;
183 		break;
184 
185 	case PPPIOCSASYNCMAP:
186 		if (get_user(network->xaccm[0], user_arg))
187 			break;
188 		err = 0;
189 		break;
190 
191 	case PPPIOCGRASYNCMAP:
192 		if (put_user(network->raccm, user_arg))
193 			break;
194 		err = 0;
195 		break;
196 
197 	case PPPIOCSRASYNCMAP:
198 		if (get_user(network->raccm, user_arg))
199 			break;
200 		err = 0;
201 		break;
202 
203 	case PPPIOCGXASYNCMAP:
204 		if (copy_to_user((void __user *) arg, network->xaccm,
205 					sizeof(network->xaccm)))
206 			break;
207 		err = 0;
208 		break;
209 
210 	case PPPIOCSXASYNCMAP:
211 		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
212 			break;
213 		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
214 		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
215 		memcpy(network->xaccm, accm, sizeof(network->xaccm));
216 		err = 0;
217 		break;
218 
219 	case PPPIOCGMRU:
220 		if (put_user(network->mru, user_arg))
221 			break;
222 		err = 0;
223 		break;
224 
225 	case PPPIOCSMRU:
226 		if (get_user(val, user_arg))
227 			break;
228 		if (val < PPP_MRU)
229 			val = PPP_MRU;
230 		network->mru = val;
231 		err = 0;
232 		break;
233 
234 	default:
235 		err = -ENOTTY;
236 	}
237 
238 	return err;
239 }
240 
241 static struct ppp_channel_ops ipwireless_ppp_channel_ops = {
242 	.start_xmit = ipwireless_ppp_start_xmit,
243 	.ioctl      = ipwireless_ppp_ioctl
244 };
245 
do_go_online(struct work_struct * work_go_online)246 static void do_go_online(struct work_struct *work_go_online)
247 {
248 	struct ipw_network *network =
249 		container_of(work_go_online, struct ipw_network,
250 				work_go_online);
251 	unsigned long flags;
252 
253 	spin_lock_irqsave(&network->lock, flags);
254 	if (!network->ppp_channel) {
255 		struct ppp_channel *channel;
256 
257 		spin_unlock_irqrestore(&network->lock, flags);
258 		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
259 		if (!channel) {
260 			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
261 					": unable to allocate PPP channel\n");
262 			return;
263 		}
264 		channel->private = network;
265 		channel->mtu = 16384;	/* Wild guess */
266 		channel->hdrlen = 2;
267 		channel->ops = &ipwireless_ppp_channel_ops;
268 
269 		network->flags = 0;
270 		network->rbits = 0;
271 		network->mru = PPP_MRU;
272 		memset(network->xaccm, 0, sizeof(network->xaccm));
273 		network->xaccm[0] = ~0U;
274 		network->xaccm[3] = 0x60000000U;
275 		network->raccm = ~0U;
276 		ppp_register_channel(channel);
277 		spin_lock_irqsave(&network->lock, flags);
278 		network->ppp_channel = channel;
279 	}
280 	spin_unlock_irqrestore(&network->lock, flags);
281 }
282 
do_go_offline(struct work_struct * work_go_offline)283 static void do_go_offline(struct work_struct *work_go_offline)
284 {
285 	struct ipw_network *network =
286 		container_of(work_go_offline, struct ipw_network,
287 				work_go_offline);
288 	unsigned long flags;
289 
290 	mutex_lock(&network->close_lock);
291 	spin_lock_irqsave(&network->lock, flags);
292 	if (network->ppp_channel != NULL) {
293 		struct ppp_channel *channel = network->ppp_channel;
294 
295 		network->ppp_channel = NULL;
296 		spin_unlock_irqrestore(&network->lock, flags);
297 		mutex_unlock(&network->close_lock);
298 		ppp_unregister_channel(channel);
299 	} else {
300 		spin_unlock_irqrestore(&network->lock, flags);
301 		mutex_unlock(&network->close_lock);
302 	}
303 }
304 
ipwireless_network_notify_control_line_change(struct ipw_network * network,unsigned int channel_idx,unsigned int control_lines,unsigned int changed_mask)305 void ipwireless_network_notify_control_line_change(struct ipw_network *network,
306 						   unsigned int channel_idx,
307 						   unsigned int control_lines,
308 						   unsigned int changed_mask)
309 {
310 	int i;
311 
312 	if (channel_idx == IPW_CHANNEL_RAS)
313 		network->ras_control_lines = control_lines;
314 
315 	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
316 		struct ipw_tty *tty =
317 			network->associated_ttys[channel_idx][i];
318 
319 		/*
320 		 * If it's associated with a tty (other than the RAS channel
321 		 * when we're online), then send the data to that tty.  The RAS
322 		 * channel's data is handled above - it always goes through
323 		 * ppp_generic.
324 		 */
325 		if (tty)
326 			ipwireless_tty_notify_control_line_change(tty,
327 								  channel_idx,
328 								  control_lines,
329 								  changed_mask);
330 	}
331 }
332 
333 /*
334  * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
335  * bytes, which are required on sent packet, but not always present on received
336  * packets
337  */
ipw_packet_received_skb(unsigned char * data,unsigned int length)338 static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
339 					       unsigned int length)
340 {
341 	struct sk_buff *skb;
342 
343 	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
344 		length -= 2;
345 		data += 2;
346 	}
347 
348 	skb = dev_alloc_skb(length + 4);
349 	skb_reserve(skb, 2);
350 	memcpy(skb_put(skb, length), data, length);
351 
352 	return skb;
353 }
354 
ipwireless_network_packet_received(struct ipw_network * network,unsigned int channel_idx,unsigned char * data,unsigned int length)355 void ipwireless_network_packet_received(struct ipw_network *network,
356 					unsigned int channel_idx,
357 					unsigned char *data,
358 					unsigned int length)
359 {
360 	int i;
361 	unsigned long flags;
362 
363 	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
364 		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
365 
366 		if (!tty)
367 			continue;
368 
369 		/*
370 		 * If it's associated with a tty (other than the RAS channel
371 		 * when we're online), then send the data to that tty.  The RAS
372 		 * channel's data is handled above - it always goes through
373 		 * ppp_generic.
374 		 */
375 		if (channel_idx == IPW_CHANNEL_RAS
376 				&& (network->ras_control_lines &
377 					IPW_CONTROL_LINE_DCD) != 0
378 				&& ipwireless_tty_is_modem(tty)) {
379 			/*
380 			 * If data came in on the RAS channel and this tty is
381 			 * the modem tty, and we are online, then we send it to
382 			 * the PPP layer.
383 			 */
384 			mutex_lock(&network->close_lock);
385 			spin_lock_irqsave(&network->lock, flags);
386 			if (network->ppp_channel != NULL) {
387 				struct sk_buff *skb;
388 
389 				spin_unlock_irqrestore(&network->lock,
390 						flags);
391 
392 				/* Send the data to the ppp_generic module. */
393 				skb = ipw_packet_received_skb(data, length);
394 				ppp_input(network->ppp_channel, skb);
395 			} else
396 				spin_unlock_irqrestore(&network->lock,
397 						flags);
398 			mutex_unlock(&network->close_lock);
399 		}
400 		/* Otherwise we send it out the tty. */
401 		else
402 			ipwireless_tty_received(tty, data, length);
403 	}
404 }
405 
ipwireless_network_create(struct ipw_hardware * hw)406 struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
407 {
408 	struct ipw_network *network =
409 		kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
410 
411 	if (!network)
412 		return NULL;
413 
414 	spin_lock_init(&network->lock);
415 	mutex_init(&network->close_lock);
416 
417 	network->hardware = hw;
418 
419 	INIT_WORK(&network->work_go_online, do_go_online);
420 	INIT_WORK(&network->work_go_offline, do_go_offline);
421 
422 	ipwireless_associate_network(hw, network);
423 
424 	return network;
425 }
426 
ipwireless_network_free(struct ipw_network * network)427 void ipwireless_network_free(struct ipw_network *network)
428 {
429 	network->shutting_down = 1;
430 
431 	ipwireless_ppp_close(network);
432 	flush_scheduled_work();
433 
434 	ipwireless_stop_interrupts(network->hardware);
435 	ipwireless_associate_network(network->hardware, NULL);
436 
437 	kfree(network);
438 }
439 
ipwireless_associate_network_tty(struct ipw_network * network,unsigned int channel_idx,struct ipw_tty * tty)440 void ipwireless_associate_network_tty(struct ipw_network *network,
441 				      unsigned int channel_idx,
442 				      struct ipw_tty *tty)
443 {
444 	int i;
445 
446 	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
447 		if (network->associated_ttys[channel_idx][i] == NULL) {
448 			network->associated_ttys[channel_idx][i] = tty;
449 			break;
450 		}
451 }
452 
ipwireless_disassociate_network_ttys(struct ipw_network * network,unsigned int channel_idx)453 void ipwireless_disassociate_network_ttys(struct ipw_network *network,
454 					  unsigned int channel_idx)
455 {
456 	int i;
457 
458 	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
459 		network->associated_ttys[channel_idx][i] = NULL;
460 }
461 
ipwireless_ppp_open(struct ipw_network * network)462 void ipwireless_ppp_open(struct ipw_network *network)
463 {
464 	if (ipwireless_debug)
465 		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
466 	schedule_work(&network->work_go_online);
467 }
468 
ipwireless_ppp_close(struct ipw_network * network)469 void ipwireless_ppp_close(struct ipw_network *network)
470 {
471 	/* Disconnect from the wireless network. */
472 	if (ipwireless_debug)
473 		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
474 	schedule_work(&network->work_go_offline);
475 }
476 
ipwireless_ppp_channel_index(struct ipw_network * network)477 int ipwireless_ppp_channel_index(struct ipw_network *network)
478 {
479 	int ret = -1;
480 	unsigned long flags;
481 
482 	spin_lock_irqsave(&network->lock, flags);
483 	if (network->ppp_channel != NULL)
484 		ret = ppp_channel_index(network->ppp_channel);
485 	spin_unlock_irqrestore(&network->lock, flags);
486 
487 	return ret;
488 }
489 
ipwireless_ppp_unit_number(struct ipw_network * network)490 int ipwireless_ppp_unit_number(struct ipw_network *network)
491 {
492 	int ret = -1;
493 	unsigned long flags;
494 
495 	spin_lock_irqsave(&network->lock, flags);
496 	if (network->ppp_channel != NULL)
497 		ret = ppp_unit_number(network->ppp_channel);
498 	spin_unlock_irqrestore(&network->lock, flags);
499 
500 	return ret;
501 }
502 
ipwireless_ppp_mru(const struct ipw_network * network)503 int ipwireless_ppp_mru(const struct ipw_network *network)
504 {
505 	return network->mru;
506 }
507