diff options
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r-- | drivers/tty/n_gsm.c | 77 |
1 files changed, 42 insertions, 35 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 55577cf9b6a4..2afe5fce68e3 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -89,18 +89,14 @@ module_param(debug, int, 0600); /** * struct gsm_mux_net - network interface * @struct gsm_dlci* dlci - * @struct net_device_stats stats; * * Created when net interface is initialized. **/ struct gsm_mux_net { struct kref ref; struct gsm_dlci *dlci; - struct net_device_stats stats; }; -#define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats) - /* * Each block of data we have queued to go out is in the form of * a gsm_msg which holds everything we need in a link layer independent @@ -2019,6 +2015,33 @@ static void gsm_error(struct gsm_mux *gsm, gsm->io_error++; } +static int gsm_disconnect(struct gsm_mux *gsm) +{ + struct gsm_dlci *dlci = gsm->dlci[0]; + struct gsm_control *gc; + + if (!dlci) + return 0; + + /* In theory disconnecting DLCI 0 is sufficient but for some + modems this is apparently not the case. */ + gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); + if (gc) + gsm_control_wait(gsm, gc); + + del_timer_sync(&gsm->t2_timer); + /* Now we are sure T2 has stopped */ + + gsm_dlci_begin_close(dlci); + wait_event_interruptible(gsm->event, + dlci->state == DLCI_CLOSED); + + if (signal_pending(current)) + return -EINTR; + + return 0; +} + /** * gsm_cleanup_mux - generic GSM protocol cleanup * @gsm: our mux @@ -2033,7 +2056,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) int i; struct gsm_dlci *dlci = gsm->dlci[0]; struct gsm_msg *txq, *ntxq; - struct gsm_control *gc; gsm->dead = 1; @@ -2049,21 +2071,11 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) if (i == MAX_MUX) return; - /* In theory disconnecting DLCI 0 is sufficient but for some - modems this is apparently not the case. */ - if (dlci) { - gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); - if (gc) - gsm_control_wait(gsm, gc); - } del_timer_sync(&gsm->t2_timer); /* Now we are sure T2 has stopped */ - if (dlci) { + if (dlci) dlci->dead = 1; - gsm_dlci_begin_close(dlci); - wait_event_interruptible(gsm->event, - dlci->state == DLCI_CLOSED); - } + /* Free up any link layer users */ mutex_lock(&gsm->mutex); for (i = 0; i < NUM_DLCI; i++) @@ -2523,12 +2535,12 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, */ if (need_close || need_restart) { - gsm_dlci_begin_close(gsm->dlci[0]); - /* This will timeout if the link is down due to N2 expiring */ - wait_event_interruptible(gsm->event, - gsm->dlci[0]->state == DLCI_CLOSED); - if (signal_pending(current)) - return -EINTR; + int ret; + + ret = gsm_disconnect(gsm); + + if (ret) + return ret; } if (need_restart) gsm_cleanup_mux(gsm); @@ -2613,10 +2625,6 @@ static int gsm_mux_net_close(struct net_device *net) return 0; } -static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net) -{ - return &((struct gsm_mux_net *)netdev_priv(net))->stats; -} static void dlci_net_free(struct gsm_dlci *dlci) { if (!dlci->net) { @@ -2660,8 +2668,8 @@ static int gsm_mux_net_start_xmit(struct sk_buff *skb, muxnet_get(mux_net); skb_queue_head(&dlci->skb_list, skb); - STATS(net).tx_packets++; - STATS(net).tx_bytes += skb->len; + net->stats.tx_packets++; + net->stats.tx_bytes += skb->len; gsm_dlci_data_kick(dlci); /* And tell the kernel when the last transmit started. */ netif_trans_update(net); @@ -2676,7 +2684,7 @@ static void gsm_mux_net_tx_timeout(struct net_device *net) dev_dbg(&net->dev, "Tx timed out.\n"); /* Update statistics */ - STATS(net).tx_errors++; + net->stats.tx_errors++; } static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, @@ -2691,12 +2699,12 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, skb = dev_alloc_skb(size + NET_IP_ALIGN); if (!skb) { /* We got no receive buffer. */ - STATS(net).rx_dropped++; + net->stats.rx_dropped++; muxnet_put(mux_net); return; } skb_reserve(skb, NET_IP_ALIGN); - memcpy(skb_put(skb, size), in_buf, size); + skb_put_data(skb, in_buf, size); skb->dev = net; skb->protocol = htons(ETH_P_IP); @@ -2705,8 +2713,8 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, netif_rx(skb); /* update out statistics */ - STATS(net).rx_packets++; - STATS(net).rx_bytes += size; + net->stats.rx_packets++; + net->stats.rx_bytes += size; muxnet_put(mux_net); return; } @@ -2718,7 +2726,6 @@ static void gsm_mux_net_init(struct net_device *net) .ndo_stop = gsm_mux_net_close, .ndo_start_xmit = gsm_mux_net_start_xmit, .ndo_tx_timeout = gsm_mux_net_tx_timeout, - .ndo_get_stats = gsm_mux_net_get_stats, }; net->netdev_ops = &gsm_netdev_ops; |