diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 02:09:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 02:09:27 -0400 |
commit | d5ef642355bdd9b383ff5c18cbc6102a06eecbaf (patch) | |
tree | fcf78d33c1790c6c24efbfd0c3695f7874f053d7 /drivers/tty/n_gsm.c | |
parent | f549953c15deab4c54708b39af86d4edecc6cddc (diff) | |
parent | def90f4239f094f3846c108c1c41a4cd55c33e8e (diff) |
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (26 commits)
amba pl011: workaround for uart registers lockup
n_gsm: fix the wrong FCS handling
pch_uart: add missing comment about OKI ML7223
pch_uart: Add MSI support
tty: fix "IRQ45: nobody cared"
PTI feature to allow user to name and mark masterchannel request.
0 for o PTI Makefile bug.
tty: serial: samsung.c remove legacy PM code.
SERIAL: SC26xx: Fix link error.
serial: mrst_max3110: initialize waitqueue earlier
mrst_max3110: Change max missing message priority.
tty: s5pv210: Add delay loop on fifo reset function for UART
tty/serial: Fix XSCALE serial ports, e.g. ce4100
serial: bfin_5xx: fix off-by-one with resource size
drivers/tty: use printk_ratelimited() instead of printk_ratelimit()
tty: n_gsm: Added refcount usage to gsm_mux and gsm_dlci structs
tty: n_gsm: Add raw-ip support
tty: n_gsm: expose gsmtty device nodes at ldisc open time
pch_phub: Fix register miss-setting issue
serial: 8250, increase PASS_LIMIT
...
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r-- | drivers/tty/n_gsm.c | 401 |
1 files changed, 372 insertions, 29 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 19b4ae052af8..8a50e4eebf18 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -58,6 +58,10 @@ | |||
58 | #include <linux/serial.h> | 58 | #include <linux/serial.h> |
59 | #include <linux/kfifo.h> | 59 | #include <linux/kfifo.h> |
60 | #include <linux/skbuff.h> | 60 | #include <linux/skbuff.h> |
61 | #include <net/arp.h> | ||
62 | #include <linux/ip.h> | ||
63 | #include <linux/netdevice.h> | ||
64 | #include <linux/etherdevice.h> | ||
61 | #include <linux/gsmmux.h> | 65 | #include <linux/gsmmux.h> |
62 | 66 | ||
63 | static int debug; | 67 | static int debug; |
@@ -77,8 +81,24 @@ module_param(debug, int, 0600); | |||
77 | * Semi-arbitrary buffer size limits. 0710 is normally run with 32-64 byte | 81 | * Semi-arbitrary buffer size limits. 0710 is normally run with 32-64 byte |
78 | * limits so this is plenty | 82 | * limits so this is plenty |
79 | */ | 83 | */ |
80 | #define MAX_MRU 512 | 84 | #define MAX_MRU 1500 |
81 | #define MAX_MTU 512 | 85 | #define MAX_MTU 1500 |
86 | #define GSM_NET_TX_TIMEOUT (HZ*10) | ||
87 | |||
88 | /** | ||
89 | * struct gsm_mux_net - network interface | ||
90 | * @struct gsm_dlci* dlci | ||
91 | * @struct net_device_stats stats; | ||
92 | * | ||
93 | * Created when net interface is initialized. | ||
94 | **/ | ||
95 | struct gsm_mux_net { | ||
96 | struct kref ref; | ||
97 | struct gsm_dlci *dlci; | ||
98 | struct net_device_stats stats; | ||
99 | }; | ||
100 | |||
101 | #define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats) | ||
82 | 102 | ||
83 | /* | 103 | /* |
84 | * Each block of data we have queued to go out is in the form of | 104 | * Each block of data we have queued to go out is in the form of |
@@ -113,6 +133,8 @@ struct gsm_dlci { | |||
113 | #define DLCI_OPENING 1 /* Sending SABM not seen UA */ | 133 | #define DLCI_OPENING 1 /* Sending SABM not seen UA */ |
114 | #define DLCI_OPEN 2 /* SABM/UA complete */ | 134 | #define DLCI_OPEN 2 /* SABM/UA complete */ |
115 | #define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ | 135 | #define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ |
136 | struct kref ref; /* freed from port or mux close */ | ||
137 | struct mutex mutex; | ||
116 | 138 | ||
117 | /* Link layer */ | 139 | /* Link layer */ |
118 | spinlock_t lock; /* Protects the internal state */ | 140 | spinlock_t lock; /* Protects the internal state */ |
@@ -123,6 +145,7 @@ struct gsm_dlci { | |||
123 | struct kfifo *fifo; /* Queue fifo for the DLCI */ | 145 | struct kfifo *fifo; /* Queue fifo for the DLCI */ |
124 | struct kfifo _fifo; /* For new fifo API porting only */ | 146 | struct kfifo _fifo; /* For new fifo API porting only */ |
125 | int adaption; /* Adaption layer in use */ | 147 | int adaption; /* Adaption layer in use */ |
148 | int prev_adaption; | ||
126 | u32 modem_rx; /* Our incoming virtual modem lines */ | 149 | u32 modem_rx; /* Our incoming virtual modem lines */ |
127 | u32 modem_tx; /* Our outgoing modem lines */ | 150 | u32 modem_tx; /* Our outgoing modem lines */ |
128 | int dead; /* Refuse re-open */ | 151 | int dead; /* Refuse re-open */ |
@@ -134,6 +157,8 @@ struct gsm_dlci { | |||
134 | struct sk_buff_head skb_list; /* Queued frames */ | 157 | struct sk_buff_head skb_list; /* Queued frames */ |
135 | /* Data handling callback */ | 158 | /* Data handling callback */ |
136 | void (*data)(struct gsm_dlci *dlci, u8 *data, int len); | 159 | void (*data)(struct gsm_dlci *dlci, u8 *data, int len); |
160 | void (*prev_data)(struct gsm_dlci *dlci, u8 *data, int len); | ||
161 | struct net_device *net; /* network interface, if created */ | ||
137 | }; | 162 | }; |
138 | 163 | ||
139 | /* DLCI 0, 62/63 are special or reseved see gsmtty_open */ | 164 | /* DLCI 0, 62/63 are special or reseved see gsmtty_open */ |
@@ -169,6 +194,8 @@ struct gsm_control { | |||
169 | struct gsm_mux { | 194 | struct gsm_mux { |
170 | struct tty_struct *tty; /* The tty our ldisc is bound to */ | 195 | struct tty_struct *tty; /* The tty our ldisc is bound to */ |
171 | spinlock_t lock; | 196 | spinlock_t lock; |
197 | unsigned int num; | ||
198 | struct kref ref; | ||
172 | 199 | ||
173 | /* Events on the GSM channel */ | 200 | /* Events on the GSM channel */ |
174 | wait_queue_head_t event; | 201 | wait_queue_head_t event; |
@@ -250,6 +277,8 @@ struct gsm_mux { | |||
250 | static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */ | 277 | static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */ |
251 | static spinlock_t gsm_mux_lock; | 278 | static spinlock_t gsm_mux_lock; |
252 | 279 | ||
280 | static struct tty_driver *gsm_tty_driver; | ||
281 | |||
253 | /* | 282 | /* |
254 | * This section of the driver logic implements the GSM encodings | 283 | * This section of the driver logic implements the GSM encodings |
255 | * both the basic and the 'advanced'. Reliable transport is not | 284 | * both the basic and the 'advanced'. Reliable transport is not |
@@ -878,8 +907,10 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, | |||
878 | memcpy(dp, dlci->skb->data, len); | 907 | memcpy(dp, dlci->skb->data, len); |
879 | skb_pull(dlci->skb, len); | 908 | skb_pull(dlci->skb, len); |
880 | __gsm_data_queue(dlci, msg); | 909 | __gsm_data_queue(dlci, msg); |
881 | if (last) | 910 | if (last) { |
911 | kfree_skb(dlci->skb); | ||
882 | dlci->skb = NULL; | 912 | dlci->skb = NULL; |
913 | } | ||
883 | return size; | 914 | return size; |
884 | } | 915 | } |
885 | 916 | ||
@@ -912,7 +943,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) | |||
912 | i++; | 943 | i++; |
913 | continue; | 944 | continue; |
914 | } | 945 | } |
915 | if (dlci->adaption < 3) | 946 | if (dlci->adaption < 3 && !dlci->net) |
916 | len = gsm_dlci_data_output(gsm, dlci); | 947 | len = gsm_dlci_data_output(gsm, dlci); |
917 | else | 948 | else |
918 | len = gsm_dlci_data_output_framed(gsm, dlci); | 949 | len = gsm_dlci_data_output_framed(gsm, dlci); |
@@ -939,9 +970,12 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) | |||
939 | 970 | ||
940 | spin_lock_irqsave(&dlci->gsm->tx_lock, flags); | 971 | spin_lock_irqsave(&dlci->gsm->tx_lock, flags); |
941 | /* If we have nothing running then we need to fire up */ | 972 | /* If we have nothing running then we need to fire up */ |
942 | if (dlci->gsm->tx_bytes == 0) | 973 | if (dlci->gsm->tx_bytes == 0) { |
943 | gsm_dlci_data_output(dlci->gsm, dlci); | 974 | if (dlci->net) |
944 | else if (dlci->gsm->tx_bytes < TX_THRESH_LO) | 975 | gsm_dlci_data_output_framed(dlci->gsm, dlci); |
976 | else | ||
977 | gsm_dlci_data_output(dlci->gsm, dlci); | ||
978 | } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) | ||
945 | gsm_dlci_data_sweep(dlci->gsm); | 979 | gsm_dlci_data_sweep(dlci->gsm); |
946 | spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); | 980 | spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); |
947 | } | 981 | } |
@@ -1588,6 +1622,8 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) | |||
1588 | if (dlci == NULL) | 1622 | if (dlci == NULL) |
1589 | return NULL; | 1623 | return NULL; |
1590 | spin_lock_init(&dlci->lock); | 1624 | spin_lock_init(&dlci->lock); |
1625 | kref_init(&dlci->ref); | ||
1626 | mutex_init(&dlci->mutex); | ||
1591 | dlci->fifo = &dlci->_fifo; | 1627 | dlci->fifo = &dlci->_fifo; |
1592 | if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { | 1628 | if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { |
1593 | kfree(dlci); | 1629 | kfree(dlci); |
@@ -1613,26 +1649,52 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) | |||
1613 | } | 1649 | } |
1614 | 1650 | ||
1615 | /** | 1651 | /** |
1616 | * gsm_dlci_free - release DLCI | 1652 | * gsm_dlci_free - free DLCI |
1653 | * @dlci: DLCI to free | ||
1654 | * | ||
1655 | * Free up a DLCI. | ||
1656 | * | ||
1657 | * Can sleep. | ||
1658 | */ | ||
1659 | static void gsm_dlci_free(struct kref *ref) | ||
1660 | { | ||
1661 | struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref); | ||
1662 | |||
1663 | del_timer_sync(&dlci->t1); | ||
1664 | dlci->gsm->dlci[dlci->addr] = NULL; | ||
1665 | kfifo_free(dlci->fifo); | ||
1666 | while ((dlci->skb = skb_dequeue(&dlci->skb_list))) | ||
1667 | kfree_skb(dlci->skb); | ||
1668 | kfree(dlci); | ||
1669 | } | ||
1670 | |||
1671 | static inline void dlci_get(struct gsm_dlci *dlci) | ||
1672 | { | ||
1673 | kref_get(&dlci->ref); | ||
1674 | } | ||
1675 | |||
1676 | static inline void dlci_put(struct gsm_dlci *dlci) | ||
1677 | { | ||
1678 | kref_put(&dlci->ref, gsm_dlci_free); | ||
1679 | } | ||
1680 | |||
1681 | /** | ||
1682 | * gsm_dlci_release - release DLCI | ||
1617 | * @dlci: DLCI to destroy | 1683 | * @dlci: DLCI to destroy |
1618 | * | 1684 | * |
1619 | * Free up a DLCI. Currently to keep the lifetime rules sane we only | 1685 | * Release a DLCI. Actual free is deferred until either |
1620 | * clean up DLCI objects when the MUX closes rather than as the port | 1686 | * mux is closed or tty is closed - whichever is last. |
1621 | * is closed down on both the tty and mux levels. | ||
1622 | * | 1687 | * |
1623 | * Can sleep. | 1688 | * Can sleep. |
1624 | */ | 1689 | */ |
1625 | static void gsm_dlci_free(struct gsm_dlci *dlci) | 1690 | static void gsm_dlci_release(struct gsm_dlci *dlci) |
1626 | { | 1691 | { |
1627 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); | 1692 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); |
1628 | if (tty) { | 1693 | if (tty) { |
1629 | tty_vhangup(tty); | 1694 | tty_vhangup(tty); |
1630 | tty_kref_put(tty); | 1695 | tty_kref_put(tty); |
1631 | } | 1696 | } |
1632 | del_timer_sync(&dlci->t1); | 1697 | dlci_put(dlci); |
1633 | dlci->gsm->dlci[dlci->addr] = NULL; | ||
1634 | kfifo_free(dlci->fifo); | ||
1635 | kfree(dlci); | ||
1636 | } | 1698 | } |
1637 | 1699 | ||
1638 | /* | 1700 | /* |
@@ -1823,10 +1885,6 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) | |||
1823 | break; | 1885 | break; |
1824 | case GSM_FCS: /* FCS follows the packet */ | 1886 | case GSM_FCS: /* FCS follows the packet */ |
1825 | gsm->received_fcs = c; | 1887 | gsm->received_fcs = c; |
1826 | if (c == GSM0_SOF) { | ||
1827 | gsm->state = GSM_SEARCH; | ||
1828 | break; | ||
1829 | } | ||
1830 | gsm_queue(gsm); | 1888 | gsm_queue(gsm); |
1831 | gsm->state = GSM_SSOF; | 1889 | gsm->state = GSM_SSOF; |
1832 | break; | 1890 | break; |
@@ -1970,7 +2028,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) | |||
1970 | /* Free up any link layer users */ | 2028 | /* Free up any link layer users */ |
1971 | for (i = 0; i < NUM_DLCI; i++) | 2029 | for (i = 0; i < NUM_DLCI; i++) |
1972 | if (gsm->dlci[i]) | 2030 | if (gsm->dlci[i]) |
1973 | gsm_dlci_free(gsm->dlci[i]); | 2031 | gsm_dlci_release(gsm->dlci[i]); |
1974 | /* Now wipe the queues */ | 2032 | /* Now wipe the queues */ |
1975 | for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) { | 2033 | for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) { |
1976 | gsm->tx_head = txq->next; | 2034 | gsm->tx_head = txq->next; |
@@ -2010,6 +2068,7 @@ int gsm_activate_mux(struct gsm_mux *gsm) | |||
2010 | spin_lock(&gsm_mux_lock); | 2068 | spin_lock(&gsm_mux_lock); |
2011 | for (i = 0; i < MAX_MUX; i++) { | 2069 | for (i = 0; i < MAX_MUX; i++) { |
2012 | if (gsm_mux[i] == NULL) { | 2070 | if (gsm_mux[i] == NULL) { |
2071 | gsm->num = i; | ||
2013 | gsm_mux[i] = gsm; | 2072 | gsm_mux[i] = gsm; |
2014 | break; | 2073 | break; |
2015 | } | 2074 | } |
@@ -2030,8 +2089,7 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux); | |||
2030 | * gsm_free_mux - free up a mux | 2089 | * gsm_free_mux - free up a mux |
2031 | * @mux: mux to free | 2090 | * @mux: mux to free |
2032 | * | 2091 | * |
2033 | * Dispose of allocated resources for a dead mux. No refcounting | 2092 | * Dispose of allocated resources for a dead mux |
2034 | * at present so the mux must be truly dead. | ||
2035 | */ | 2093 | */ |
2036 | void gsm_free_mux(struct gsm_mux *gsm) | 2094 | void gsm_free_mux(struct gsm_mux *gsm) |
2037 | { | 2095 | { |
@@ -2042,6 +2100,28 @@ void gsm_free_mux(struct gsm_mux *gsm) | |||
2042 | EXPORT_SYMBOL_GPL(gsm_free_mux); | 2100 | EXPORT_SYMBOL_GPL(gsm_free_mux); |
2043 | 2101 | ||
2044 | /** | 2102 | /** |
2103 | * gsm_free_muxr - free up a mux | ||
2104 | * @mux: mux to free | ||
2105 | * | ||
2106 | * Dispose of allocated resources for a dead mux | ||
2107 | */ | ||
2108 | static void gsm_free_muxr(struct kref *ref) | ||
2109 | { | ||
2110 | struct gsm_mux *gsm = container_of(ref, struct gsm_mux, ref); | ||
2111 | gsm_free_mux(gsm); | ||
2112 | } | ||
2113 | |||
2114 | static inline void mux_get(struct gsm_mux *gsm) | ||
2115 | { | ||
2116 | kref_get(&gsm->ref); | ||
2117 | } | ||
2118 | |||
2119 | static inline void mux_put(struct gsm_mux *gsm) | ||
2120 | { | ||
2121 | kref_put(&gsm->ref, gsm_free_muxr); | ||
2122 | } | ||
2123 | |||
2124 | /** | ||
2045 | * gsm_alloc_mux - allocate a mux | 2125 | * gsm_alloc_mux - allocate a mux |
2046 | * | 2126 | * |
2047 | * Creates a new mux ready for activation. | 2127 | * Creates a new mux ready for activation. |
@@ -2064,12 +2144,12 @@ struct gsm_mux *gsm_alloc_mux(void) | |||
2064 | return NULL; | 2144 | return NULL; |
2065 | } | 2145 | } |
2066 | spin_lock_init(&gsm->lock); | 2146 | spin_lock_init(&gsm->lock); |
2147 | kref_init(&gsm->ref); | ||
2067 | 2148 | ||
2068 | gsm->t1 = T1; | 2149 | gsm->t1 = T1; |
2069 | gsm->t2 = T2; | 2150 | gsm->t2 = T2; |
2070 | gsm->n2 = N2; | 2151 | gsm->n2 = N2; |
2071 | gsm->ftype = UIH; | 2152 | gsm->ftype = UIH; |
2072 | gsm->initiator = 0; | ||
2073 | gsm->adaption = 1; | 2153 | gsm->adaption = 1; |
2074 | gsm->encoding = 1; | 2154 | gsm->encoding = 1; |
2075 | gsm->mru = 64; /* Default to encoding 1 so these should be 64 */ | 2155 | gsm->mru = 64; /* Default to encoding 1 so these should be 64 */ |
@@ -2115,13 +2195,20 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) | |||
2115 | 2195 | ||
2116 | static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | 2196 | static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) |
2117 | { | 2197 | { |
2118 | int ret; | 2198 | int ret, i; |
2199 | int base = gsm->num << 6; /* Base for this MUX */ | ||
2119 | 2200 | ||
2120 | gsm->tty = tty_kref_get(tty); | 2201 | gsm->tty = tty_kref_get(tty); |
2121 | gsm->output = gsmld_output; | 2202 | gsm->output = gsmld_output; |
2122 | ret = gsm_activate_mux(gsm); | 2203 | ret = gsm_activate_mux(gsm); |
2123 | if (ret != 0) | 2204 | if (ret != 0) |
2124 | tty_kref_put(gsm->tty); | 2205 | tty_kref_put(gsm->tty); |
2206 | else { | ||
2207 | /* Don't register device 0 - this is the control channel and not | ||
2208 | a usable tty interface */ | ||
2209 | for (i = 1; i < NUM_DLCI; i++) | ||
2210 | tty_register_device(gsm_tty_driver, base + i, NULL); | ||
2211 | } | ||
2125 | return ret; | 2212 | return ret; |
2126 | } | 2213 | } |
2127 | 2214 | ||
@@ -2136,7 +2223,12 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | |||
2136 | 2223 | ||
2137 | static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | 2224 | static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) |
2138 | { | 2225 | { |
2226 | int i; | ||
2227 | int base = gsm->num << 6; /* Base for this MUX */ | ||
2228 | |||
2139 | WARN_ON(tty != gsm->tty); | 2229 | WARN_ON(tty != gsm->tty); |
2230 | for (i = 1; i < NUM_DLCI; i++) | ||
2231 | tty_unregister_device(gsm_tty_driver, base + i); | ||
2140 | gsm_cleanup_mux(gsm); | 2232 | gsm_cleanup_mux(gsm); |
2141 | tty_kref_put(gsm->tty); | 2233 | tty_kref_put(gsm->tty); |
2142 | gsm->tty = NULL; | 2234 | gsm->tty = NULL; |
@@ -2224,7 +2316,7 @@ static void gsmld_close(struct tty_struct *tty) | |||
2224 | 2316 | ||
2225 | gsmld_flush_buffer(tty); | 2317 | gsmld_flush_buffer(tty); |
2226 | /* Do other clean up here */ | 2318 | /* Do other clean up here */ |
2227 | gsm_free_mux(gsm); | 2319 | mux_put(gsm); |
2228 | } | 2320 | } |
2229 | 2321 | ||
2230 | /** | 2322 | /** |
@@ -2476,6 +2568,220 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file, | |||
2476 | } | 2568 | } |
2477 | } | 2569 | } |
2478 | 2570 | ||
2571 | /* | ||
2572 | * Network interface | ||
2573 | * | ||
2574 | */ | ||
2575 | |||
2576 | static int gsm_mux_net_open(struct net_device *net) | ||
2577 | { | ||
2578 | pr_debug("%s called\n", __func__); | ||
2579 | netif_start_queue(net); | ||
2580 | return 0; | ||
2581 | } | ||
2582 | |||
2583 | static int gsm_mux_net_close(struct net_device *net) | ||
2584 | { | ||
2585 | netif_stop_queue(net); | ||
2586 | return 0; | ||
2587 | } | ||
2588 | |||
2589 | static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net) | ||
2590 | { | ||
2591 | return &((struct gsm_mux_net *)netdev_priv(net))->stats; | ||
2592 | } | ||
2593 | static void dlci_net_free(struct gsm_dlci *dlci) | ||
2594 | { | ||
2595 | if (!dlci->net) { | ||
2596 | WARN_ON(1); | ||
2597 | return; | ||
2598 | } | ||
2599 | dlci->adaption = dlci->prev_adaption; | ||
2600 | dlci->data = dlci->prev_data; | ||
2601 | free_netdev(dlci->net); | ||
2602 | dlci->net = NULL; | ||
2603 | } | ||
2604 | static void net_free(struct kref *ref) | ||
2605 | { | ||
2606 | struct gsm_mux_net *mux_net; | ||
2607 | struct gsm_dlci *dlci; | ||
2608 | |||
2609 | mux_net = container_of(ref, struct gsm_mux_net, ref); | ||
2610 | dlci = mux_net->dlci; | ||
2611 | |||
2612 | if (dlci->net) { | ||
2613 | unregister_netdev(dlci->net); | ||
2614 | dlci_net_free(dlci); | ||
2615 | } | ||
2616 | } | ||
2617 | |||
2618 | static inline void muxnet_get(struct gsm_mux_net *mux_net) | ||
2619 | { | ||
2620 | kref_get(&mux_net->ref); | ||
2621 | } | ||
2622 | |||
2623 | static inline void muxnet_put(struct gsm_mux_net *mux_net) | ||
2624 | { | ||
2625 | kref_put(&mux_net->ref, net_free); | ||
2626 | } | ||
2627 | |||
2628 | static int gsm_mux_net_start_xmit(struct sk_buff *skb, | ||
2629 | struct net_device *net) | ||
2630 | { | ||
2631 | struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net); | ||
2632 | struct gsm_dlci *dlci = mux_net->dlci; | ||
2633 | muxnet_get(mux_net); | ||
2634 | |||
2635 | skb_queue_head(&dlci->skb_list, skb); | ||
2636 | STATS(net).tx_packets++; | ||
2637 | STATS(net).tx_bytes += skb->len; | ||
2638 | gsm_dlci_data_kick(dlci); | ||
2639 | /* And tell the kernel when the last transmit started. */ | ||
2640 | net->trans_start = jiffies; | ||
2641 | muxnet_put(mux_net); | ||
2642 | return NETDEV_TX_OK; | ||
2643 | } | ||
2644 | |||
2645 | /* called when a packet did not ack after watchdogtimeout */ | ||
2646 | static void gsm_mux_net_tx_timeout(struct net_device *net) | ||
2647 | { | ||
2648 | /* Tell syslog we are hosed. */ | ||
2649 | dev_dbg(&net->dev, "Tx timed out.\n"); | ||
2650 | |||
2651 | /* Update statistics */ | ||
2652 | STATS(net).tx_errors++; | ||
2653 | } | ||
2654 | |||
2655 | static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, | ||
2656 | unsigned char *in_buf, int size) | ||
2657 | { | ||
2658 | struct net_device *net = dlci->net; | ||
2659 | struct sk_buff *skb; | ||
2660 | struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net); | ||
2661 | muxnet_get(mux_net); | ||
2662 | |||
2663 | /* Allocate an sk_buff */ | ||
2664 | skb = dev_alloc_skb(size + NET_IP_ALIGN); | ||
2665 | if (!skb) { | ||
2666 | /* We got no receive buffer. */ | ||
2667 | STATS(net).rx_dropped++; | ||
2668 | muxnet_put(mux_net); | ||
2669 | return; | ||
2670 | } | ||
2671 | skb_reserve(skb, NET_IP_ALIGN); | ||
2672 | memcpy(skb_put(skb, size), in_buf, size); | ||
2673 | |||
2674 | skb->dev = net; | ||
2675 | skb->protocol = __constant_htons(ETH_P_IP); | ||
2676 | |||
2677 | /* Ship it off to the kernel */ | ||
2678 | netif_rx(skb); | ||
2679 | |||
2680 | /* update out statistics */ | ||
2681 | STATS(net).rx_packets++; | ||
2682 | STATS(net).rx_bytes += size; | ||
2683 | muxnet_put(mux_net); | ||
2684 | return; | ||
2685 | } | ||
2686 | |||
2687 | int gsm_change_mtu(struct net_device *net, int new_mtu) | ||
2688 | { | ||
2689 | struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net); | ||
2690 | if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu)) | ||
2691 | return -EINVAL; | ||
2692 | net->mtu = new_mtu; | ||
2693 | return 0; | ||
2694 | } | ||
2695 | |||
2696 | static void gsm_mux_net_init(struct net_device *net) | ||
2697 | { | ||
2698 | static const struct net_device_ops gsm_netdev_ops = { | ||
2699 | .ndo_open = gsm_mux_net_open, | ||
2700 | .ndo_stop = gsm_mux_net_close, | ||
2701 | .ndo_start_xmit = gsm_mux_net_start_xmit, | ||
2702 | .ndo_tx_timeout = gsm_mux_net_tx_timeout, | ||
2703 | .ndo_get_stats = gsm_mux_net_get_stats, | ||
2704 | .ndo_change_mtu = gsm_change_mtu, | ||
2705 | }; | ||
2706 | |||
2707 | net->netdev_ops = &gsm_netdev_ops; | ||
2708 | |||
2709 | /* fill in the other fields */ | ||
2710 | net->watchdog_timeo = GSM_NET_TX_TIMEOUT; | ||
2711 | net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; | ||
2712 | net->type = ARPHRD_NONE; | ||
2713 | net->tx_queue_len = 10; | ||
2714 | } | ||
2715 | |||
2716 | |||
2717 | /* caller holds the dlci mutex */ | ||
2718 | static void gsm_destroy_network(struct gsm_dlci *dlci) | ||
2719 | { | ||
2720 | struct gsm_mux_net *mux_net; | ||
2721 | |||
2722 | pr_debug("destroy network interface"); | ||
2723 | if (!dlci->net) | ||
2724 | return; | ||
2725 | mux_net = (struct gsm_mux_net *)netdev_priv(dlci->net); | ||
2726 | muxnet_put(mux_net); | ||
2727 | } | ||
2728 | |||
2729 | |||
2730 | /* caller holds the dlci mutex */ | ||
2731 | static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc) | ||
2732 | { | ||
2733 | char *netname; | ||
2734 | int retval = 0; | ||
2735 | struct net_device *net; | ||
2736 | struct gsm_mux_net *mux_net; | ||
2737 | |||
2738 | if (!capable(CAP_NET_ADMIN)) | ||
2739 | return -EPERM; | ||
2740 | |||
2741 | /* Already in a non tty mode */ | ||
2742 | if (dlci->adaption > 2) | ||
2743 | return -EBUSY; | ||
2744 | |||
2745 | if (nc->protocol != htons(ETH_P_IP)) | ||
2746 | return -EPROTONOSUPPORT; | ||
2747 | |||
2748 | if (nc->adaption != 3 && nc->adaption != 4) | ||
2749 | return -EPROTONOSUPPORT; | ||
2750 | |||
2751 | pr_debug("create network interface"); | ||
2752 | |||
2753 | netname = "gsm%d"; | ||
2754 | if (nc->if_name[0] != '\0') | ||
2755 | netname = nc->if_name; | ||
2756 | net = alloc_netdev(sizeof(struct gsm_mux_net), | ||
2757 | netname, | ||
2758 | gsm_mux_net_init); | ||
2759 | if (!net) { | ||
2760 | pr_err("alloc_netdev failed"); | ||
2761 | return -ENOMEM; | ||
2762 | } | ||
2763 | net->mtu = dlci->gsm->mtu; | ||
2764 | mux_net = (struct gsm_mux_net *)netdev_priv(net); | ||
2765 | mux_net->dlci = dlci; | ||
2766 | kref_init(&mux_net->ref); | ||
2767 | strncpy(nc->if_name, net->name, IFNAMSIZ); /* return net name */ | ||
2768 | |||
2769 | /* reconfigure dlci for network */ | ||
2770 | dlci->prev_adaption = dlci->adaption; | ||
2771 | dlci->prev_data = dlci->data; | ||
2772 | dlci->adaption = nc->adaption; | ||
2773 | dlci->data = gsm_mux_rx_netchar; | ||
2774 | dlci->net = net; | ||
2775 | |||
2776 | pr_debug("register netdev"); | ||
2777 | retval = register_netdev(net); | ||
2778 | if (retval) { | ||
2779 | pr_err("network register fail %d\n", retval); | ||
2780 | dlci_net_free(dlci); | ||
2781 | return retval; | ||
2782 | } | ||
2783 | return net->ifindex; /* return network index */ | ||
2784 | } | ||
2479 | 2785 | ||
2480 | /* Line discipline for real tty */ | 2786 | /* Line discipline for real tty */ |
2481 | struct tty_ldisc_ops tty_ldisc_packet = { | 2787 | struct tty_ldisc_ops tty_ldisc_packet = { |
@@ -2579,6 +2885,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) | |||
2579 | port = &dlci->port; | 2885 | port = &dlci->port; |
2580 | port->count++; | 2886 | port->count++; |
2581 | tty->driver_data = dlci; | 2887 | tty->driver_data = dlci; |
2888 | dlci_get(dlci); | ||
2889 | dlci_get(dlci->gsm->dlci[0]); | ||
2890 | mux_get(dlci->gsm); | ||
2582 | tty_port_tty_set(port, tty); | 2891 | tty_port_tty_set(port, tty); |
2583 | 2892 | ||
2584 | dlci->modem_rx = 0; | 2893 | dlci->modem_rx = 0; |
@@ -2594,13 +2903,23 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) | |||
2594 | static void gsmtty_close(struct tty_struct *tty, struct file *filp) | 2903 | static void gsmtty_close(struct tty_struct *tty, struct file *filp) |
2595 | { | 2904 | { |
2596 | struct gsm_dlci *dlci = tty->driver_data; | 2905 | struct gsm_dlci *dlci = tty->driver_data; |
2906 | struct gsm_mux *gsm; | ||
2907 | |||
2597 | if (dlci == NULL) | 2908 | if (dlci == NULL) |
2598 | return; | 2909 | return; |
2910 | mutex_lock(&dlci->mutex); | ||
2911 | gsm_destroy_network(dlci); | ||
2912 | mutex_unlock(&dlci->mutex); | ||
2913 | gsm = dlci->gsm; | ||
2599 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) | 2914 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) |
2600 | return; | 2915 | goto out; |
2601 | gsm_dlci_begin_close(dlci); | 2916 | gsm_dlci_begin_close(dlci); |
2602 | tty_port_close_end(&dlci->port, tty); | 2917 | tty_port_close_end(&dlci->port, tty); |
2603 | tty_port_tty_set(&dlci->port, NULL); | 2918 | tty_port_tty_set(&dlci->port, NULL); |
2919 | out: | ||
2920 | dlci_put(dlci); | ||
2921 | dlci_put(gsm->dlci[0]); | ||
2922 | mux_put(gsm); | ||
2604 | } | 2923 | } |
2605 | 2924 | ||
2606 | static void gsmtty_hangup(struct tty_struct *tty) | 2925 | static void gsmtty_hangup(struct tty_struct *tty) |
@@ -2677,7 +2996,32 @@ static int gsmtty_tiocmset(struct tty_struct *tty, | |||
2677 | static int gsmtty_ioctl(struct tty_struct *tty, | 2996 | static int gsmtty_ioctl(struct tty_struct *tty, |
2678 | unsigned int cmd, unsigned long arg) | 2997 | unsigned int cmd, unsigned long arg) |
2679 | { | 2998 | { |
2680 | return -ENOIOCTLCMD; | 2999 | struct gsm_dlci *dlci = tty->driver_data; |
3000 | struct gsm_netconfig nc; | ||
3001 | int index; | ||
3002 | |||
3003 | switch (cmd) { | ||
3004 | case GSMIOC_ENABLE_NET: | ||
3005 | if (copy_from_user(&nc, (void __user *)arg, sizeof(nc))) | ||
3006 | return -EFAULT; | ||
3007 | nc.if_name[IFNAMSIZ-1] = '\0'; | ||
3008 | /* return net interface index or error code */ | ||
3009 | mutex_lock(&dlci->mutex); | ||
3010 | index = gsm_create_network(dlci, &nc); | ||
3011 | mutex_unlock(&dlci->mutex); | ||
3012 | if (copy_to_user((void __user *)arg, &nc, sizeof(nc))) | ||
3013 | return -EFAULT; | ||
3014 | return index; | ||
3015 | case GSMIOC_DISABLE_NET: | ||
3016 | if (!capable(CAP_NET_ADMIN)) | ||
3017 | return -EPERM; | ||
3018 | mutex_lock(&dlci->mutex); | ||
3019 | gsm_destroy_network(dlci); | ||
3020 | mutex_unlock(&dlci->mutex); | ||
3021 | return 0; | ||
3022 | default: | ||
3023 | return -ENOIOCTLCMD; | ||
3024 | } | ||
2681 | } | 3025 | } |
2682 | 3026 | ||
2683 | static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) | 3027 | static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) |
@@ -2726,7 +3070,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) | |||
2726 | return gsmtty_modem_update(dlci, encode); | 3070 | return gsmtty_modem_update(dlci, encode); |
2727 | } | 3071 | } |
2728 | 3072 | ||
2729 | static struct tty_driver *gsm_tty_driver; | ||
2730 | 3073 | ||
2731 | /* Virtual ttys for the demux */ | 3074 | /* Virtual ttys for the demux */ |
2732 | static const struct tty_operations gsmtty_ops = { | 3075 | static const struct tty_operations gsmtty_ops = { |