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