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