aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/ipwireless
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/tty/ipwireless
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/tty/ipwireless')
-rw-r--r--drivers/tty/ipwireless/hardware.c2
-rw-r--r--drivers/tty/ipwireless/network.c18
-rw-r--r--drivers/tty/ipwireless/setup_protocol.h2
-rw-r--r--drivers/tty/ipwireless/tty.c119
4 files changed, 77 insertions, 64 deletions
diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c
index b4ba0670dc5..0aeb5a38d29 100644
--- a/drivers/tty/ipwireless/hardware.c
+++ b/drivers/tty/ipwireless/hardware.c
@@ -1729,7 +1729,7 @@ void ipwireless_hardware_free(struct ipw_hardware *hw)
1729 1729
1730 ipwireless_stop_interrupts(hw); 1730 ipwireless_stop_interrupts(hw);
1731 1731
1732 flush_work(&hw->work_rx); 1732 flush_work_sync(&hw->work_rx);
1733 1733
1734 for (i = 0; i < NL_NUM_OF_ADDRESSES; i++) 1734 for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
1735 if (hw->packet_assembler[i] != NULL) 1735 if (hw->packet_assembler[i] != NULL)
diff --git a/drivers/tty/ipwireless/network.c b/drivers/tty/ipwireless/network.c
index c0dfb642383..f7daeea598e 100644
--- a/drivers/tty/ipwireless/network.c
+++ b/drivers/tty/ipwireless/network.c
@@ -22,7 +22,7 @@
22#include <linux/ppp_channel.h> 22#include <linux/ppp_channel.h>
23#include <linux/ppp_defs.h> 23#include <linux/ppp_defs.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/ppp-ioctl.h> 25#include <linux/if_ppp.h>
26#include <linux/skbuff.h> 26#include <linux/skbuff.h>
27 27
28#include "network.h" 28#include "network.h"
@@ -274,12 +274,7 @@ static void do_go_online(struct work_struct *work_go_online)
274 network->xaccm[0] = ~0U; 274 network->xaccm[0] = ~0U;
275 network->xaccm[3] = 0x60000000U; 275 network->xaccm[3] = 0x60000000U;
276 network->raccm = ~0U; 276 network->raccm = ~0U;
277 if (ppp_register_channel(channel) < 0) { 277 ppp_register_channel(channel);
278 printk(KERN_ERR IPWIRELESS_PCCARD_NAME
279 ": unable to register PPP channel\n");
280 kfree(channel);
281 return;
282 }
283 spin_lock_irqsave(&network->lock, flags); 278 spin_lock_irqsave(&network->lock, flags);
284 network->ppp_channel = channel; 279 network->ppp_channel = channel;
285 } 280 }
@@ -352,8 +347,6 @@ static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
352 } 347 }
353 348
354 skb = dev_alloc_skb(length + 4); 349 skb = dev_alloc_skb(length + 4);
355 if (skb == NULL)
356 return NULL;
357 skb_reserve(skb, 2); 350 skb_reserve(skb, 2);
358 memcpy(skb_put(skb, length), data, length); 351 memcpy(skb_put(skb, length), data, length);
359 352
@@ -399,8 +392,7 @@ void ipwireless_network_packet_received(struct ipw_network *network,
399 392
400 /* Send the data to the ppp_generic module. */ 393 /* Send the data to the ppp_generic module. */
401 skb = ipw_packet_received_skb(data, length); 394 skb = ipw_packet_received_skb(data, length);
402 if (skb) 395 ppp_input(network->ppp_channel, skb);
403 ppp_input(network->ppp_channel, skb);
404 } else 396 } else
405 spin_unlock_irqrestore(&network->lock, 397 spin_unlock_irqrestore(&network->lock,
406 flags); 398 flags);
@@ -438,8 +430,8 @@ void ipwireless_network_free(struct ipw_network *network)
438 network->shutting_down = 1; 430 network->shutting_down = 1;
439 431
440 ipwireless_ppp_close(network); 432 ipwireless_ppp_close(network);
441 flush_work(&network->work_go_online); 433 flush_work_sync(&network->work_go_online);
442 flush_work(&network->work_go_offline); 434 flush_work_sync(&network->work_go_offline);
443 435
444 ipwireless_stop_interrupts(network->hardware); 436 ipwireless_stop_interrupts(network->hardware);
445 ipwireless_associate_network(network->hardware, NULL); 437 ipwireless_associate_network(network->hardware, NULL);
diff --git a/drivers/tty/ipwireless/setup_protocol.h b/drivers/tty/ipwireless/setup_protocol.h
index 002c34e7252..9d6bcc77c73 100644
--- a/drivers/tty/ipwireless/setup_protocol.h
+++ b/drivers/tty/ipwireless/setup_protocol.h
@@ -59,7 +59,7 @@ struct tl_setup_config_done_msg {
59 unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */ 59 unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
60} __attribute__ ((__packed__)); 60} __attribute__ ((__packed__));
61 61
62/* Asynchronous messages */ 62/* Asyncronous messages */
63struct tl_setup_open_msg { 63struct tl_setup_open_msg {
64 unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */ 64 unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */
65 unsigned char port_no; 65 unsigned char port_no;
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index 2cde13ddf9f..ef92869502a 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -21,7 +21,7 @@
21#include <linux/mutex.h> 21#include <linux/mutex.h>
22#include <linux/ppp_defs.h> 22#include <linux/ppp_defs.h>
23#include <linux/if.h> 23#include <linux/if.h>
24#include <linux/ppp-ioctl.h> 24#include <linux/if_ppp.h>
25#include <linux/sched.h> 25#include <linux/sched.h>
26#include <linux/serial.h> 26#include <linux/serial.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
@@ -44,13 +44,14 @@
44#define TTYTYPE_RAS_RAW (2) 44#define TTYTYPE_RAS_RAW (2)
45 45
46struct ipw_tty { 46struct ipw_tty {
47 struct tty_port port;
48 int index; 47 int index;
49 struct ipw_hardware *hardware; 48 struct ipw_hardware *hardware;
50 unsigned int channel_idx; 49 unsigned int channel_idx;
51 unsigned int secondary_channel_idx; 50 unsigned int secondary_channel_idx;
52 int tty_type; 51 int tty_type;
53 struct ipw_network *network; 52 struct ipw_network *network;
53 struct tty_struct *linux_tty;
54 int open_count;
54 unsigned int control_lines; 55 unsigned int control_lines;
55 struct mutex ipw_tty_mutex; 56 struct mutex ipw_tty_mutex;
56 int tx_bytes_queued; 57 int tx_bytes_queued;
@@ -72,23 +73,50 @@ static char *tty_type_name(int tty_type)
72 return channel_names[tty_type]; 73 return channel_names[tty_type];
73} 74}
74 75
75static struct ipw_tty *get_tty(int index) 76static void report_registering(struct ipw_tty *tty)
76{ 77{
77 /* 78 char *iftype = tty_type_name(tty->tty_type);
78 * The 'ras_raw' channel is only available when 'loopback' mode 79
79 * is enabled. 80 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
80 * Number of minor starts with 16 (_RANGE * _RAS_RAW). 81 ": registering %s device ttyIPWp%d\n", iftype, tty->index);
81 */ 82}
82 if (!ipwireless_loopback && index >= 83
83 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) 84static void report_deregistering(struct ipw_tty *tty)
84 return NULL; 85{
86 char *iftype = tty_type_name(tty->tty_type);
85 87
86 return ttys[index]; 88 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
89 ": deregistering %s device ttyIPWp%d\n", iftype,
90 tty->index);
91}
92
93static struct ipw_tty *get_tty(int minor)
94{
95 if (minor < ipw_tty_driver->minor_start
96 || minor >= ipw_tty_driver->minor_start +
97 IPWIRELESS_PCMCIA_MINORS)
98 return NULL;
99 else {
100 int minor_offset = minor - ipw_tty_driver->minor_start;
101
102 /*
103 * The 'ras_raw' channel is only available when 'loopback' mode
104 * is enabled.
105 * Number of minor starts with 16 (_RANGE * _RAS_RAW).
106 */
107 if (!ipwireless_loopback &&
108 minor_offset >=
109 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
110 return NULL;
111
112 return ttys[minor_offset];
113 }
87} 114}
88 115
89static int ipw_open(struct tty_struct *linux_tty, struct file *filp) 116static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
90{ 117{
91 struct ipw_tty *tty = get_tty(linux_tty->index); 118 int minor = linux_tty->index;
119 struct ipw_tty *tty = get_tty(minor);
92 120
93 if (!tty) 121 if (!tty)
94 return -ENODEV; 122 return -ENODEV;
@@ -99,12 +127,12 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
99 mutex_unlock(&tty->ipw_tty_mutex); 127 mutex_unlock(&tty->ipw_tty_mutex);
100 return -ENODEV; 128 return -ENODEV;
101 } 129 }
102 if (tty->port.count == 0) 130 if (tty->open_count == 0)
103 tty->tx_bytes_queued = 0; 131 tty->tx_bytes_queued = 0;
104 132
105 tty->port.count++; 133 tty->open_count++;
106 134
107 tty->port.tty = linux_tty; 135 tty->linux_tty = linux_tty;
108 linux_tty->driver_data = tty; 136 linux_tty->driver_data = tty;
109 linux_tty->low_latency = 1; 137 linux_tty->low_latency = 1;
110 138
@@ -118,13 +146,13 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
118 146
119static void do_ipw_close(struct ipw_tty *tty) 147static void do_ipw_close(struct ipw_tty *tty)
120{ 148{
121 tty->port.count--; 149 tty->open_count--;
122 150
123 if (tty->port.count == 0) { 151 if (tty->open_count == 0) {
124 struct tty_struct *linux_tty = tty->port.tty; 152 struct tty_struct *linux_tty = tty->linux_tty;
125 153
126 if (linux_tty != NULL) { 154 if (linux_tty != NULL) {
127 tty->port.tty = NULL; 155 tty->linux_tty = NULL;
128 linux_tty->driver_data = NULL; 156 linux_tty->driver_data = NULL;
129 157
130 if (tty->tty_type == TTYTYPE_MODEM) 158 if (tty->tty_type == TTYTYPE_MODEM)
@@ -141,7 +169,7 @@ static void ipw_hangup(struct tty_struct *linux_tty)
141 return; 169 return;
142 170
143 mutex_lock(&tty->ipw_tty_mutex); 171 mutex_lock(&tty->ipw_tty_mutex);
144 if (tty->port.count == 0) { 172 if (tty->open_count == 0) {
145 mutex_unlock(&tty->ipw_tty_mutex); 173 mutex_unlock(&tty->ipw_tty_mutex);
146 return; 174 return;
147 } 175 }
@@ -164,13 +192,13 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
164 int work = 0; 192 int work = 0;
165 193
166 mutex_lock(&tty->ipw_tty_mutex); 194 mutex_lock(&tty->ipw_tty_mutex);
167 linux_tty = tty->port.tty; 195 linux_tty = tty->linux_tty;
168 if (linux_tty == NULL) { 196 if (linux_tty == NULL) {
169 mutex_unlock(&tty->ipw_tty_mutex); 197 mutex_unlock(&tty->ipw_tty_mutex);
170 return; 198 return;
171 } 199 }
172 200
173 if (!tty->port.count) { 201 if (!tty->open_count) {
174 mutex_unlock(&tty->ipw_tty_mutex); 202 mutex_unlock(&tty->ipw_tty_mutex);
175 return; 203 return;
176 } 204 }
@@ -212,7 +240,7 @@ static int ipw_write(struct tty_struct *linux_tty,
212 return -ENODEV; 240 return -ENODEV;
213 241
214 mutex_lock(&tty->ipw_tty_mutex); 242 mutex_lock(&tty->ipw_tty_mutex);
215 if (!tty->port.count) { 243 if (!tty->open_count) {
216 mutex_unlock(&tty->ipw_tty_mutex); 244 mutex_unlock(&tty->ipw_tty_mutex);
217 return -EINVAL; 245 return -EINVAL;
218 } 246 }
@@ -252,7 +280,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)
252 if (!tty) 280 if (!tty)
253 return -ENODEV; 281 return -ENODEV;
254 282
255 if (!tty->port.count) 283 if (!tty->open_count)
256 return -EINVAL; 284 return -EINVAL;
257 285
258 room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; 286 room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
@@ -294,7 +322,7 @@ static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
294 if (!tty) 322 if (!tty)
295 return 0; 323 return 0;
296 324
297 if (!tty->port.count) 325 if (!tty->open_count)
298 return 0; 326 return 0;
299 327
300 return tty->tx_bytes_queued; 328 return tty->tx_bytes_queued;
@@ -375,7 +403,7 @@ static int ipw_tiocmget(struct tty_struct *linux_tty)
375 if (!tty) 403 if (!tty)
376 return -ENODEV; 404 return -ENODEV;
377 405
378 if (!tty->port.count) 406 if (!tty->open_count)
379 return -EINVAL; 407 return -EINVAL;
380 408
381 return get_control_lines(tty); 409 return get_control_lines(tty);
@@ -391,7 +419,7 @@ ipw_tiocmset(struct tty_struct *linux_tty,
391 if (!tty) 419 if (!tty)
392 return -ENODEV; 420 return -ENODEV;
393 421
394 if (!tty->port.count) 422 if (!tty->open_count)
395 return -EINVAL; 423 return -EINVAL;
396 424
397 return set_control_lines(tty, set, clear); 425 return set_control_lines(tty, set, clear);
@@ -405,7 +433,7 @@ static int ipw_ioctl(struct tty_struct *linux_tty,
405 if (!tty) 433 if (!tty)
406 return -ENODEV; 434 return -ENODEV;
407 435
408 if (!tty->port.count) 436 if (!tty->open_count)
409 return -EINVAL; 437 return -EINVAL;
410 438
411 /* FIXME: Exactly how is the tty object locked here .. */ 439 /* FIXME: Exactly how is the tty object locked here .. */
@@ -474,21 +502,16 @@ static int add_tty(int j,
474 ttys[j]->network = network; 502 ttys[j]->network = network;
475 ttys[j]->tty_type = tty_type; 503 ttys[j]->tty_type = tty_type;
476 mutex_init(&ttys[j]->ipw_tty_mutex); 504 mutex_init(&ttys[j]->ipw_tty_mutex);
477 tty_port_init(&ttys[j]->port);
478 505
479 tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL); 506 tty_register_device(ipw_tty_driver, j, NULL);
480 ipwireless_associate_network_tty(network, channel_idx, ttys[j]); 507 ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
481 508
482 if (secondary_channel_idx != -1) 509 if (secondary_channel_idx != -1)
483 ipwireless_associate_network_tty(network, 510 ipwireless_associate_network_tty(network,
484 secondary_channel_idx, 511 secondary_channel_idx,
485 ttys[j]); 512 ttys[j]);
486 /* check if we provide raw device (if loopback is enabled) */ 513 if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
487 if (get_tty(j)) 514 report_registering(ttys[j]);
488 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
489 ": registering %s device ttyIPWp%d\n",
490 tty_type_name(tty_type), j);
491
492 return 0; 515 return 0;
493} 516}
494 517
@@ -547,26 +570,23 @@ void ipwireless_tty_free(struct ipw_tty *tty)
547 570
548 if (ttyj) { 571 if (ttyj) {
549 mutex_lock(&ttyj->ipw_tty_mutex); 572 mutex_lock(&ttyj->ipw_tty_mutex);
550 if (get_tty(j)) 573 if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
551 printk(KERN_INFO IPWIRELESS_PCCARD_NAME 574 report_deregistering(ttyj);
552 ": deregistering %s device ttyIPWp%d\n",
553 tty_type_name(ttyj->tty_type), j);
554 ttyj->closing = 1; 575 ttyj->closing = 1;
555 if (ttyj->port.tty != NULL) { 576 if (ttyj->linux_tty != NULL) {
556 mutex_unlock(&ttyj->ipw_tty_mutex); 577 mutex_unlock(&ttyj->ipw_tty_mutex);
557 tty_vhangup(ttyj->port.tty); 578 tty_hangup(ttyj->linux_tty);
579 /* Wait till the tty_hangup has completed */
580 flush_work_sync(&ttyj->linux_tty->hangup_work);
558 /* FIXME: Exactly how is the tty object locked here 581 /* FIXME: Exactly how is the tty object locked here
559 against a parallel ioctl etc */ 582 against a parallel ioctl etc */
560 /* FIXME2: hangup does not mean all processes
561 * are gone */
562 mutex_lock(&ttyj->ipw_tty_mutex); 583 mutex_lock(&ttyj->ipw_tty_mutex);
563 } 584 }
564 while (ttyj->port.count) 585 while (ttyj->open_count)
565 do_ipw_close(ttyj); 586 do_ipw_close(ttyj);
566 ipwireless_disassociate_network_ttys(network, 587 ipwireless_disassociate_network_ttys(network,
567 ttyj->channel_idx); 588 ttyj->channel_idx);
568 tty_unregister_device(ipw_tty_driver, j); 589 tty_unregister_device(ipw_tty_driver, j);
569 tty_port_destroy(&ttyj->port);
570 ttys[j] = NULL; 590 ttys[j] = NULL;
571 mutex_unlock(&ttyj->ipw_tty_mutex); 591 mutex_unlock(&ttyj->ipw_tty_mutex);
572 kfree(ttyj); 592 kfree(ttyj);
@@ -594,6 +614,7 @@ int ipwireless_tty_init(void)
594 if (!ipw_tty_driver) 614 if (!ipw_tty_driver)
595 return -ENOMEM; 615 return -ENOMEM;
596 616
617 ipw_tty_driver->owner = THIS_MODULE;
597 ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; 618 ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
598 ipw_tty_driver->name = "ttyIPWp"; 619 ipw_tty_driver->name = "ttyIPWp";
599 ipw_tty_driver->major = 0; 620 ipw_tty_driver->major = 0;
@@ -651,8 +672,8 @@ ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
651 */ 672 */
652 if ((old_control_lines & IPW_CONTROL_LINE_DCD) 673 if ((old_control_lines & IPW_CONTROL_LINE_DCD)
653 && !(tty->control_lines & IPW_CONTROL_LINE_DCD) 674 && !(tty->control_lines & IPW_CONTROL_LINE_DCD)
654 && tty->port.tty) { 675 && tty->linux_tty) {
655 tty_hangup(tty->port.tty); 676 tty_hangup(tty->linux_tty);
656 } 677 }
657} 678}
658 679