diff options
181 files changed, 1113 insertions, 678 deletions
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 2047275..bed0ba6 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -42,6 +42,8 @@ struct btmrvl_device { void *card; struct hci_dev *hcidev; + u8 dev_type; + u8 tx_dnld_rdy; u8 psmode; @@ -88,8 +90,11 @@ struct btmrvl_private { #define BT_CMD_HOST_SLEEP_ENABLE 0x5A #define BT_CMD_MODULE_CFG_REQ 0x5B -/* Sub-commands: Module Bringup/Shutdown Request */ +/* Sub-commands: Module Bringup/Shutdown Request/Response */ #define MODULE_BRINGUP_REQ 0xF1 +#define MODULE_BROUGHT_UP 0x00 +#define MODULE_ALREADY_UP 0x0C + #define MODULE_SHUTDOWN_REQ 0xF2 #define BT_EVENT_POWER_STATE 0x20 @@ -123,6 +128,7 @@ struct btmrvl_event { /* Prototype of global function */ +int btmrvl_register_hdev(struct btmrvl_private *priv); struct btmrvl_private *btmrvl_add_card(void *card); int btmrvl_remove_card(struct btmrvl_private *priv); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 53a43ad..ee37ef0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -66,7 +66,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) { struct btmrvl_adapter *adapter = priv->adapter; struct btmrvl_event *event; - u8 ret = 0; + int ret = 0; event = (struct btmrvl_event *) skb->data; if (event->ec != 0xff) { @@ -112,8 +112,17 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) case BT_CMD_MODULE_CFG_REQ: if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_BRINGUP_REQ) { - BT_DBG("EVENT:%s", (event->data[2]) ? - "Bring-up failed" : "Bring-up succeed"); + BT_DBG("EVENT:%s", + ((event->data[2] == MODULE_BROUGHT_UP) || + (event->data[2] == MODULE_ALREADY_UP)) ? + "Bring-up succeed" : "Bring-up failed"); + + if (event->length > 3) + priv->btmrvl_dev.dev_type = event->data[3]; + else + priv->btmrvl_dev.dev_type = HCI_BREDR; + + BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type); } else if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_SHUTDOWN_REQ) { BT_DBG("EVENT:%s", (event->data[2]) ? @@ -522,47 +531,20 @@ static int btmrvl_service_main_thread(void *data) return 0; } -struct btmrvl_private *btmrvl_add_card(void *card) +int btmrvl_register_hdev(struct btmrvl_private *priv) { struct hci_dev *hdev = NULL; - struct btmrvl_private *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - BT_ERR("Can not allocate priv"); - goto err_priv; - } - - priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL); - if (!priv->adapter) { - BT_ERR("Allocate buffer for btmrvl_adapter failed!"); - goto err_adapter; - } - - btmrvl_init_adapter(priv); - hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can not allocate HCI device"); goto err_hdev; } - BT_DBG("Starting kthread..."); - priv->main_thread.priv = priv; - spin_lock_init(&priv->driver_lock); - - init_waitqueue_head(&priv->main_thread.wait_q); - priv->main_thread.task = kthread_run(btmrvl_service_main_thread, - &priv->main_thread, "btmrvl_main_service"); - priv->btmrvl_dev.hcidev = hdev; - priv->btmrvl_dev.card = card; - hdev->driver_data = priv; - priv->btmrvl_dev.tx_dnld_rdy = true; - hdev->bus = HCI_SDIO; hdev->open = btmrvl_open; hdev->close = btmrvl_close; @@ -572,6 +554,10 @@ struct btmrvl_private *btmrvl_add_card(void *card) hdev->ioctl = btmrvl_ioctl; hdev->owner = THIS_MODULE; + btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + + hdev->dev_type = priv->btmrvl_dev.dev_type; + ret = hci_register_dev(hdev); if (ret < 0) { BT_ERR("Can not register HCI device"); @@ -582,16 +568,52 @@ struct btmrvl_private *btmrvl_add_card(void *card) btmrvl_debugfs_init(hdev); #endif - return priv; + return 0; err_hci_register_dev: - /* Stop the thread servicing the interrupts */ - kthread_stop(priv->main_thread.task); - hci_free_dev(hdev); err_hdev: + /* Stop the thread servicing the interrupts */ + kthread_stop(priv->main_thread.task); + btmrvl_free_adapter(priv); + kfree(priv); + + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(btmrvl_register_hdev); + +struct btmrvl_private *btmrvl_add_card(void *card) +{ + struct btmrvl_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + BT_ERR("Can not allocate priv"); + goto err_priv; + } + + priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL); + if (!priv->adapter) { + BT_ERR("Allocate buffer for btmrvl_adapter failed!"); + goto err_adapter; + } + + btmrvl_init_adapter(priv); + + BT_DBG("Starting kthread..."); + priv->main_thread.priv = priv; + spin_lock_init(&priv->driver_lock); + + init_waitqueue_head(&priv->main_thread.wait_q); + priv->main_thread.task = kthread_run(btmrvl_service_main_thread, + &priv->main_thread, "btmrvl_main_service"); + + priv->btmrvl_dev.card = card; + priv->btmrvl_dev.tx_dnld_rdy = true; + + return priv; err_adapter: kfree(priv); diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 0dba76a..df0773e 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -931,7 +931,12 @@ static int btmrvl_sdio_probe(struct sdio_func *func, priv->hw_host_to_card = btmrvl_sdio_host_to_card; priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; - btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + if (btmrvl_register_hdev(priv)) { + BT_ERR("Register hdev failed!"); + ret = -ENODEV; + goto disable_host_int; + } + priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index c0ce813..3f038f5 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -246,7 +246,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) BT_ERR("Can't allocate mem for new packet"); h4->rx_state = H4_W4_PACKET_TYPE; h4->rx_count = 0; - return 0; + return -ENOMEM; } h4->rx_skb->dev = (void *) hu->hdev; diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 5c65014..fb8445c 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -402,7 +402,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_EVENT_HDR: - eh = (struct hci_event_hdr *) ll->rx_skb->data; + eh = hci_event_hdr(ll->rx_skb); BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); @@ -410,7 +410,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_ACL_HDR: - ah = (struct hci_acl_hdr *) ll->rx_skb->data; + ah = hci_acl_hdr(ll->rx_skb); dlen = __le16_to_cpu(ah->dlen); BT_DBG("ACL header: dlen %d", dlen); @@ -419,7 +419,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) continue; case HCILL_W4_SCO_HDR: - sh = (struct hci_sco_hdr *) ll->rx_skb->data; + sh = hci_sco_hdr(ll->rx_skb); BT_DBG("SCO header: dlen %d", sh->dlen); @@ -491,7 +491,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) BT_ERR("Can't allocate mem for new packet"); ll->rx_state = HCILL_W4_PACKET_TYPE; ll->rx_count = 0; - return 0; + return -ENOMEM; } ll->rx_skb->dev = (void *) hu->hdev; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index bb0aefd..3aa7b2a 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -157,7 +157,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, break; case HCI_SCODATA_PKT: - data->hdev->stat.cmd_tx++; + data->hdev->stat.sco_tx++; break; }; diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 3ea42ff1..4fed2a8 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -480,7 +480,6 @@ static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev) /* fire ... Trigger xmit. */ outb(AX_XMIT, AX_CMD); lp->loading = 0; - dev->trans_start = jiffies; if (el_debug > 2) pr_debug(" queued xmit.\n"); dev_kfree_skb(skb); diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 8d584f5..88d766e 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1055,7 +1055,7 @@ static void elp_timeout(struct net_device *dev) (stat & ACRF) ? "interrupt" : "command"); if (elp_debug >= 1) pr_debug("%s: status %#02x\n", dev->name, stat); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_dropped++; netif_wake_queue(dev); } @@ -1093,11 +1093,6 @@ static netdev_tx_t elp_start_xmit(struct sk_buff *skb, struct net_device *dev) if (elp_debug >= 3) pr_debug("%s: packet of length %d sent\n", dev->name, (int) skb->len); - /* - * start the transmit timeout - */ - dev->trans_start = jiffies; - prime_rx(dev); spin_unlock_irqrestore(&adapter->lock, flags); netif_start_queue(dev); diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 9e95afa..c4e272f 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -504,7 +504,7 @@ static void el16_tx_timeout (struct net_device *dev) outb (0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ lp->last_restart = dev->stats.tx_packets; } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } @@ -528,7 +528,6 @@ static netdev_tx_t el16_send_packet (struct sk_buff *skb, hardware_send_packet (dev, buf, skb->len, length - skb->len); - dev->trans_start = jiffies; /* Enable the 82586 interrupt input. */ outb (0x84, ioaddr + MISC_CTRL); diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index ab9bb3c..54deaa9 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -807,7 +807,7 @@ el3_tx_timeout (struct net_device *dev) dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS), inw(ioaddr + TX_FREE)); dev->stats.tx_errors++; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* Issue TX_RESET and TX_START commands. */ outw(TxReset, ioaddr + EL3_CMD); outw(TxEnable, ioaddr + EL3_CMD); @@ -868,7 +868,6 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev) /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev->trans_start = jiffies; if (inw(ioaddr + TX_FREE) > 1536) netif_start_queue(dev); else diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 2e17837..569e269 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -992,7 +992,7 @@ static void corkscrew_timeout(struct net_device *dev) if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; outw(TxEnable, ioaddr + EL3_CMD); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; dev->stats.tx_dropped++; netif_wake_queue(dev); @@ -1055,7 +1055,6 @@ static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb, prev_entry->status &= ~0x80000000; netif_wake_queue(dev); } - dev->trans_start = jiffies; return NETDEV_TX_OK; } /* Put out the doubleword header... */ @@ -1091,7 +1090,6 @@ static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb, outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD); #endif /* bus master */ - dev->trans_start = jiffies; /* Clear the Tx status stack. */ { diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 55d219e..a7b0e5e 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -1152,7 +1152,6 @@ static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev) p->scb->cmd = CUC_START; p->xmit_cmds[0]->cmd_status = 0; elmc_attn586(); - dev->trans_start = jiffies; if (!i) { dev_kfree_skb(skb); } @@ -1176,7 +1175,6 @@ static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev) p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - dev->trans_start = jiffies; p->nop_point = next_nop; dev_kfree_skb(skb); #endif @@ -1190,7 +1188,6 @@ static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev) = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; p->xmit_count = next_nop; if (p->xmit_count != p->xmit_last) netif_wake_queue(dev); diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 9752530..dab2afa 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1917,7 +1917,7 @@ static void vortex_tx_timeout(struct net_device *dev) /* Issue Tx Enable */ iowrite16(TxEnable, ioaddr + EL3_CMD); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* Switch to register set 7 for normal use. */ EL3WINDOW(7); @@ -2063,7 +2063,6 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) } } - dev->trans_start = jiffies; /* Clear the Tx status stack. */ { @@ -2174,7 +2173,6 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) } iowrite16(DownUnstall, ioaddr + EL3_CMD); spin_unlock_irqrestore(&vp->lock, flags); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/7990.c b/drivers/net/7990.c index f09e594..561d3d5 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -262,7 +262,7 @@ static int lance_reset (struct net_device *dev) load_csrs (lp); lance_init_ring (dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ status = init_restart_lance (lp); #ifdef DEBUG_DRIVER printk ("Lance restart=%d\n", status); @@ -526,7 +526,7 @@ void lance_tx_timeout(struct net_device *dev) { printk("lance_tx_timeout\n"); lance_reset(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } EXPORT_SYMBOL_GPL(lance_tx_timeout); @@ -574,7 +574,6 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) outs++; /* Kick the lance: transmit now */ WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD); - dev->trans_start = jiffies; dev_kfree_skb (skb); spin_lock_irqsave (&lp->devlock, flags); diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 4e8d11c..cd63b97 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -882,7 +882,6 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, spin_unlock_irqrestore(&cp->lock, intr_flags); cpw8(TxPoll, NormalTxPoll); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index d0cb372..4ba7293 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -1716,8 +1716,6 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - dev->trans_start = jiffies; - tp->cur_tx++; if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 97c5fc0..dd8dc15 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1050,7 +1050,7 @@ static void i596_tx_timeout (struct net_device *dev) lp->last_restart = dev->stats.tx_packets; } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } @@ -1060,7 +1060,6 @@ static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev) struct tx_cmd *tx_cmd; struct i596_tbd *tbd; short length = skb->len; - dev->trans_start = jiffies; DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n", dev->name, skb->len, skb->data)); diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ce0a0b8..ecaa28c 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -525,7 +525,7 @@ static inline int lance_reset (struct net_device *dev) load_csrs (lp); lance_init_ring (dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_start_queue(dev); status = init_restart_lance (lp); @@ -588,7 +588,6 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb, /* Kick the lance: transmit now */ ll->rdp = LE_C0_INEA | LE_C0_TDMD; - dev->trans_start = jiffies; dev_kfree_skb (skb); local_irq_restore(flags); diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 97d71a9..585c25f 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1339,8 +1339,6 @@ static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb, writel( VAL1 | TDMD0, lp->mmio + CMD0); writel( VAL2 | RDMD0,lp->mmio + CMD0); - dev->trans_start = jiffies; - if(amd8111e_tx_queue_avail(lp) < 0){ netif_stop_queue(dev); } diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 6f8d620..14e1d95 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -866,7 +866,7 @@ static void cops_timeout(struct net_device *dev) } printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); cops_jumpstart(dev); /* Restart the card. */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -919,9 +919,8 @@ static netdev_tx_t cops_send_packet(struct sk_buff *skb, /* Done sending packet, update counters and cleanup. */ dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; dev_kfree_skb (skb); - return NETDEV_TX_OK; + return NETDEV_TX_OK; } /* diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index d8f0293..a746ba2 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -654,7 +654,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, } } retval = NETDEV_TX_OK; - dev->trans_start = jiffies; lp->next_tx = txbuf; } else { retval = NETDEV_TX_BUSY; diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a235..705373a 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -676,8 +676,6 @@ static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb, lance->RAP = CSR0; /* PCnet-ISA Controller Status */ lance->RDP = INEA|TDMD; - dev->trans_start = jiffies; - if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) { netif_stop_queue(dev); priv->tx_full = 1; diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index a4b5b08..8c496fb 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -469,7 +469,6 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->chip_lock, flags); write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA); - dev->trans_start = jiffies; spin_unlock_irqrestore(&priv->chip_lock, flags); /* diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 0adab30..e07b314 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -824,7 +824,6 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Set length of the packet in the Transmit Control register */ at91_emac_write(AT91_EMAC_TCR, skb->len); - dev->trans_start = jiffies; } else { printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n"); return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 6995169..c5f6736 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -374,8 +374,6 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) skb->len, DMA_TO_DEVICE); dev_kfree_skb(skb); - dev->trans_start = jiffies; - spin_lock_irq(&ep->tx_pending_lock); ep->tx_pending++; if (ep->tx_pending == TX_QUEUE_ENTRIES) diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index e47c0d9..b17ab51 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -736,7 +736,6 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) local_irq_restore(flags); /* handle transmit */ - dev->trans_start = jiffies; /* check to see if we have room for a full sized ether frame */ tmp = priv(dev)->tx_head; diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index d9de9bc..1361b73 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -529,7 +529,6 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; /* unable to queue */ } - dev->trans_start = jiffies; ptr = 0x600 * priv(dev)->tx_head; priv(dev)->tx_head = next_ptr; next_ptr *= 0x600; diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 7800d7d..24df032 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -708,7 +708,6 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) /* NPE firmware pads short frames with zeros internally */ wmb(); queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); - dev->trans_start = jiffies; if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ #if DEBUG_TX diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 6404704..54c6d84 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1302,8 +1302,6 @@ ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (++ksp->tx_ring_used == MAX_TX_DESC) netif_stop_queue(ndev); - ndev->trans_start = jiffies; - /* Kick the TX DMA in case it decided to go IDLE */ ks8695_writereg(ksp, KS8695_DTSC, 0); diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c index 2491934..2e85246 100644 --- a/drivers/net/arm/w90p910_ether.c +++ b/drivers/net/arm/w90p910_ether.c @@ -483,7 +483,7 @@ static void w90p910_reset_mac(struct net_device *dev) w90p910_init_desc(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ ether->cur_tx = 0x0; ether->finish_tx = 0x0; ether->cur_rx = 0x0; @@ -497,7 +497,7 @@ static void w90p910_reset_mac(struct net_device *dev) w90p910_trigger_tx(dev); w90p910_trigger_rx(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ if (netif_queue_stopped(dev)) netif_wake_queue(dev); @@ -634,8 +634,6 @@ static int w90p910_send_frame(struct net_device *dev, txbd = ðer->tdesc->desclist[ether->cur_tx]; - dev->trans_start = jiffies; - if (txbd->mode & TX_OWEN_DMA) netif_stop_queue(dev); diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index 332f980..861f07a 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -583,7 +583,7 @@ static void net_tx_timeout (struct net_device *dev) outb (0x00, ioaddr + TX_START); outb (0x03, ioaddr + COL16CNTL); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ lp->tx_started = 0; lp->tx_queue_ready = 1; @@ -636,7 +636,6 @@ static netdev_tx_t net_send_packet (struct sk_buff *skb, outb (0x80 | lp->tx_queue, ioaddr + TX_START); lp->tx_queue = 0; lp->tx_queue_len = 0; - dev->trans_start = jiffies; lp->tx_started = 1; netif_start_queue (dev); } else if (lp->tx_queue_len < 4096 - 1502) diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index a8686bf..b57d7de 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -767,8 +767,8 @@ static void lance_tx_timeout (struct net_device *dev) /* lance_restart, essentially */ lance_init_ring(dev); REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; - dev->trans_start = jiffies; - netif_wake_queue (dev); + dev->trans_start = jiffies; /* prevent tx timeout */ + netif_wake_queue(dev); } /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ @@ -836,7 +836,6 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) /* Trigger an immediate send poll. */ DREG = CSR0_INEA | CSR0_TDMD; - dev->trans_start = jiffies; if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == TMD1_OWN_HOST) diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index fee9cf6..8da8738 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -892,7 +892,6 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb, (adapter->txd_write_ptr >> 2)); mmiowb(); - netdev->trans_start = jiffies; dev_kfree_skb_any(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/atp.c b/drivers/net/atp.c index 2bd1a5c..75ff0c5 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -547,7 +547,7 @@ static void tx_timeout(struct net_device *dev) dev->stats.tx_errors++; /* Try to restart the adapter. */ hardware_init(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); dev->stats.tx_errors++; } @@ -586,7 +586,6 @@ static netdev_tx_t atp_send_packet(struct sk_buff *skb, write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); write_reg_high(ioaddr, IMR, ISRh_RxErr); - dev->trans_start = jiffies; dev_kfree_skb (skb); return NETDEV_TX_OK; } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 7abb2c8..ece6128 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -924,7 +924,6 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev) au_sync(); dev_kfree_skb(skb); aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1); - dev->trans_start = jiffies; return NETDEV_TX_OK; } @@ -937,7 +936,7 @@ static void au1000_tx_timeout(struct net_device *dev) netdev_err(dev, "au1000_tx_timeout: dev=%p\n", dev); au1000_reset_mac(dev); au1000_init(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 4582721..293f9c1 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1014,8 +1014,6 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); - dev->trans_start = jiffies; - out_unlock: spin_unlock_irqrestore(&bp->lock, flags); diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index f48ba80..faf5add 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -565,7 +565,6 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_bytes += skb->len; priv->stats.tx_packets++; - dev->trans_start = jiffies; ret = NETDEV_TX_OK; out_unlock: diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index c488cea..b0207f0 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -654,7 +654,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, out: adjust_tx_list(); current_tx_ptr = current_tx_ptr->next; - dev->trans_start = jiffies; dev->stats.tx_packets++; dev->stats.tx_bytes += (skb->len); return NETDEV_TX_OK; @@ -805,7 +804,7 @@ static void bfin_mac_timeout(struct net_device *dev) bfin_mac_enable(); /* We can accept TX packets again */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 5f98348..2d8bd86 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -375,7 +375,6 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) at91_write(priv, AT91_MCR(mb), reg_mcr); stats->tx_bytes += cf->can_dlc; - dev->trans_start = jiffies; /* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */ can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST); diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index d77264a..b6e890d 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -269,8 +269,6 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) /* fill data length code */ bfin_write16(®->chl[TRANSMIT_CHL].dlc, dlc); - dev->trans_start = jiffies; - can_put_echo_skb(skb, dev, 0); /* set transmit request */ diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 8431eb0..b11a0cb 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -475,7 +475,6 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, netif_stop_queue(net); priv->tx_skb = skb; - net->trans_start = jiffies; queue_work(priv->wq, &priv->tx_work); return NETDEV_TX_OK; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 618c112..24b5861 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -292,8 +292,6 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, for (i = 0; i < dlc; i++) priv->write_reg(priv, dreg++, cf->data[i]); - dev->trans_start = jiffies; - can_put_echo_skb(skb, dev, 0); priv->write_reg(priv, REG_CMR, CMD_TR); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index bd857a2..6d76236 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2889,7 +2889,6 @@ static netdev_tx_t cas_start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb)) return NETDEV_TX_BUSY; - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index bdfff78..3c58db5 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -579,7 +579,6 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) } spin_lock(&priv->lock); - dev->trans_start = jiffies; spin_unlock(&priv->lock); desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN; desc->skb = skb; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index f49ad8e..7e00027 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1108,7 +1108,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev) myNextTxDesc->skb = skb; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ e100_hardware_send_packet(np, buf, skb->len); diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 4c38491..2281ebc 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1554,7 +1554,6 @@ static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev) writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); spin_unlock_irqrestore(&lp->lock, flags); lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; dev_kfree_skb (skb); /* diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 1f9df5c..08e82b1 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1468,7 +1468,6 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) tx_buf.length = skb->len; tx_buf.buf_token = (void *)skb; tx_buf.data_ptr = skb->data; - ndev->trans_start = jiffies; ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); if (unlikely(ret_code != 0)) { if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { diff --git a/drivers/net/de600.c b/drivers/net/de600.c index 6b13f4f..23a6539 100644 --- a/drivers/net/de600.c +++ b/drivers/net/de600.c @@ -166,8 +166,8 @@ static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev) int i; if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ - tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) + tickssofar = jiffies - dev_trans_start(dev); + if (tickssofar < HZ/20) return NETDEV_TX_BUSY; /* else */ printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem"); diff --git a/drivers/net/de620.c b/drivers/net/de620.c index a0a6830..f3650fd 100644 --- a/drivers/net/de620.c +++ b/drivers/net/de620.c @@ -535,7 +535,6 @@ static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev) } de620_write_block(dev, buffer, skb->len, len-skb->len); - dev->trans_start = jiffies; if(!(using_txbuf == (TXBF0 | TXBF1))) netif_wake_queue(dev); diff --git a/drivers/net/declance.c b/drivers/net/declance.c index fb3f098..74abe19 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -874,7 +874,7 @@ static inline int lance_reset(struct net_device *dev) lance_init_ring(dev); load_csrs(lp); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ status = init_restart_lance(lp); return status; } @@ -930,7 +930,6 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); - dev->trans_start = jiffies; dev_kfree_skb(skb); return NETDEV_TX_OK; diff --git a/drivers/net/depca.c b/drivers/net/depca.c index a88300a0..38d4d9e 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -921,7 +921,7 @@ static void depca_tx_timeout(struct net_device *dev) STOP_DEPCA; depca_init_ring(dev); LoadCSRs(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); InitRestartDepca(dev); } @@ -954,7 +954,6 @@ static netdev_tx_t depca_start_xmit(struct sk_buff *skb, outw(CSR0, DEPCA_ADDR); outw(INEA | TDMD, DEPCA_DATA); - dev->trans_start = jiffies; dev_kfree_skb(skb); } if (TX_BUFFS_AVAIL) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index a818ea9..254b6f7 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -769,7 +769,7 @@ dm9000_hash_table(struct net_device *dev) } /* - * Initilize dm9000 board + * Initialize dm9000 board */ static void dm9000_init_dm9000(struct net_device *dev) @@ -825,7 +825,7 @@ dm9000_init_dm9000(struct net_device *dev) /* Init Driver variable */ db->tx_pkt_cnt = 0; db->queue_pkt_len = 0; - dev->trans_start = 0; + dev->trans_start = jiffies; } /* Our watchdog timed out. Called by the networking layer */ @@ -843,7 +843,7 @@ static void dm9000_timeout(struct net_device *dev) dm9000_reset(db); dm9000_init_dm9000(dev); /* We can accept TX packets again */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); /* Restore previous register address */ diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index d51a83e..8b0f50b 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -594,8 +594,6 @@ static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index ef97bfc..b194bad 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1764,7 +1764,6 @@ static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, return NETDEV_TX_BUSY; } - netdev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index eed65d8..8d97f16 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1161,8 +1161,7 @@ static netdev_tx_t eepro_send_packet(struct sk_buff *skb, /* we won't wake queue here because we're out of space */ dev->stats.tx_dropped++; else { - dev->stats.tx_bytes+=skb->len; - dev->trans_start = jiffies; + dev->stats.tx_bytes+=skb->len; netif_wake_queue(dev); } diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index c31dd06..43c9c9c 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -543,7 +543,7 @@ static void unstick_cu(struct net_device *dev) if (lp->started) { - if (time_after(jiffies, dev->trans_start + 50)) + if (time_after(jiffies, dev_trans_start(dev) + HZ/2)) { if (lp->tx_link==lp->last_tx_restart) { @@ -1018,7 +1018,7 @@ static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, outw(lp->tx_head+0x16, ioaddr + DATAPORT); outw(0, ioaddr + DATAPORT); - outsw(ioaddr + DATAPORT, buf, (len+1)>>1); + outsw(ioaddr + DATAPORT, buf, (len+1)>>1); outw(lp->tx_tail+0xc, ioaddr + WRITE_PTR); outw(lp->tx_head, ioaddr + DATAPORT); diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3977481..33a41e2 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2241,7 +2241,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } spin_unlock_irqrestore(&pr->netif_queue, flags); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ spin_unlock(&pr->xmit_lock); return NETDEV_TX_OK; diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index ff27f728..112c5aa 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -1293,8 +1293,6 @@ static netdev_tx_t enc28j60_send_packet(struct sk_buff *skb, */ netif_stop_queue(dev); - /* save the timestamp */ - priv->netdev->trans_start = jiffies; /* Remember the skb for deferred processing */ priv->tx_skb = skb; schedule_work(&priv->tx_work); diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 8b5a203..a48da2d 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -908,7 +908,7 @@ static void epic_tx_timeout(struct net_device *dev) outl(TxQueued, dev->base_addr + COMMAND); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ ep->stats.tx_errors++; if (!ep->tx_full) netif_wake_queue(dev); @@ -1006,7 +1006,6 @@ static netdev_tx_t epic_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Trigger an immediate transmit demand. */ outl(TxQueued, dev->base_addr + COMMAND); - dev->trans_start = jiffies; if (debug > 4) printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, " "flag %2.2x Tx status %8.8x.\n", diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index d4e24f0..874973f 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -1027,7 +1027,7 @@ static void eth16i_timeout(struct net_device *dev) inw(ioaddr + TX_STATUS_REG), (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? "IRQ conflict" : "network cable problem"); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* Let's dump all registers */ if(eth16i_debug > 0) { @@ -1047,7 +1047,7 @@ static void eth16i_timeout(struct net_device *dev) } dev->stats.tx_errors++; eth16i_reset(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); netif_wake_queue(dev); } @@ -1109,7 +1109,6 @@ static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev) outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG); lp->tx_queue = 0; lp->tx_queue_len = 0; - dev->trans_start = jiffies; lp->tx_started = 1; netif_wake_queue(dev); } diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index ad1bc73..14cbde5 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -851,7 +851,6 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - dev->trans_start = jiffies; spin_unlock_irq(&priv->lock); out: dev_kfree_skb(skb); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 11ba70f..99eb56b 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -757,7 +757,7 @@ static void ewrk3_timeout(struct net_device *dev) */ ENABLE_IRQs; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } } @@ -862,7 +862,6 @@ static netdev_tx_t ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq (&lp->hw_lock); dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; dev_kfree_skb (skb); /* Check for free resources: stop Tx queue if there are none */ diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 51b738d..15f4f8d 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1233,7 +1233,7 @@ static void fealnx_tx_timeout(struct net_device *dev) spin_unlock_irqrestore(&np->lock, flags); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ np->stats.tx_errors++; netif_wake_queue(dev); /* or .._start_.. ?? */ } @@ -1374,7 +1374,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); ++np->really_tx_count; iowrite32(0, np->mem + TXPDR); - dev->trans_start = jiffies; spin_unlock_irqrestore(&np->lock, flags); return NETDEV_TX_OK; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 2b1651a..47da519 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -275,8 +275,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; - dev->trans_start = jiffies; - /* Trigger transmission start */ writel(0, fep->hwp + FEC_X_DES_ACTIVE); diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 0376c3e..221f440 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -327,7 +327,6 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) } spin_lock_irqsave(&priv->lock, flags); - dev->trans_start = jiffies; bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->tx_dmatsk); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e282d0a..268ea4d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2214,7 +2214,6 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) dprintk("\n"); } - dev->trans_start = jiffies; writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); return NETDEV_TX_OK; } @@ -2369,7 +2368,6 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, dprintk("\n"); } - dev->trans_start = jiffies; writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); return NETDEV_TX_OK; } diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 0770e2f..0fb0fef 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -674,8 +674,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->data, skb->len, DMA_TO_DEVICE)); CBDW_DATLEN(bdp, skb->len); - dev->trans_start = jiffies; - /* * If this was the last BD in the ring, start at the beginning again. */ diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 5267c27..11d8cae 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1738,7 +1738,7 @@ void gfar_start(struct net_device *dev) gfar_write(®s->imask, IMASK_DEFAULT); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } void gfar_configure_coalescing(struct gfar_private *priv, @@ -2161,8 +2161,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* reduce TxBD free count */ tx_queue->num_txbdfree -= (nr_txbds); - dev->trans_start = jiffies; - /* If the next BD still needs to be cleaned up, then the bds are full. We need to tell the kernel to stop sending us stuff. */ if (!tx_queue->num_txbdfree) { diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 0f3f6c2..68e5ac8 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1102,7 +1102,7 @@ static int hp100_open(struct net_device *dev) return -EAGAIN; } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_start_queue(dev); lp->lan_type = hp100_sense_lan(dev); @@ -1510,7 +1510,7 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb, printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name); #endif /* not waited long enough since last tx? */ - if (time_before(jiffies, dev->trans_start + HZ)) + if (time_before(jiffies, dev_trans_start(dev) + HZ)) goto drop; if (hp100_check_lan(dev)) @@ -1547,7 +1547,6 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb, } } - dev->trans_start = jiffies; goto drop; } @@ -1585,7 +1584,6 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb, /* Update statistics */ lp->stats.tx_packets++; lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; return NETDEV_TX_OK; @@ -1663,7 +1661,7 @@ static netdev_tx_t hp100_start_xmit(struct sk_buff *skb, printk("hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i); #endif /* not waited long enough since last failed tx try? */ - if (time_before(jiffies, dev->trans_start + HZ)) { + if (time_before(jiffies, dev_trans_start(dev) + HZ)) { #ifdef HP100_DEBUG printk("hp100: %s: trans_start timing problem\n", dev->name); @@ -1701,7 +1699,6 @@ static netdev_tx_t hp100_start_xmit(struct sk_buff *skb, mdelay(1); } } - dev->trans_start = jiffies; goto drop; } @@ -1745,7 +1742,6 @@ static netdev_tx_t hp100_start_xmit(struct sk_buff *skb, lp->stats.tx_packets++; lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; hp100_ints_on(); spin_unlock_irqrestore(&lp->lock, flags); diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 0d2c3ac..092fb9d 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -957,7 +957,7 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, } else { tx_packets++; tx_bytes += skb->len; - netdev->trans_start = jiffies; + netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ } if (!used_bounce) diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index f4081c0..ab9f675 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -182,7 +182,6 @@ static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - dev->trans_start = jiffies; skb_queue_tail(&dp->rq, skb); if (!dp->tasklet_pending) { dp->tasklet_pending = 1; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 091ea33..e3b5e94 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1503,7 +1503,6 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) BARRIER(); - dev->trans_start = jiffies; ip->tx_skbs[produce] = skb; /* Remember skb */ produce = (produce + 1) & 127; ip->tx_pi = produce; diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index b5cbd39..a3d696a 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -546,7 +546,6 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb(skb); aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index b7e6625..48bd5ec 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1002,8 +1002,6 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) toshoboe_checkstuck (self); - dev->trans_start = jiffies; - /* Check if we need to change the speed */ /* But not now. Wait after transmission if mtt not required */ speed=irda_get_next_speed(skb); diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 1a54f6b..c192c31 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -556,7 +556,6 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) } dev_kfree_skb(skb); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 1dcdce0..da27050 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -715,8 +715,6 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_TXE; } - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index de91cd1..1b051da 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -655,7 +655,6 @@ static netdev_tx_t sirdev_hard_xmit(struct sk_buff *skb, if (likely(actual > 0)) { dev->tx_skb = skb; - ndev->trans_start = jiffies; dev->tx_buff.data += actual; dev->tx_buff.len -= actual; } diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 6af84d8..35e4e44 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -868,7 +868,7 @@ static void smsc_ircc_timeout(struct net_device *dev) spin_lock_irqsave(&self->lock, flags); smsc_ircc_sir_start(self); smsc_ircc_change_speed(self, self->io.speed); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); spin_unlock_irqrestore(&self->lock, flags); } diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index e145052..c3d0738 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1037,7 +1037,6 @@ static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, wmb(); outw(0, iobase+VLSI_PIO_PROMPT); } - ndev->trans_start = jiffies; if (ring_put(r) == NULL) { netif_stop_queue(ndev); diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index cb0cb75..1f9c3f08 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -515,7 +515,6 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, /* Check for empty frame */ if (!skb->len) { w83977af_change_speed(self, speed); - dev->trans_start = jiffies; dev_kfree_skb(skb); return NETDEV_TX_OK; } else @@ -549,7 +548,6 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, switch_bank(iobase, SET0); outb(ICR_ETXTHI, iobase+ICR); } - dev->trans_start = jiffies; dev_kfree_skb(skb); /* Restore set register */ diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 460c37f..40f47b8 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -3184,8 +3184,6 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ixgbevf_tx_map(adapter, tx_ring, skb, tx_flags, first), skb->len, hdr_len); - netdev->trans_start = jiffies; - ixgbevf_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); return NETDEV_TX_OK; diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index d5932ca..78ddd8b 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -64,8 +64,6 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) ixp2000_reg_write(RING_TX_PENDING, TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc))); - dev->trans_start = jiffies; - local_irq_save(flags); ip->tx_queue_entries++; if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN) diff --git a/drivers/net/lance.c b/drivers/net/lance.c index 7b94476..21f8ada 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -945,7 +945,7 @@ static void lance_tx_timeout (struct net_device *dev) #endif lance_restart (dev, 0x0043, 1); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } @@ -1011,8 +1011,6 @@ static netdev_tx_t lance_start_xmit(struct sk_buff *skb, outw(0x0000, ioaddr+LANCE_ADDR); outw(0x0048, ioaddr+LANCE_DATA); - dev->trans_start = jiffies; - if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE) netif_stop_queue(dev); diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 61c38ab..de856d8 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -963,7 +963,7 @@ static void i596_tx_timeout (struct net_device *dev) lp->last_restart = dev->stats.tx_packets; } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } @@ -974,7 +974,6 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) struct tx_cmd *tx_cmd; struct i596_tbd *tbd; short length = skb->len; - dev->trans_start = jiffies; DEB(DEB_STARTTX, printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n", diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 770b606..64d51d6 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -257,7 +257,7 @@ static void __ei_tx_timeout(struct net_device *dev) { unsigned long e8390_base = dev->base_addr; struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int txsr, isr, tickssofar = jiffies - dev->trans_start; + int txsr, isr, tickssofar = jiffies - dev_trans_start(dev); unsigned long flags; dev->stats.tx_errors++; @@ -386,7 +386,6 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb, { ei_local->txing = 1; NS8390_trigger_send(dev, send_length, output_page); - dev->trans_start = jiffies; if (output_page == ei_local->tx_start_page) { ei_local->tx1 = -1; diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 78c9a2e..b59b24d 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -527,7 +527,7 @@ static void temac_device_reset(struct net_device *ndev) dev_err(&ndev->dev, "Error setting TEMAC options\n"); /* Init Driver variable */ - ndev->trans_start = 0; + ndev->trans_start = jiffies; /* prevent tx timeout */ } void temac_adjust_link(struct net_device *ndev) diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 72379c5..3df046a 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -875,8 +875,6 @@ static netdev_tx_t i596_start_xmit (struct sk_buff *skb, struct net_device *dev) length = ETH_ZLEN; } - dev->trans_start = jiffies; - tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); if (tx_cmd == NULL) { printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index c0876e9..69fa4ef6 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -408,7 +408,6 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev) skb->len+1); local_irq_restore(flags); - dev->trans_start = jiffies; dev_kfree_skb (skb); return NETDEV_TX_OK; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index cf7debc..40797fb 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -666,8 +666,6 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index a6e19fc..c685a46 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -488,7 +488,6 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb(skb); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/meth.c b/drivers/net/meth.c index 9f72cb4..16a3594 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -746,7 +746,7 @@ static void meth_tx_timeout(struct net_device *dev) /* Enable interrupt */ spin_unlock_irqrestore(&priv->meth_lock, flags); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); return; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 4ee9d04..1f724e5 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -882,7 +882,6 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) txq->tx_bytes += skb->len; txq->tx_packets++; - dev->trans_start = jiffies; entries_left = txq->tx_ring_size - txq->tx_desc_count; if (entries_left < MAX_SKB_FRAGS + 1) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 9250bf6..2a17b50 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1905,7 +1905,7 @@ static void ns_tx_timeout(struct net_device *dev) spin_unlock_irq(&np->lock); enable_irq(dev->irq); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ np->stats.tx_errors++; netif_wake_queue(dev); } @@ -2119,8 +2119,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) } spin_unlock_irqrestore(&np->lock, flags); - dev->trans_start = jiffies; - if (netif_msg_tx_queued(np)) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", dev->name, np->cur_tx, entry); diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index 6477029..2e4b421 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -126,7 +126,6 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) FIFO_PTR_FRAMENO(1) | FIFO_PTR_FRAMELEN(len)); - ndev->trans_start = jiffies; ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 3892330..f80b501 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -444,7 +444,7 @@ static void ni5010_timeout(struct net_device *dev) /* Try to restart the adaptor. */ /* FIXME: Give it a real kick here */ chipset_init(dev, 1); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -460,7 +460,6 @@ static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); hardware_send_packet(dev, (unsigned char *)skb->data, skb->len, length-skb->len); - dev->trans_start = jiffies; dev_kfree_skb (skb); return NETDEV_TX_OK; } diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index b7837eb..9bddb5f 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -1147,7 +1147,7 @@ static void ni52_timeout(struct net_device *dev) writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_scb_cmd(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ return 0; } #endif @@ -1165,7 +1165,7 @@ static void ni52_timeout(struct net_device *dev) ni52_close(dev); ni52_open(dev); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } /****************************************************** @@ -1218,7 +1218,6 @@ static netdev_tx_t ni52_send_packet(struct sk_buff *skb, writeb(CUC_START, &p->scb->cmd_cuc); } ni_attn586(); - dev->trans_start = jiffies; if (!i) dev_kfree_skb(skb); wait_for_scb_cmd(dev); @@ -1240,7 +1239,6 @@ static netdev_tx_t ni52_send_packet(struct sk_buff *skb, writew(0, &p->nop_cmds[next_nop]->cmd_status); writew(make16(p->xmit_cmds[0]), &p->nop_cmds[p->nop_point]->cmd_link); - dev->trans_start = jiffies; p->nop_point = next_nop; dev_kfree_skb(skb); # endif @@ -1256,7 +1254,6 @@ static netdev_tx_t ni52_send_packet(struct sk_buff *skb, writew(0, &p->nop_cmds[next_nop]->cmd_status); writew(make16(p->xmit_cmds[p->xmit_count]), &p->nop_cmds[p->xmit_count]->cmd_link); - dev->trans_start = jiffies; p->xmit_count = next_nop; { unsigned long flags; diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index 9225c76..da228a0 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -784,7 +784,7 @@ static void ni65_stop_start(struct net_device *dev,struct priv *p) if(!p->lock) if (p->tmdnum || !p->xmit_queued) netif_wake_queue(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } else writedatareg(CSR0_STRT | csr0); @@ -1150,7 +1150,7 @@ static void ni65_timeout(struct net_device *dev) printk("%02x ",p->tmdhead[i].u.s.status); printk("\n"); ni65_lance_reinit(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -1213,7 +1213,6 @@ static netdev_tx_t ni65_send_packet(struct sk_buff *skb, netif_wake_queue(dev); p->lock = 0; - dev->trans_start = jiffies; spin_unlock_irqrestore(&p->ring_lock, flags); } diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index 3924703..43bf26f 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -992,7 +992,6 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) /* Ring the bell. */ cvmx_write_csr(CVMX_MIXX_ORING2(port), 1); - netdev->trans_start = jiffies; rv = NETDEV_TX_OK; out: octeon_mgmt_update_tx_stats(netdev); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index dc3b4c7..56f3fc4 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1354,7 +1354,6 @@ static int netdrv_start_xmit(struct sk_buff *skb, struct net_device *dev) NETDRV_W32(TxStatus0 + (entry * sizeof(u32)), tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); - dev->trans_start = jiffies; atomic_inc(&tp->cur_tx); if ((atomic_read(&tp->cur_tx) - atomic_read(&tp->dirty_tx)) >= NUM_TX_DESC) netif_stop_queue(dev); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 757f87b..b6d9313 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -739,7 +739,7 @@ static void el3_tx_timeout(struct net_device *dev) printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name); dump_status(dev); dev->stats.tx_errors++; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* Issue TX_RESET and TX_START commands. */ tc574_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); @@ -790,8 +790,6 @@ static netdev_tx_t el3_start_xmit(struct sk_buff *skb, /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2); - dev->trans_start = jiffies; - /* TxFree appears only in Window 1, not offset 0x1c. */ if (inw(ioaddr + TxFree) <= 1536) { netif_stop_queue(dev); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 580977f..d6a459d 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -563,7 +563,7 @@ static void el3_tx_timeout(struct net_device *dev) netdev_warn(dev, "Transmit timed out!\n"); dump_status(dev); dev->stats.tx_errors++; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* Issue TX_RESET and TX_START commands. */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); @@ -611,7 +611,6 @@ static netdev_tx_t el3_start_xmit(struct sk_buff *skb, /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev->trans_start = jiffies; if (inw(ioaddr + TX_FREE) <= 1536) { netif_stop_queue(dev); /* Interrupt us when the FIFO has room for max-sized packet. */ diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 70fc959..a1a6b08 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1005,7 +1005,7 @@ static void axnet_tx_timeout(struct net_device *dev) { long e8390_base = dev->base_addr; struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int txsr, isr, tickssofar = jiffies - dev->trans_start; + int txsr, isr, tickssofar = jiffies - dev_trans_start(dev); unsigned long flags; dev->stats.tx_errors++; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 6734f7d..16fc3e5 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -890,7 +890,6 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb, lp->sent = lp->tx_queue ; lp->tx_queue = 0; lp->tx_queue_len = 0; - dev->trans_start = jiffies; lp->tx_started = 1; netif_start_queue(dev); } else { diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index c516c19..ca4efd2 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -903,7 +903,7 @@ static void mace_tx_timeout(struct net_device *dev) #else /* #if RESET_ON_TIMEOUT */ printk("NOT resetting card\n"); #endif /* #if RESET_ON_TIMEOUT */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -945,8 +945,6 @@ static netdev_tx_t mace_start_xmit(struct sk_buff *skb, outb(skb->data[skb->len-1], ioaddr + AM2150_XMT); } - dev->trans_start = jiffies; - #if MULTI_TX if (lp->tx_free_frames > 0) netif_start_queue(dev); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 949ac1a..b5c62db 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1254,7 +1254,7 @@ static void smc_tx_timeout(struct net_device *dev) dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2)); dev->stats.tx_errors++; smc_reset(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ smc->saved_skb = NULL; netif_wake_queue(dev); } diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 656be93..6622f04 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1295,7 +1295,7 @@ xirc2ps_tx_timeout_task(struct work_struct *work) struct net_device *dev = local->dev; /* reset the card */ do_reset(dev,1); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -1358,7 +1358,6 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) PutByte(XIRCREG_CR, TransmitPacket|EnableIntr); dev_kfree_skb (skb); - dev->trans_start = jiffies; dev->stats.tx_bytes += pktlen; netif_start_queue(dev); return NETDEV_TX_OK; diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index a2254f7..566fd89 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -448,7 +448,7 @@ static void pcnet32_netif_stop(struct net_device *dev) { struct pcnet32_private *lp = netdev_priv(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ napi_disable(&lp->napi); netif_tx_disable(dev); } @@ -2398,7 +2398,7 @@ static void pcnet32_tx_timeout(struct net_device *dev) } pcnet32_restart(dev, CSR0_NORMAL); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -2449,8 +2449,6 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb, /* Trigger an immediate send poll. */ lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL); - dev->trans_start = jiffies; - if (lp->tx_ring[(entry + 1) & lp->tx_mod_mask].base != 0) { lp->tx_full = 1; netif_stop_queue(dev); diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 9a2103a..f4e1f9a 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -979,7 +979,6 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: send request\n", dev->name); spin_lock_irq(&nl->lock); - dev->trans_start = jiffies; snd->skb = skb; snd->length.h = skb->len; snd->state = PLIP_PK_TRIGGER; diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 022317d..87d6b8f 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -903,9 +903,6 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) gelic_descr_release_tx(card, descr->next); card->tx_chain.tail = descr->next->next; dev_info(ctodev(card), "%s: kick failure\n", __func__); - } else { - /* OK, DMA started/reserved */ - netdev->trans_start = jiffies; } spin_unlock_irqrestore(&card->tx_lock, flags); diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 4122916..3cc7bef 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -924,7 +924,6 @@ static netdev_tx_t r6040_start_xmit(struct sk_buff *skb, if (!lp->tx_free_desc) netif_stop_queue(dev); - dev->trans_start = jiffies; spin_unlock_irqrestore(&lp->lock, flags); return NETDEV_TX_OK; diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index f2e335f..e26e107 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -1467,7 +1467,6 @@ static netdev_tx_t rr_start_xmit(struct sk_buff *skb, spin_unlock_irqrestore(&rrpriv->lock, flags); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/s6gmac.c b/drivers/net/s6gmac.c index 6b12524..a7ff8ea 100644 --- a/drivers/net/s6gmac.c +++ b/drivers/net/s6gmac.c @@ -852,8 +852,8 @@ static int s6gmac_tx(struct sk_buff *skb, struct net_device *dev) { struct s6gmac *pd = netdev_priv(dev); unsigned long flags; + spin_lock_irqsave(&pd->lock, flags); - dev->trans_start = jiffies; writel(skb->len << S6_GMAC_BURST_PREWR_LEN | 0 << S6_GMAC_BURST_PREWR_CFE | 1 << S6_GMAC_BURST_PREWR_PPE | diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index fec3c29..1f3acc3 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2068,8 +2068,6 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - dev->trans_start = jiffies; - spin_unlock_irqrestore(&sc->sbm_lock, flags); return NETDEV_TX_OK; @@ -2488,7 +2486,7 @@ static void sbmac_tx_timeout (struct net_device *dev) spin_lock_irqsave(&sc->sbm_lock, flags); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; spin_unlock_irqrestore(&sc->sbm_lock, flags); diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 1b32605..8c4067a 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -987,8 +987,6 @@ static netdev_tx_t sc92031_start_xmit(struct sk_buff *skb, iowrite32(tx_status, port_base + TxStatus0 + entry * 4); mmiowb(); - dev->trans_start = jiffies; - if (priv->tx_head - priv->tx_tail >= NUM_TX_DESC) netif_stop_queue(dev); diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 374832c..11ab32e 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -390,7 +390,7 @@ static void seeq8005_timeout(struct net_device *dev) tx_done(dev) ? "IRQ conflict" : "network cable problem"); /* Try to restart the adaptor. */ seeq8005_init(dev, 1); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -411,7 +411,6 @@ static netdev_tx_t seeq8005_send_packet(struct sk_buff *skb, netif_stop_queue(dev); hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; dev->stats.tx_bytes += length; dev_kfree_skb (skb); /* You might need to clean up and record Tx statistics here. */ diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index c8fc896..cc4bd8c 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -574,7 +574,7 @@ static inline int sgiseeq_reset(struct net_device *dev) if (err) return err; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); return 0; @@ -638,8 +638,6 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) kick_tx(dev, sp, hregs); - dev->trans_start = jiffies; - if (!TX_BUFFS_AVAIL(sp)) netif_stop_queue(dev); spin_unlock_irqrestore(&sp->tx_lock, flags); @@ -652,7 +650,7 @@ static void timeout(struct net_device *dev) printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name); sgiseeq_reset(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 6242b85..586ed09 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1148,8 +1148,6 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (!(ctrl_inl(ndev->base_addr + EDTRR) & EDTRR_TRNS)) ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR); - ndev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 6293592..11f7ebe 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1553,7 +1553,7 @@ static void sis900_tx_timeout(struct net_device *net_dev) spin_unlock_irqrestore(&sis_priv->lock, flags); - net_dev->trans_start = jiffies; + net_dev->trans_start = jiffies; /* prevent tx timeout */ /* load Transmit Descriptor Register */ outl(sis_priv->tx_ring_dma, ioaddr + txdp); @@ -1623,8 +1623,6 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) spin_unlock_irqrestore(&sis_priv->lock, flags); - net_dev->trans_start = jiffies; - if (netif_msg_tx_queued(sis_priv)) printk(KERN_DEBUG "%s: Queued Tx packet at %p size %d " "to slot %d.\n", diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 7912606..91adc38 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -1076,7 +1076,6 @@ static netdev_tx_t skfp_send_pkt(struct sk_buff *skb, if (bp->QueueSkb == 0) { netif_stop_queue(dev); } - dev->trans_start = jiffies; return NETDEV_TX_OK; } // skfp_send_pkt diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 8969615..d92772e 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -458,7 +458,7 @@ static void sl_tx_timeout(struct net_device *dev) * 14 Oct 1994 Dmitry Gorodchanin. */ #ifdef SL_CHECK_TRANSMIT - if (time_before(jiffies, dev->trans_start + 20 * HZ)) { + if (time_before(jiffies, dev_trans_start(dev) + 20 * HZ)) { /* 20 sec timeout not reached */ goto out; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 1e49fcf..66831f3 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1289,7 +1289,7 @@ static void smc911x_timeout(struct net_device *dev) schedule_work(&lp->phy_configure); /* We can accept TX packets again */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index d76c815..acb81a8 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -1164,7 +1164,7 @@ static void smc_timeout(struct net_device *dev) /* "kick" the adaptor */ smc_reset( dev->base_addr ); smc_enable( dev->base_addr ); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ /* clear anything saved */ ((struct smc_local *)netdev_priv(dev))->saved_skb = NULL; netif_wake_queue(dev); diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 682bc4f..10cf0cb 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1360,7 +1360,7 @@ static void smc_timeout(struct net_device *dev) schedule_work(&lp->phy_configure); /* We can accept TX packets again */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 746fb91..89f35f9 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1335,7 +1335,6 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz); freespace -= (skb->len + 32); dev_kfree_skb(skb); - dev->trans_start = jiffies; if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30)) smsc911x_tx_update_txcounters(dev); diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index ada05c4..6cdee6a 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1034,8 +1034,6 @@ static netdev_tx_t smsc9420_hard_start_xmit(struct sk_buff *skb, smsc9420_reg_write(pd, TX_POLL_DEMAND, 1); smsc9420_pci_flush_write(pd); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index e5d6732..26e25d7 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -174,7 +174,7 @@ static void sonic_tx_timeout(struct net_device *dev) /* Try to restart the adaptor. */ sonic_init(dev); lp->stats.tx_errors++; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } @@ -263,8 +263,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 8a6d27c..e19b5a1 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1173,7 +1173,7 @@ static void tx_timeout(struct net_device *dev) /* Trigger an immediate transmit demand. */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ np->stats.tx_errors++; netif_wake_queue(dev); } @@ -1312,8 +1312,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) if ((np->cur_tx - np->dirty_tx) + 4 > TX_RING_SIZE) netif_stop_queue(dev); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index 31ab4ab..1513123 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -985,7 +985,7 @@ static void sun3_82586_timeout(struct net_device *dev) p->scb->cmd_cuc = CUC_START; sun3_attn586(); WAIT_4_SCB_CMD(); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ return 0; } #endif @@ -998,7 +998,7 @@ static void sun3_82586_timeout(struct net_device *dev) sun3_82586_close(dev); sun3_82586_open(dev); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } /****************************************************** @@ -1062,7 +1062,6 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) } sun3_attn586(); - dev->trans_start = jiffies; if(!i) dev_kfree_skb(skb); WAIT_4_SCB_CMD(); @@ -1082,7 +1081,6 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - dev->trans_start = jiffies; p->nop_point = next_nop; dev_kfree_skb(skb); # endif @@ -1097,7 +1095,6 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; p->xmit_count = next_nop; { diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 1694ca5..358c22f 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -523,8 +523,8 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) /* Transmitter timeout, serious problems. */ if (netif_queue_stopped(dev)) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 20) + int tickssofar = jiffies - dev_trans_start(dev); + if (tickssofar < HZ/5) return NETDEV_TX_BUSY; DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", @@ -559,7 +559,6 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; netif_start_queue(dev); - dev->trans_start = jiffies; return NETDEV_TX_OK; } @@ -637,8 +636,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) AREG = CSR0; DPRINTK( 2, ( "%s: lance_start_xmit() exiting, csr0 %4.4x.\n", dev->name, DREG )); - dev->trans_start = jiffies; - dev_kfree_skb( skb ); + dev_kfree_skb(skb); lp->lock = 0; if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 5291315..34446b6 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -982,8 +982,6 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev) sbus_writel(CREG_CTRL_TWAKEUP, bp->creg + CREG_CTRL); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index da45f01..1680325 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -972,7 +972,7 @@ static void tx_timeout(struct net_device *dev) dev->if_port = 0; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { netif_wake_queue(dev); @@ -1084,7 +1084,6 @@ start_tx (struct sk_buff *skb, struct net_device *dev) } else { netif_stop_queue (dev); } - dev->trans_start = jiffies; if (netif_msg_tx_queued(np)) { printk (KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 2b78e97..5bc786f 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1136,7 +1136,7 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb, writel(gp->tx_new, gp->regs + TXDMA_KICK); spin_unlock_irqrestore(&gp->tx_lock, flags); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ return NETDEV_TX_OK; } diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 982ff12..377c0b5 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2341,8 +2341,6 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb, spin_unlock_irq(&hp->happy_lock); - dev->trans_start = jiffies; - tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); return NETDEV_TX_OK; } diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index c7748b7..f88a60f 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1003,7 +1003,7 @@ static int lance_reset(struct net_device *dev) } lp->init_ring(dev); load_csrs(lp); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ status = init_restart_lance(lp); return status; } @@ -1160,7 +1160,6 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&lp->lock); - dev->trans_start = jiffies; dev_kfree_skb(skb); return NETDEV_TX_OK; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 239f097..a7542d2 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -602,7 +602,6 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev) qep->tx_new = NEXT_TX(entry); /* Get it going. */ - dev->trans_start = jiffies; sbus_writel(CREG_CTRL_TWAKEUP, qep->qcregs + CREG_CTRL); dev->stats.tx_packets++; diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 6cf8b06..d281a7b 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -717,7 +717,6 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb(skb); - dev->trans_start = jiffies; return NETDEV_TX_OK; out_dropped_unlock: diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 36149dd..be08b75 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1357,8 +1357,6 @@ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev) } lp->tfd_start = (lp->tfd_start + 1) % TX_FD_NUM; - dev->trans_start = jiffies; - /* If we just used up the very last entry in the * TX ring on this device, tell the queueing * layer to send no more. diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 8ffec22..ccee3ed 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1034,7 +1034,7 @@ static void TLan_tx_timeout(struct net_device *dev) TLan_ResetLists( dev ); TLan_ReadAndClearStats( dev, TLAN_IGNORE ); TLan_ResetAdapter( dev ); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue( dev ); } @@ -1147,7 +1147,6 @@ static netdev_tx_t TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS ); - dev->trans_start = jiffies; return NETDEV_TX_OK; } /* TLan_StartTx */ diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index eebdaae..91e6c78 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1041,7 +1041,6 @@ static netdev_tx_t tok_send_packet(struct sk_buff *skb, writew(ti->exsap_station_id, ti->srb + STATION_ID_OFST); writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); spin_unlock_irqrestore(&(ti->lock), flags); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index e405601..213b9af 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -4562,7 +4562,7 @@ static void smctr_timeout(struct net_device *dev) * fake transmission time and go on trying. Our own timeout * routine is in sktr_timer_chk() */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index c169fd0..8cb126a 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -592,7 +592,7 @@ static void tms380tr_timeout(struct net_device *dev) * fake transmission time and go on trying. Our own timeout * routine is in tms380tr_timer_chk() */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 9c0f29c..c0e7000 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -654,7 +654,6 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb, /* Trigger an immediate transmit demand. */ dw32(TxPoll, NormalTxPoll); - dev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index d818456..9522baf 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1337,7 +1337,7 @@ de4x5_open(struct net_device *dev) } lp->interrupt = UNMASK_INTERRUPTS; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ START_DE4X5; @@ -1507,7 +1507,6 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */ lp->tx_new = (++lp->tx_new) % lp->txRingSize; - dev->trans_start = jiffies; if (TX_BUFFS_AVAIL) { netif_start_queue(dev); /* Another pkt may be queued */ @@ -1937,7 +1936,7 @@ set_multicast_list(struct net_device *dev) lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } } } diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 7278ecb..bdb25b8 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -1180,11 +1180,11 @@ static void dmfe_timer(unsigned long data) /* TX polling kick monitor */ if ( db->tx_packet_cnt && - time_after(jiffies, dev->trans_start + DMFE_TX_KICK) ) { + time_after(jiffies, dev_trans_start(dev) + DMFE_TX_KICK) ) { outl(0x1, dev->base_addr + DCR1); /* Tx polling again */ /* TX Timeout */ - if ( time_after(jiffies, dev->trans_start + DMFE_TX_TIMEOUT) ) { + if (time_after(jiffies, dev_trans_start(dev) + DMFE_TX_TIMEOUT) ) { db->reset_TXtimeout++; db->wait_reset = 1; dev_warn(&dev->dev, "Tx timeout - resetting\n"); diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index 966efa1..a63e64b 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -67,7 +67,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5) */ if (tulip_media_cap[dev->if_port] & MediaIsMII) return; - if (! tp->nwayset || time_after(jiffies, dev->trans_start + 1*HZ)) { + if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); iowrite32(tp->csr6, ioaddr + CSR6); iowrite32(0x30, ioaddr + CSR12); diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 22e766e..254643e 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -605,7 +605,7 @@ static void tulip_tx_timeout(struct net_device *dev) out_unlock: spin_unlock_irqrestore (&tp->lock, flags); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue (dev); } @@ -707,8 +707,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&tp->lock, flags); - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index c7f9728..96de582 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -1040,11 +1040,11 @@ static void uli526x_timer(unsigned long data) /* TX polling kick monitor */ if ( db->tx_packet_cnt && - time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) { + time_after(jiffies, dev_trans_start(dev) + ULI526X_TX_KICK) ) { outl(0x1, dev->base_addr + DCR1); // Tx polling again // TX Timeout - if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) { + if ( time_after(jiffies, dev_trans_start(dev) + ULI526X_TX_TIMEOUT) ) { db->reset_TXtimeout++; db->wait_reset = 1; printk( "%s: Tx timeout - resetting\n", diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 18c8ced..60a8754 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -969,7 +969,7 @@ static void tx_timeout(struct net_device *dev) enable_irq(dev->irq); netif_wake_queue(dev); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ np->stats.tx_errors++; return; } @@ -1055,8 +1055,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) } spin_unlock_irq(&np->lock); - dev->trans_start = jiffies; - if (debug > 4) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d\n", dev->name, np->cur_tx, entry); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 6b150c07..dbdfb1f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -396,7 +396,6 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) /* Enqueue packet */ skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb); - dev->trans_start = jiffies; /* Notify and wake up reader process */ if (tun->flags & TUN_FASYNC) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index b94c4cc..22bde49 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -881,8 +881,6 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) wmb(); iowrite32(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister); - dev->trans_start = jiffies; - /* If we don't have room to put the worst case packet on the * queue, then we must stop the queue. We need 2 extra * descriptors -- one to prevent ring wrap, and one for the diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 081f76b..932602d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3148,8 +3148,6 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) /* set bd status and length */ out_be32((u32 __iomem *)bd, bd_status); - dev->trans_start = jiffies; - /* Move to next BD in the ring */ if (!(bd_status & T_W)) bd += sizeof(struct qe_bd); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index be0cc99..a6227f8 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -834,8 +834,6 @@ static netdev_tx_t hso_net_start_xmit(struct sk_buff *skb, } else { net->stats.tx_packets++; net->stats.tx_bytes += skb->len; - /* And tell the kernel when the last transmit started. */ - net->trans_start = jiffies; } dev_kfree_skb(skb); /* we're done */ diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index c4c334d..46890dc 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -856,7 +856,6 @@ skip: { kaweth->stats.tx_packets++; kaweth->stats.tx_bytes += skb->len; - net->trans_start = jiffies; } spin_unlock_irq(&kaweth->device_lock); diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 4183877..1cd17d2 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -808,7 +808,7 @@ static void write_bulk_callback(struct urb *urb) break; } - net->trans_start = jiffies; + net->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(net); } @@ -909,7 +909,6 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb, } else { pegasus->stats.tx_packets++; pegasus->stats.tx_bytes += skb->len; - net->trans_start = jiffies; } dev_kfree_skb(skb); diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 467bcff..4930f9d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1209,7 +1209,7 @@ static void rhine_reset_task(struct work_struct *work) spin_unlock_bh(&rp->lock); enable_irq(rp->pdev->irq); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; netif_wake_queue(dev); } @@ -1294,8 +1294,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN) netif_stop_queue(dev); - dev->trans_start = jiffies; - spin_unlock_irqrestore(&rp->lock, flags); if (debug > 4) { diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 616f8c9..42dffd3 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2606,7 +2606,6 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb, td_ptr->td_buf[0].size |= TD_QUEUE; mac_tx_queue_wake(vptr->mac_regs, qnum); - dev->trans_start = jiffies; spin_unlock_irqrestore(&vptr->lock, flags); out: return NETDEV_TX_OK; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 90e783a..3946232 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -992,7 +992,6 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD, tq->tx_ring.next2fill); } - netdev->trans_start = jiffies; return NETDEV_TX_OK; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index a4859f7..d45b08d 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -1175,8 +1175,6 @@ static netdev_tx_t dscc4_start_xmit(struct sk_buff *skb, spin_unlock(&dpriv->lock); #endif - dev->trans_start = jiffies; - if (debug > 2) dscc4_tx_print(dev, dpriv, "Xmit"); /* To be cleaned(unsigned int)/optimized. Later, ok ? */ diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c index 4dde2ea..a3ea27c 100644 --- a/drivers/net/wan/hd64570.c +++ b/drivers/net/wan/hd64570.c @@ -658,7 +658,6 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev) #endif writew(len, &desc->len); writeb(ST_TX_EOM, &desc->stat); - dev->trans_start = jiffies; port->txin = next_desc(port, port->txin, 1); sca_outw(desc_offset(port, port->txin, 1), diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c index aad9ed4..ea476cb 100644 --- a/drivers/net/wan/hd64572.c +++ b/drivers/net/wan/hd64572.c @@ -585,7 +585,6 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev) writew(len, &desc->len); writeb(ST_TX_EOM, &desc->stat); - dev->trans_start = jiffies; port->txin = (port->txin + 1) % card->tx_ring_buffers; sca_outl(desc_offset(port, port->txin, 1), diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 0c2cdde..88e3630 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -891,7 +891,6 @@ static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); - dev->trans_start = jiffies; if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ #if DEBUG_TX diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index b278503..e2c6f7f 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1506,8 +1506,6 @@ static netdev_tx_t lmc_start_xmit(struct sk_buff *skb, /* send now! */ LMC_CSR_WRITE (sc, csr_txpoll, 0); - dev->trans_start = jiffies; - spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_start_xmit_out"); @@ -2103,7 +2101,7 @@ static void lmc_driver_timeout(struct net_device *dev) printk("%s: Xmitter busy|\n", dev->name); sc->extra_stats.tx_tbusy_calls++; - if (jiffies - dev->trans_start < TX_TIMEOUT) + if (jiffies - dev_trans_start(dev) < TX_TIMEOUT) goto bug_out; /* @@ -2135,7 +2133,7 @@ static void lmc_driver_timeout(struct net_device *dev) sc->lmc_device->stats.tx_errors++; sc->extra_stats.tx_ProcTimeout++; /* -baz */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ bug_out: diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 17502d8..c6aa66e 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -1790,7 +1790,7 @@ static void cpc_tx_timeout(struct net_device *dev) cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED1 << (2 * ch))); } - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ CPC_UNLOCK(card, flags); netif_wake_queue(dev); } @@ -1849,7 +1849,6 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev) if (d->trace_on) { cpc_trace(dev, skb, 'T'); } - dev->trans_start = jiffies; /* Start transmission */ CPC_LOCK(card, flags); diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 541c700..db73a7b 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -298,7 +298,6 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev) desc->stat = PACKET_FULL; writel(1 << (DOORBELL_TO_CARD_TX_0 + port->node), port->card->plx + PLX_DOORBELL_TO_CARD); - dev->trans_start = jiffies; port->tx_out = (port->tx_out + 1) % TX_BUFFERS; diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 3edbbcf..c8f7090 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -865,7 +865,6 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) /* low bit of first byte of destination tells us if broadcast */ tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA); - dev->trans_start = jiffies; dev->stats.tx_bytes += len; spin_unlock_irqrestore(&priv->irqlock, flags); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 38edad6..d9b8ee1 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -229,7 +229,7 @@ static void lbs_tx_timeout(struct net_device *dev) lbs_pr_err("tx watch dog timeout\n"); - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ if (priv->currenttxskb) lbs_send_tx_feedback(priv, 0); diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 52d244e..a9bf658 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -147,8 +147,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - if (priv->monitormode) { /* Keep the skb to echo it back once Tx feedback is received from FW */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 1d60c7e..884a777 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -517,7 +517,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) goto busy; } - dev->trans_start = jiffies; stats->tx_bytes += HERMES_802_3_OFFSET + skb->len; goto ok; diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 64585da..2fc52bc 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -224,8 +224,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) priv->data_low_tx_full = 1; } - /* set the transmission time */ - ndev->trans_start = jiffies; ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index d9c45bf..73972ee 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -941,7 +941,6 @@ static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb, case XMIT_MSG_BAD: case XMIT_OK: default: - dev->trans_start = jiffies; dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 65dd502..1e61e6c 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1307,7 +1307,7 @@ static void wl3501_tx_timeout(struct net_device *dev) printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n", dev->name, rc); else { - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } } @@ -1326,7 +1326,6 @@ static netdev_tx_t wl3501_hard_start_xmit(struct sk_buff *skb, spin_lock_irqsave(&this->lock, flags); enabled = wl3501_block_interrupt(this); - dev->trans_start = jiffies; rc = wl3501_send_pkt(this, skb->data, skb->len); if (enabled) wl3501_unblock_interrupt(this); diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 1e2b684..ece86a5 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -827,7 +827,6 @@ static netdev_tx_t zd1201_hard_start_xmit(struct sk_buff *skb, } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; } kfree_skb(skb); @@ -845,7 +844,7 @@ static void zd1201_tx_timeout(struct net_device *dev) usb_unlink_urb(zd->tx_urb); dev->stats.tx_errors++; /* Restart the timeout to quiet the watchdog: */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } static int zd1201_set_mac_address(struct net_device *dev, void *p) diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index 93828d5..a7db68d 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -558,7 +558,7 @@ static void xemaclite_tx_timeout(struct net_device *dev) } /* To exclude tx timeout */ - dev->trans_start = 0xffffffff - TX_TIMEOUT - TX_TIMEOUT; + dev->trans_start = jiffies; /* prevent tx timeout */ /* We're all ready to go. Start the queue */ netif_wake_queue(dev); @@ -590,7 +590,7 @@ static void xemaclite_tx_handler(struct net_device *dev) dev->stats.tx_bytes += lp->deferred_skb->len; dev_kfree_skb_irq(lp->deferred_skb); lp->deferred_skb = NULL; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); } } @@ -1054,7 +1054,6 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev) dev->stats.tx_bytes += len; dev_kfree_skb(new_skb); - dev->trans_start = jiffies; return 0; } diff --git a/drivers/net/znet.c b/drivers/net/znet.c index dbfef8d..b9fd2f0 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -587,7 +587,6 @@ static netdev_tx_t znet_send_packet(struct sk_buff *skb, struct net_device *dev) } spin_unlock_irqrestore (&znet->lock, flags); - dev->trans_start = jiffies; netif_start_queue (dev); if (znet_debug > 4) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ce3c99e..e42f6ed 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -107,6 +107,8 @@ struct hci_dev { unsigned long acl_last_tx; unsigned long sco_last_tx; + struct workqueue_struct *workqueue; + struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; @@ -636,8 +638,8 @@ int hci_register_notifier(struct notifier_block *nb); int hci_unregister_notifier(struct notifier_block *nb); int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); -int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); -int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); +void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); +void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 17a689f..7c695bf 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -30,11 +30,12 @@ #define L2CAP_DEFAULT_MIN_MTU 48 #define L2CAP_DEFAULT_FLUSH_TO 0xffff #define L2CAP_DEFAULT_TX_WINDOW 63 -#define L2CAP_DEFAULT_NUM_TO_ACK (L2CAP_DEFAULT_TX_WINDOW/5) #define L2CAP_DEFAULT_MAX_TX 3 #define L2CAP_DEFAULT_RETRANS_TO 1000 /* 1 second */ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ #define L2CAP_DEFAULT_MAX_PDU_SIZE 672 +#define L2CAP_DEFAULT_ACK_TO 200 +#define L2CAP_LOCAL_BUSY_TRIES 12 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ @@ -55,6 +56,8 @@ struct l2cap_options { __u16 flush_to; __u8 mode; __u8 fcs; + __u8 max_tx; + __u16 txwin_size; }; #define L2CAP_CONNINFO 0x02 @@ -292,6 +295,7 @@ struct l2cap_conn { #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) +#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) struct srej_list { @@ -320,7 +324,7 @@ struct l2cap_pinfo { __u8 conf_req[64]; __u8 conf_len; __u8 conf_state; - __u8 conn_state; + __u16 conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -328,27 +332,35 @@ struct l2cap_pinfo { __u8 buffer_seq; __u8 buffer_seq_srej; __u8 srej_save_reqseq; + __u8 frames_sent; __u8 unacked_frames; __u8 retry_count; - __u8 num_to_ack; + __u8 num_acked; __u16 sdu_len; __u16 partial_sdu_len; struct sk_buff *sdu; __u8 ident; + __u8 tx_win; + __u8 max_tx; __u8 remote_tx_win; __u8 remote_max_tx; __u16 retrans_timeout; __u16 monitor_timeout; - __u16 max_pdu_size; + __u16 remote_mps; + __u16 mps; __le16 sport; + spinlock_t send_lock; struct timer_list retrans_timer; struct timer_list monitor_timer; + struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; + struct sk_buff_head busy_queue; + struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; struct sock *next_c; @@ -367,19 +379,24 @@ struct l2cap_pinfo { #define L2CAP_CONF_MAX_CONF_REQ 2 #define L2CAP_CONF_MAX_CONF_RSP 2 -#define L2CAP_CONN_SAR_SDU 0x01 -#define L2CAP_CONN_SREJ_SENT 0x02 -#define L2CAP_CONN_WAIT_F 0x04 -#define L2CAP_CONN_SREJ_ACT 0x08 -#define L2CAP_CONN_SEND_PBIT 0x10 -#define L2CAP_CONN_REMOTE_BUSY 0x20 -#define L2CAP_CONN_LOCAL_BUSY 0x40 -#define L2CAP_CONN_REJ_ACT 0x80 +#define L2CAP_CONN_SAR_SDU 0x0001 +#define L2CAP_CONN_SREJ_SENT 0x0002 +#define L2CAP_CONN_WAIT_F 0x0004 +#define L2CAP_CONN_SREJ_ACT 0x0008 +#define L2CAP_CONN_SEND_PBIT 0x0010 +#define L2CAP_CONN_REMOTE_BUSY 0x0020 +#define L2CAP_CONN_LOCAL_BUSY 0x0040 +#define L2CAP_CONN_REJ_ACT 0x0080 +#define L2CAP_CONN_SEND_FBIT 0x0100 +#define L2CAP_CONN_RNR_SENT 0x0200 +#define L2CAP_CONN_SAR_RETRY 0x0400 #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); #define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); +#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ + jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); static inline int l2cap_tx_window_full(struct sock *sk) { diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index ed37168..ee3b304 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -43,6 +43,19 @@ config BT_L2CAP Say Y here to compile L2CAP support into the kernel or say M to compile it as module (l2cap). +config BT_L2CAP_EXT_FEATURES + bool "L2CAP Extended Features support (EXPERIMENTAL)" + depends on BT_L2CAP && EXPERIMENTAL + help + This option enables the L2CAP Extended Features support. These + new features include the Enhanced Retransmission and Streaming + Modes, the Frame Check Sequence (FCS), and Segmentation and + Reassembly (SAR) for L2CAP packets. They are a required for the + new Alternate MAC/PHY and the Bluetooth Medical Profile. + + You should say N unless you know what you are doing. Note that + this is in an experimental state yet. + config BT_SCO tristate "SCO links support" depends on BT diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4ad2319..5e83f8e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -37,6 +37,7 @@ #include <linux/fcntl.h> #include <linux/init.h> #include <linux/skbuff.h> +#include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/notifier.h> #include <linux/rfkill.h> @@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev) write_unlock_bh(&hci_dev_list_lock); + hdev->workqueue = create_singlethread_workqueue(hdev->name); + if (!hdev->workqueue) + goto nomem; + hci_register_sysfs(hdev); hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, @@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_REG); return id; + +nomem: + write_lock_bh(&hci_dev_list_lock); + list_del(&hdev->list); + write_unlock_bh(&hci_dev_list_lock); + + return -ENOMEM; } EXPORT_SYMBOL(hci_register_dev); @@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_unregister_sysfs(hdev); + destroy_workqueue(hdev->workqueue); + __hci_dev_put(hdev); return 0; @@ -1260,7 +1274,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) hdr->dlen = cpu_to_le16(len); } -int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) +void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) { struct hci_dev *hdev = conn->hdev; struct sk_buff *list; @@ -1303,23 +1317,18 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) tasklet_schedule(&hdev->tx_task); - return 0; + return; } EXPORT_SYMBOL(hci_send_acl); /* Send SCO data */ -int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) +void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) { struct hci_dev *hdev = conn->hdev; struct hci_sco_hdr hdr; BT_DBG("%s len %d", hdev->name, skb->len); - if (skb->len > hdev->sco_mtu) { - kfree_skb(skb); - return -EINVAL; - } - hdr.handle = cpu_to_le16(conn->handle); hdr.dlen = skb->len; @@ -1332,8 +1341,6 @@ int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) skb_queue_tail(&conn->data_q, skb); tasklet_schedule(&hdev->tx_task); - - return 0; } EXPORT_SYMBOL(hci_send_sco); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 0e8e1a5..463ffa4 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -14,8 +14,6 @@ static struct class *bt_class; struct dentry *bt_debugfs = NULL; EXPORT_SYMBOL_GPL(bt_debugfs); -static struct workqueue_struct *bt_workq; - static inline char *link_typetostr(int type) { switch (type) { @@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_add); + queue_work(conn->hdev->workqueue, &conn->work_add); } void hci_conn_del_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_del); + queue_work(conn->hdev->workqueue, &conn->work_del); } static inline char *host_bustostr(int bus) @@ -283,11 +281,9 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u32 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val != 0 && (val < 500 || val > 3600000)) @@ -307,11 +303,9 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u16 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val < 0x0002 || val > 0xFFFE || val % 2) @@ -334,11 +328,9 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hci_dev *hdev = dev_get_drvdata(dev); - char *ptr; - __u16 val; + unsigned long val; - val = simple_strtoul(buf, &ptr, 10); - if (ptr == buf) + if (strict_strtoul(buf, 0, &val) < 0) return -EINVAL; if (val < 0x0002 || val > 0xFFFE || val % 2) @@ -487,17 +479,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - bt_workq = create_singlethread_workqueue("bluetooth"); - if (!bt_workq) - return -ENOMEM; - bt_debugfs = debugfs_create_dir("bluetooth", NULL); bt_class = class_create(THIS_MODULE, "bluetooth"); - if (IS_ERR(bt_class)) { - destroy_workqueue(bt_workq); + if (IS_ERR(bt_class)) return PTR_ERR(bt_class); - } return 0; } @@ -507,6 +493,4 @@ void bt_sysfs_cleanup(void) class_destroy(bt_class); debugfs_remove_recursive(bt_debugfs); - - destroy_workqueue(bt_workq); } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 864c76f..673a368 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -55,18 +55,27 @@ #define VERSION "2.14" +#ifdef CONFIG_BT_L2CAP_EXT_FEATURES +static int enable_ertm = 1; +#else static int enable_ertm = 0; +#endif static int max_transmit = L2CAP_DEFAULT_MAX_TX; +static int tx_window = L2CAP_DEFAULT_TX_WINDOW; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u8 l2cap_fixed_chan[8] = { 0x02, }; static const struct proto_ops l2cap_sock_ops; +static struct workqueue_struct *_busy_wq; + static struct bt_sock_list l2cap_sk_list = { .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) }; +static void l2cap_busy_work(struct work_struct *work); + static void __l2cap_sock_close(struct sock *sk, int reason); static void l2cap_sock_close(struct sock *sk); static void l2cap_sock_kill(struct sock *sk); @@ -219,7 +228,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so l2cap_pi(sk)->conn = conn; - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { /* Alloc CID for connection-oriented socket */ l2cap_pi(sk)->scid = l2cap_alloc_cid(l); } else if (sk->sk_type == SOCK_DGRAM) { @@ -325,19 +334,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) return id; } -static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) +static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) { struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); BT_DBG("code 0x%2.2x", code); if (!skb) - return -ENOMEM; + return; - return hci_send_acl(conn->hcon, skb, 0); + hci_send_acl(conn->hcon, skb, 0); } -static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) { struct sk_buff *skb; struct l2cap_hdr *lh; @@ -352,9 +361,19 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) count = min_t(unsigned int, conn->mtu, hlen); control |= L2CAP_CTRL_FRAME_TYPE; + if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + control |= L2CAP_CTRL_FINAL; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } + + if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { + control |= L2CAP_CTRL_POLL; + pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; + } + skb = bt_skb_alloc(count, GFP_ATOMIC); if (!skb) - return -ENOMEM; + return; lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); @@ -366,19 +385,20 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) put_unaligned_le16(fcs, skb_put(skb, 2)); } - return hci_send_acl(pi->conn->hcon, skb, 0); + hci_send_acl(pi->conn->hcon, skb, 0); } -static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) { - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - else + pi->conn_state |= L2CAP_CONN_RNR_SENT; + } else control |= L2CAP_SUPER_RCV_READY; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - return l2cap_send_sframe(pi, control); + l2cap_send_sframe(pi, control); } static void l2cap_do_start(struct sock *sk) @@ -437,7 +457,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { bh_lock_sock(sk); - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { bh_unlock_sock(sk); continue; } @@ -497,7 +518,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { bh_lock_sock(sk); - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); sk->sk_state = BT_CONNECTED; sk->sk_state_change(sk); @@ -706,7 +728,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) case BT_CONNECTED: case BT_CONFIG: - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || + sk->sk_type == SOCK_STREAM) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; sk->sk_state = BT_DISCONN; @@ -717,7 +740,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) break; case BT_CONNECT2: - if (sk->sk_type == SOCK_SEQPACKET) { + if (sk->sk_type == SOCK_SEQPACKET || + sk->sk_type == SOCK_STREAM) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct l2cap_conn_rsp rsp; __u16 result; @@ -772,14 +796,21 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = l2cap_pi(parent)->omtu; pi->mode = l2cap_pi(parent)->mode; pi->fcs = l2cap_pi(parent)->fcs; + pi->max_tx = l2cap_pi(parent)->max_tx; + pi->tx_win = l2cap_pi(parent)->tx_win; pi->sec_level = l2cap_pi(parent)->sec_level; pi->role_switch = l2cap_pi(parent)->role_switch; pi->force_reliable = l2cap_pi(parent)->force_reliable; } else { pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; - pi->mode = L2CAP_MODE_BASIC; + if (enable_ertm && sk->sk_type == SOCK_STREAM) + pi->mode = L2CAP_MODE_ERTM; + else + pi->mode = L2CAP_MODE_BASIC; + pi->max_tx = max_transmit; pi->fcs = L2CAP_FCS_CRC16; + pi->tx_win = tx_window; pi->sec_level = BT_SECURITY_LOW; pi->role_switch = 0; pi->force_reliable = 0; @@ -790,6 +821,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); skb_queue_head_init(SREJ_QUEUE(sk)); + skb_queue_head_init(BUSY_QUEUE(sk)); INIT_LIST_HEAD(SREJ_LIST(sk)); } @@ -833,7 +865,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, sock->state = SS_UNCONNECTED; - if (sock->type != SOCK_SEQPACKET && + if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; @@ -981,7 +1013,8 @@ static int l2cap_do_connect(struct sock *sk) l2cap_sock_set_timer(sk, sk->sk_sndtimeo); if (hcon->state == BT_CONNECTED) { - if (sk->sk_type != SOCK_SEQPACKET) { + if (sk->sk_type != SOCK_SEQPACKET && + sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); sk->sk_state = BT_CONNECTED; } else @@ -1015,7 +1048,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al lock_sock(sk); - if (sk->sk_type == SOCK_SEQPACKET && !la.l2_psm) { + if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) + && !la.l2_psm) { err = -EINVAL; goto done; } @@ -1079,7 +1113,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) lock_sock(sk); - if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) { + if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) + || sk->sk_state != BT_BOUND) { err = -EBADFD; goto done; } @@ -1207,10 +1242,40 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l return 0; } +static int __l2cap_wait_ack(struct sock *sk) +{ + DECLARE_WAITQUEUE(wait, current); + int err = 0; + int timeo = HZ/5; + + add_wait_queue(sk_sleep(sk), &wait); + while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { + set_current_state(TASK_INTERRUPTIBLE); + + if (!timeo) + timeo = HZ/5; + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + err = sock_error(sk); + if (err) + break; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(sk_sleep(sk), &wait); + return err; +} + static void l2cap_monitor_timeout(unsigned long arg) { struct sock *sk = (void *) arg; - u16 control; bh_lock_sock(sk); if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { @@ -1222,15 +1287,13 @@ static void l2cap_monitor_timeout(unsigned long arg) l2cap_pi(sk)->retry_count++; __mod_monitor_timer(); - control = L2CAP_CTRL_POLL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); + l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); bh_unlock_sock(sk); } static void l2cap_retrans_timeout(unsigned long arg) { struct sock *sk = (void *) arg; - u16 control; bh_lock_sock(sk); l2cap_pi(sk)->retry_count = 1; @@ -1238,8 +1301,7 @@ static void l2cap_retrans_timeout(unsigned long arg) l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; - control = L2CAP_CTRL_POLL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); + l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); bh_unlock_sock(sk); } @@ -1247,7 +1309,8 @@ static void l2cap_drop_acked_frames(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_peek(TX_QUEUE(sk)))) { + while ((skb = skb_peek(TX_QUEUE(sk))) && + l2cap_pi(sk)->unacked_frames) { if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) break; @@ -1263,18 +1326,13 @@ static void l2cap_drop_acked_frames(struct sock *sk) return; } -static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb) +static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) { struct l2cap_pinfo *pi = l2cap_pi(sk); - int err; BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); - err = hci_send_acl(pi->conn->hcon, skb, 0); - if (err < 0) - kfree_skb(skb); - - return err; + hci_send_acl(pi->conn->hcon, skb, 0); } static int l2cap_streaming_send(struct sock *sk) @@ -1282,7 +1340,6 @@ static int l2cap_streaming_send(struct sock *sk) struct sk_buff *skb, *tx_skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - int err; while ((skb = sk->sk_send_head)) { tx_skb = skb_clone(skb, GFP_ATOMIC); @@ -1291,16 +1348,12 @@ static int l2cap_streaming_send(struct sock *sk) control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { + if (pi->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } + l2cap_do_send(sk, tx_skb); pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; @@ -1315,48 +1368,44 @@ static int l2cap_streaming_send(struct sock *sk) return 0; } -static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) +static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; - int err; skb = skb_peek(TX_QUEUE(sk)); - do { - if (bt_cb(skb)->tx_seq != tx_seq) { - if (skb_queue_is_last(TX_QUEUE(sk), skb)) - break; - skb = skb_queue_next(TX_QUEUE(sk), skb); - continue; - } + if (!skb) + return; - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk); + do { + if (bt_cb(skb)->tx_seq == tx_seq) break; - } - tx_skb = skb_clone(skb, GFP_ATOMIC); - bt_cb(skb)->retries++; - control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) - | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); + if (skb_queue_is_last(TX_QUEUE(sk), skb)) + return; - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); - put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); - } + } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } - break; - } while(1); - return 0; + if (pi->remote_max_tx && + bt_cb(skb)->retries == pi->remote_max_tx) { + l2cap_send_disconn_req(pi->conn, sk); + return; + } + + tx_skb = skb_clone(skb, GFP_ATOMIC); + bt_cb(skb)->retries++; + control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); + control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); + put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); + + if (pi->fcs == L2CAP_FCS_CRC16) { + fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); + put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); + } + + l2cap_do_send(sk, tx_skb); } static int l2cap_ertm_send(struct sock *sk) @@ -1364,13 +1413,13 @@ static int l2cap_ertm_send(struct sock *sk) struct sk_buff *skb, *tx_skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - int err; + int nsent = 0; if (pi->conn_state & L2CAP_CONN_WAIT_F) return 0; while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && - !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { + !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { if (pi->remote_max_tx && bt_cb(skb)->retries == pi->remote_max_tx) { @@ -1383,35 +1432,97 @@ static int l2cap_ertm_send(struct sock *sk) bt_cb(skb)->retries++; control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); + if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + control |= L2CAP_CTRL_FINAL; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { + if (pi->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } + l2cap_do_send(sk, tx_skb); + __mod_retrans_timer(); bt_cb(skb)->tx_seq = pi->next_tx_seq; pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; pi->unacked_frames++; + pi->frames_sent++; if (skb_queue_is_last(TX_QUEUE(sk), skb)) sk->sk_send_head = NULL; else sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); + + nsent++; } - return 0; + return nsent; +} + +static int l2cap_retransmit_frames(struct sock *sk) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int ret; + + spin_lock_bh(&pi->send_lock); + + if (!skb_queue_empty(TX_QUEUE(sk))) + sk->sk_send_head = TX_QUEUE(sk)->next; + + pi->next_tx_seq = pi->expected_ack_seq; + ret = l2cap_ertm_send(sk); + + spin_unlock_bh(&pi->send_lock); + + return ret; +} + +static void l2cap_send_ack(struct l2cap_pinfo *pi) +{ + struct sock *sk = (struct sock *)pi; + u16 control = 0; + int nframes; + + control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + control |= L2CAP_SUPER_RCV_NOT_READY; + pi->conn_state |= L2CAP_CONN_RNR_SENT; + l2cap_send_sframe(pi, control); + return; + } + + spin_lock_bh(&pi->send_lock); + nframes = l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + + if (nframes > 0) + return; + + control |= L2CAP_SUPER_RCV_READY; + l2cap_send_sframe(pi, control); +} + +static void l2cap_send_srejtail(struct sock *sk) +{ + struct srej_list *tail; + u16 control; + + control = L2CAP_SUPER_SELECT_REJECT; + control |= L2CAP_CTRL_FINAL; + + tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); + control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + l2cap_send_sframe(l2cap_pi(sk), control); } static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) @@ -1420,9 +1531,8 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in struct sk_buff **frag; int err, sent = 0; - if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { + if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) return -EFAULT; - } sent += count; len -= count; @@ -1513,6 +1623,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *m BT_DBG("sk %p len %d", sk, (int)len); + if (!conn) + return ERR_PTR(-ENOTCONN); + if (sdulen) hlen += 2; @@ -1554,25 +1667,24 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz u16 control; size_t size = 0; - __skb_queue_head_init(&sar_queue); + skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len); + skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); __skb_queue_tail(&sar_queue, skb); - len -= pi->max_pdu_size; - size +=pi->max_pdu_size; - control = 0; + len -= pi->remote_mps; + size += pi->remote_mps; while (len > 0) { size_t buflen; - if (len > pi->max_pdu_size) { - control |= L2CAP_SDU_CONTINUE; - buflen = pi->max_pdu_size; + if (len > pi->remote_mps) { + control = L2CAP_SDU_CONTINUE; + buflen = pi->remote_mps; } else { - control |= L2CAP_SDU_END; + control = L2CAP_SDU_END; buflen = len; } @@ -1585,11 +1697,12 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz __skb_queue_tail(&sar_queue, skb); len -= buflen; size += buflen; - control = 0; } skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); + spin_lock_bh(&pi->send_lock); if (sk->sk_send_head == NULL) sk->sk_send_head = sar_queue.next; + spin_unlock_bh(&pi->send_lock); return size; } @@ -1611,11 +1724,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; - /* Check outgoing MTU */ - if (sk->sk_type == SOCK_SEQPACKET && pi->mode == L2CAP_MODE_BASIC && - len > pi->omtu) - return -EINVAL; - lock_sock(sk); if (sk->sk_state != BT_CONNECTED) { @@ -1626,15 +1734,23 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Connectionless channel */ if (sk->sk_type == SOCK_DGRAM) { skb = l2cap_create_connless_pdu(sk, msg, len); - if (IS_ERR(skb)) + if (IS_ERR(skb)) { err = PTR_ERR(skb); - else - err = l2cap_do_send(sk, skb); + } else { + l2cap_do_send(sk, skb); + err = len; + } goto done; } switch (pi->mode) { case L2CAP_MODE_BASIC: + /* Check outgoing MTU */ + if (len > pi->omtu) { + err = -EINVAL; + goto done; + } + /* Create a basic PDU */ skb = l2cap_create_basic_pdu(sk, msg, len); if (IS_ERR(skb)) { @@ -1642,15 +1758,14 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - err = l2cap_do_send(sk, skb); - if (!err) - err = len; + l2cap_do_send(sk, skb); + err = len; break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->max_pdu_size) { + if (len <= pi->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); if (IS_ERR(skb)) { @@ -1658,8 +1773,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } __skb_queue_tail(TX_QUEUE(sk), skb); + + if (pi->mode == L2CAP_MODE_ERTM) + spin_lock_bh(&pi->send_lock); + if (sk->sk_send_head == NULL) sk->sk_send_head = skb; + + if (pi->mode == L2CAP_MODE_ERTM) + spin_unlock_bh(&pi->send_lock); } else { /* Segment SDU into multiples PDUs */ err = l2cap_sar_segment_sdu(sk, msg, len); @@ -1667,12 +1789,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - if (pi->mode == L2CAP_MODE_STREAMING) + if (pi->mode == L2CAP_MODE_STREAMING) { err = l2cap_streaming_send(sk); - else + } else { + spin_lock_bh(&pi->send_lock); err = l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + } - if (!err) + if (err >= 0) err = len; break; @@ -1731,6 +1856,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.max_tx = l2cap_pi(sk)->max_tx; + opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { @@ -1738,10 +1865,25 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } + l2cap_pi(sk)->mode = opts.mode; + switch (l2cap_pi(sk)->mode) { + case L2CAP_MODE_BASIC: + break; + case L2CAP_MODE_ERTM: + case L2CAP_MODE_STREAMING: + if (enable_ertm) + break; + /* fall through */ + default: + err = -EINVAL; + break; + } + l2cap_pi(sk)->imtu = opts.imtu; l2cap_pi(sk)->omtu = opts.omtu; - l2cap_pi(sk)->mode = opts.mode; l2cap_pi(sk)->fcs = opts.fcs; + l2cap_pi(sk)->max_tx = opts.max_tx; + l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; break; case L2CAP_LM: @@ -1789,7 +1931,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch switch (optname) { case BT_SECURITY: - if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM + && sk->sk_type != SOCK_RAW) { err = -EINVAL; break; } @@ -1856,6 +1999,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; opts.fcs = l2cap_pi(sk)->fcs; + opts.max_tx = l2cap_pi(sk)->max_tx; + opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; len = min_t(unsigned int, len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) @@ -1937,7 +2082,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch switch (optname) { case BT_SECURITY: - if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM + && sk->sk_type != SOCK_RAW) { err = -EINVAL; break; } @@ -1982,6 +2128,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) lock_sock(sk); if (!sk->sk_shutdown) { + if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + err = __l2cap_wait_ack(sk); + sk->sk_shutdown = SHUTDOWN_MASK; l2cap_sock_clear_timer(sk); __l2cap_sock_close(sk, 0); @@ -2184,19 +2333,35 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) *ptr += L2CAP_CONF_OPT_SIZE + len; } +static void l2cap_ack_timeout(unsigned long arg) +{ + struct sock *sk = (void *) arg; + + bh_lock_sock(sk); + l2cap_send_ack(l2cap_pi(sk)); + bh_unlock_sock(sk); +} + static inline void l2cap_ertm_init(struct sock *sk) { l2cap_pi(sk)->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; l2cap_pi(sk)->buffer_seq = 0; - l2cap_pi(sk)->num_to_ack = 0; + l2cap_pi(sk)->num_acked = 0; + l2cap_pi(sk)->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, l2cap_retrans_timeout, (unsigned long) sk); setup_timer(&l2cap_pi(sk)->monitor_timer, l2cap_monitor_timeout, (unsigned long) sk); + setup_timer(&l2cap_pi(sk)->ack_timer, + l2cap_ack_timeout, (unsigned long) sk); __skb_queue_head_init(SREJ_QUEUE(sk)); + __skb_queue_head_init(BUSY_QUEUE(sk)); + spin_lock_init(&l2cap_pi(sk)->send_lock); + + INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); } static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) @@ -2232,7 +2397,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; - struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; + struct l2cap_conf_rfc rfc = { .mode = pi->mode }; void *ptr = req->data; BT_DBG("sk %p", sk); @@ -2261,11 +2426,13 @@ done: case L2CAP_MODE_ERTM: rfc.mode = L2CAP_MODE_ERTM; - rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; - rfc.max_transmit = max_transmit; + rfc.txwin_size = pi->tx_win; + rfc.max_transmit = pi->max_tx; rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -2287,6 +2454,8 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -2415,10 +2584,15 @@ done: case L2CAP_MODE_ERTM: pi->remote_tx_win = rfc.txwin_size; pi->remote_max_tx = rfc.max_transmit; - pi->max_pdu_size = rfc.max_pdu_size; + if (rfc.max_pdu_size > pi->conn->mtu - 10) + rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); - rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; - rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; + pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); + + rfc.retrans_timeout = + le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); + rfc.monitor_timeout = + le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); pi->conf_state |= L2CAP_CONF_MODE_DONE; @@ -2428,8 +2602,10 @@ done: break; case L2CAP_MODE_STREAMING: - pi->remote_tx_win = rfc.txwin_size; - pi->max_pdu_size = rfc.max_pdu_size; + if (rfc.max_pdu_size > pi->conn->mtu - 10) + rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); + + pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); pi->conf_state |= L2CAP_CONF_MODE_DONE; @@ -2506,13 +2682,12 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, switch (rfc.mode) { case L2CAP_MODE_ERTM: pi->remote_tx_win = rfc.txwin_size; - pi->retrans_timeout = rfc.retrans_timeout; - pi->monitor_timeout = rfc.monitor_timeout; - pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); + pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + pi->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); - break; + pi->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -2536,6 +2711,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla return ptr - data; } +static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int type, olen; + unsigned long val; + struct l2cap_conf_rfc rfc; + + BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); + + if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) + return; + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); + + switch (type) { + case L2CAP_CONF_RFC: + if (olen == sizeof(rfc)) + memcpy(&rfc, (void *)val, olen); + goto done; + } + } + +done: + switch (rfc.mode) { + case L2CAP_MODE_ERTM: + pi->remote_tx_win = rfc.txwin_size; + pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + pi->mps = le16_to_cpu(rfc.max_pdu_size); + break; + case L2CAP_MODE_STREAMING: + pi->mps = le16_to_cpu(rfc.max_pdu_size); + } +} + static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) { struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; @@ -2815,6 +3026,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; struct sock *sk; + int len = cmd->len - sizeof(*rsp); scid = __le16_to_cpu(rsp->scid); flags = __le16_to_cpu(rsp->flags); @@ -2829,11 +3041,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr switch (result) { case L2CAP_CONF_SUCCESS: + l2cap_conf_rfc_get(sk, rsp->data, len); break; case L2CAP_CONF_UNACCEPT: if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { - int len = cmd->len - sizeof(*rsp); char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { @@ -2917,8 +3129,10 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { skb_queue_purge(SREJ_QUEUE(sk)); + skb_queue_purge(BUSY_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&l2cap_pi(sk)->ack_timer); } l2cap_chan_del(sk, ECONNRESET); @@ -2947,8 +3161,10 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { skb_queue_purge(SREJ_QUEUE(sk)); + skb_queue_purge(BUSY_QUEUE(sk)); del_timer(&l2cap_pi(sk)->retrans_timer); del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&l2cap_pi(sk)->ack_timer); } l2cap_chan_del(sk, 0); @@ -3143,7 +3359,40 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) return 0; } -static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) +static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u16 control = 0; + + pi->frames_sent = 0; + pi->conn_state |= L2CAP_CONN_SEND_FBIT; + + control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL; + l2cap_send_sframe(pi, control); + pi->conn_state |= L2CAP_CONN_RNR_SENT; + pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + } + + if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) + __mod_retrans_timer(); + + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + + spin_lock_bh(&pi->send_lock); + l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); + + if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && + pi->frames_sent == 0) { + control |= L2CAP_SUPER_RCV_READY; + l2cap_send_sframe(pi, control); + } +} + +static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) { struct sk_buff *next_skb; @@ -3153,29 +3402,256 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ next_skb = skb_peek(SREJ_QUEUE(sk)); if (!next_skb) { __skb_queue_tail(SREJ_QUEUE(sk), skb); - return; + return 0; } do { + if (bt_cb(next_skb)->tx_seq == tx_seq) + return -EINVAL; + if (bt_cb(next_skb)->tx_seq > tx_seq) { __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); - return; + return 0; } if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) break; - } while((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); + } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); __skb_queue_tail(SREJ_QUEUE(sk), skb); + + return 0; +} + +static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sk_buff *_skb; + int err; + + switch (control & L2CAP_CTRL_SAR) { + case L2CAP_SDU_UNSEGMENTED: + if (pi->conn_state & L2CAP_CONN_SAR_SDU) + goto drop; + + err = sock_queue_rcv_skb(sk, skb); + if (!err) + return err; + + break; + + case L2CAP_SDU_START: + if (pi->conn_state & L2CAP_CONN_SAR_SDU) + goto drop; + + pi->sdu_len = get_unaligned_le16(skb->data); + + if (pi->sdu_len > pi->imtu) + goto disconnect; + + pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); + if (!pi->sdu) + return -ENOMEM; + + /* pull sdu_len bytes only after alloc, because of Local Busy + * condition we have to be sure that this will be executed + * only once, i.e., when alloc does not fail */ + skb_pull(skb, 2); + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + + pi->conn_state |= L2CAP_CONN_SAR_SDU; + pi->partial_sdu_len = skb->len; + break; + + case L2CAP_SDU_CONTINUE: + if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + goto disconnect; + + if (!pi->sdu) + goto disconnect; + + pi->partial_sdu_len += skb->len; + if (pi->partial_sdu_len > pi->sdu_len) + goto drop; + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + + break; + + case L2CAP_SDU_END: + if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + goto disconnect; + + if (!pi->sdu) + goto disconnect; + + if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { + pi->partial_sdu_len += skb->len; + + if (pi->partial_sdu_len > pi->imtu) + goto drop; + + if (pi->partial_sdu_len != pi->sdu_len) + goto drop; + + memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); + } + + _skb = skb_clone(pi->sdu, GFP_ATOMIC); + if (!_skb) { + pi->conn_state |= L2CAP_CONN_SAR_RETRY; + return -ENOMEM; + } + + err = sock_queue_rcv_skb(sk, _skb); + if (err < 0) { + kfree_skb(_skb); + pi->conn_state |= L2CAP_CONN_SAR_RETRY; + return err; + } + + pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; + pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + + kfree_skb(pi->sdu); + break; + } + + kfree_skb(skb); + return 0; + +drop: + kfree_skb(pi->sdu); + pi->sdu = NULL; + +disconnect: + l2cap_send_disconn_req(pi->conn, sk); + kfree_skb(skb); + return 0; } -static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static void l2cap_busy_work(struct work_struct *work) +{ + DECLARE_WAITQUEUE(wait, current); + struct l2cap_pinfo *pi = + container_of(work, struct l2cap_pinfo, busy_work); + struct sock *sk = (struct sock *)pi; + int n_tries = 0, timeo = HZ/5, err; + struct sk_buff *skb; + u16 control; + + lock_sock(sk); + + add_wait_queue(sk_sleep(sk), &wait); + while ((skb = skb_peek(BUSY_QUEUE(sk)))) { + set_current_state(TASK_INTERRUPTIBLE); + + if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { + err = -EBUSY; + l2cap_send_disconn_req(pi->conn, sk); + goto done; + } + + if (!timeo) + timeo = HZ/5; + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + goto done; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + err = sock_error(sk); + if (err) + goto done; + + while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { + control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; + err = l2cap_ertm_reassembly_sdu(sk, skb, control); + if (err < 0) { + skb_queue_head(BUSY_QUEUE(sk), skb); + break; + } + + pi->buffer_seq = (pi->buffer_seq + 1) % 64; + } + + if (!skb) + break; + } + + if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) + goto done; + + control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; + l2cap_send_sframe(pi, control); + l2cap_pi(sk)->retry_count = 1; + + del_timer(&pi->retrans_timer); + __mod_monitor_timer(); + + l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + +done: + pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; + pi->conn_state &= ~L2CAP_CONN_RNR_SENT; + + set_current_state(TASK_RUNNING); + remove_wait_queue(sk_sleep(sk), &wait); + + release_sock(sk); +} + +static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int sctrl, err; + + if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; + __skb_queue_tail(BUSY_QUEUE(sk), skb); + return -EBUSY; + } + + err = l2cap_ertm_reassembly_sdu(sk, skb, control); + if (err >= 0) { + pi->buffer_seq = (pi->buffer_seq + 1) % 64; + return err; + } + + /* Busy Condition */ + pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; + bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; + __skb_queue_tail(BUSY_QUEUE(sk), skb); + + sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + sctrl |= L2CAP_SUPER_RCV_NOT_READY; + l2cap_send_sframe(pi, sctrl); + + pi->conn_state |= L2CAP_CONN_RNR_SENT; + + queue_work(_busy_wq, &pi->busy_work); + + return err; +} + +static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) { struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *_skb; int err = -EINVAL; + /* + * TODO: We have to notify the userland if some data is lost with the + * Streaming Mode. + */ + switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: if (pi->conn_state & L2CAP_CONN_SAR_SDU) { @@ -3198,6 +3674,11 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co pi->sdu_len = get_unaligned_le16(skb->data); skb_pull(skb, 2); + if (pi->sdu_len > pi->imtu) { + err = -EMSGSIZE; + break; + } + pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); if (!pi->sdu) { err = -ENOMEM; @@ -3234,15 +3715,19 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co pi->conn_state &= ~L2CAP_CONN_SAR_SDU; pi->partial_sdu_len += skb->len; + if (pi->partial_sdu_len > pi->imtu) + goto drop; + if (pi->partial_sdu_len == pi->sdu_len) { _skb = skb_clone(pi->sdu, GFP_ATOMIC); err = sock_queue_rcv_skb(sk, _skb); if (err < 0) kfree_skb(_skb); } - kfree_skb(pi->sdu); err = 0; +drop: + kfree_skb(pi->sdu); break; } @@ -3253,15 +3738,15 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) { struct sk_buff *skb; - u16 control = 0; + u16 control; - while((skb = skb_peek(SREJ_QUEUE(sk)))) { + while ((skb = skb_peek(SREJ_QUEUE(sk)))) { if (bt_cb(skb)->tx_seq != tx_seq) break; skb = skb_dequeue(SREJ_QUEUE(sk)); - control |= bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - l2cap_sar_reassembly_sdu(sk, skb, control); + control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; + l2cap_ertm_reassembly_sdu(sk, skb, control); l2cap_pi(sk)->buffer_seq_srej = (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; tx_seq++; @@ -3274,7 +3759,7 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) struct srej_list *l, *tmp; u16 control; - list_for_each_entry_safe(l,tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { list_del(&l->list); kfree(l); @@ -3297,10 +3782,6 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) while (tx_seq != pi->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { - control |= L2CAP_CTRL_POLL; - pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; - } l2cap_send_sframe(pi, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); @@ -3315,18 +3796,40 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str struct l2cap_pinfo *pi = l2cap_pi(sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); - u16 tx_control = 0; u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; + u8 tx_seq_offset, expected_tx_seq_offset; + int num_to_ack = (pi->tx_win/6) + 1; int err = 0; BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + if (L2CAP_CTRL_FINAL & rx_control && + l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + del_timer(&pi->monitor_timer); + if (pi->unacked_frames > 0) + __mod_retrans_timer(); + pi->conn_state &= ~L2CAP_CONN_WAIT_F; + } + pi->expected_ack_seq = req_seq; l2cap_drop_acked_frames(sk); if (tx_seq == pi->expected_tx_seq) goto expected; + tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + if (tx_seq_offset < 0) + tx_seq_offset += 64; + + /* invalid tx_seq */ + if (tx_seq_offset >= pi->tx_win) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + + if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) + goto drop; + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; @@ -3342,10 +3845,14 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str if (list_empty(SREJ_LIST(sk))) { pi->buffer_seq = pi->buffer_seq_srej; pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; + l2cap_send_ack(pi); } } else { struct srej_list *l; - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + + /* duplicated tx_seq */ + if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) + goto drop; list_for_each_entry(l, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { @@ -3356,12 +3863,22 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str l2cap_send_srejframe(sk, tx_seq); } } else { + expected_tx_seq_offset = + (pi->expected_tx_seq - pi->buffer_seq) % 64; + if (expected_tx_seq_offset < 0) + expected_tx_seq_offset += 64; + + /* duplicated tx_seq */ + if (tx_seq_offset < expected_tx_seq_offset) + goto drop; + pi->conn_state |= L2CAP_CONN_SREJ_SENT; INIT_LIST_HEAD(SREJ_LIST(sk)); pi->buffer_seq_srej = pi->buffer_seq; __skb_queue_head_init(SREJ_QUEUE(sk)); + __skb_queue_head_init(BUSY_QUEUE(sk)); l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); pi->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3374,153 +3891,189 @@ expected: pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + bt_cb(skb)->tx_seq = tx_seq; + bt_cb(skb)->sar = sar; + __skb_queue_tail(SREJ_QUEUE(sk), skb); return 0; } if (rx_control & L2CAP_CTRL_FINAL) { if (pi->conn_state & L2CAP_CONN_REJ_ACT) pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } + else + l2cap_retransmit_frames(sk); } - pi->buffer_seq = (pi->buffer_seq + 1) % 64; - - err = l2cap_sar_reassembly_sdu(sk, skb, rx_control); + err = l2cap_push_rx_skb(sk, skb, rx_control); if (err < 0) - return err; + return 0; + + __mod_ack_timer(); + + pi->num_acked = (pi->num_acked + 1) % num_to_ack; + if (pi->num_acked == num_to_ack - 1) + l2cap_send_ack(pi); - pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; - if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) { - tx_control |= L2CAP_SUPER_RCV_READY; - tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, tx_control); - } + return 0; + +drop: + kfree_skb(skb); return 0; } -static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) { struct l2cap_pinfo *pi = l2cap_pi(sk); - u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + pi->expected_ack_seq = __get_reqseq(rx_control); + l2cap_drop_acked_frames(sk); - switch (rx_control & L2CAP_CTRL_SUPERVISE) { - case L2CAP_SUPER_RCV_READY: - if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - control |= L2CAP_SUPER_RCV_READY | - (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT); - l2cap_send_sframe(l2cap_pi(sk), control); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (rx_control & L2CAP_CTRL_POLL) { + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->unacked_frames > 0)) + __mod_retrans_timer(); - } else if (rx_control & L2CAP_CTRL_FINAL) { pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } - - if (!(pi->conn_state & L2CAP_CONN_WAIT_F)) - break; + l2cap_send_srejtail(sk); + } else { + l2cap_send_i_or_rr_or_rnr(sk); + } - pi->conn_state &= ~L2CAP_CONN_WAIT_F; - del_timer(&pi->monitor_timer); + } else if (rx_control & L2CAP_CTRL_FINAL) { + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->unacked_frames > 0) - __mod_retrans_timer(); - } else { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + if (pi->conn_state & L2CAP_CONN_REJ_ACT) + pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + else + l2cap_retransmit_frames(sk); - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->unacked_frames > 0)) - __mod_retrans_timer(); + } else { + if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->unacked_frames > 0)) + __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + l2cap_send_ack(pi); + } else { + spin_lock_bh(&pi->send_lock); l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); } - break; + } +} - case L2CAP_SUPER_REJECT: - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); + + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); - pi->expected_ack_seq = __get_reqseq(rx_control); + if (rx_control & L2CAP_CTRL_FINAL) { + if (pi->conn_state & L2CAP_CONN_REJ_ACT) + pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + else + l2cap_retransmit_frames(sk); + } else { + l2cap_retransmit_frames(sk); + + if (pi->conn_state & L2CAP_CONN_WAIT_F) + pi->conn_state |= L2CAP_CONN_REJ_ACT; + } +} +static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); + + pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + + if (rx_control & L2CAP_CTRL_POLL) { + pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); + l2cap_retransmit_one_frame(sk, tx_seq); - if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; - else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); - } - } else { - sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; - l2cap_ertm_send(sk); + spin_lock_bh(&pi->send_lock); + l2cap_ertm_send(sk); + spin_unlock_bh(&pi->send_lock); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_REJ_ACT; - } + if (pi->conn_state & L2CAP_CONN_WAIT_F) { + pi->srej_save_reqseq = tx_seq; + pi->conn_state |= L2CAP_CONN_SREJ_ACT; + } + } else if (rx_control & L2CAP_CTRL_FINAL) { + if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && + pi->srej_save_reqseq == tx_seq) + pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; + else + l2cap_retransmit_one_frame(sk, tx_seq); + } else { + l2cap_retransmit_one_frame(sk, tx_seq); + if (pi->conn_state & L2CAP_CONN_WAIT_F) { + pi->srej_save_reqseq = tx_seq; + pi->conn_state |= L2CAP_CONN_SREJ_ACT; } + } +} +static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + u8 tx_seq = __get_reqseq(rx_control); + + pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; + pi->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(sk); + + if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { + del_timer(&pi->retrans_timer); + if (rx_control & L2CAP_CTRL_POLL) + l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); + return; + } + + if (rx_control & L2CAP_CTRL_POLL) + l2cap_send_srejtail(sk); + else + l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); +} + +static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +{ + BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + + if (L2CAP_CTRL_FINAL & rx_control && + l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + del_timer(&l2cap_pi(sk)->monitor_timer); + if (l2cap_pi(sk)->unacked_frames > 0) + __mod_retrans_timer(); + l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; + } + + switch (rx_control & L2CAP_CTRL_SUPERVISE) { + case L2CAP_SUPER_RCV_READY: + l2cap_data_channel_rrframe(sk, rx_control); break; - case L2CAP_SUPER_SELECT_REJECT: - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + case L2CAP_SUPER_REJECT: + l2cap_data_channel_rejframe(sk, rx_control); + break; - if (rx_control & L2CAP_CTRL_POLL) { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - l2cap_retransmit_frame(sk, tx_seq); - l2cap_ertm_send(sk); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; - } - } else if (rx_control & L2CAP_CTRL_FINAL) { - if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && - pi->srej_save_reqseq == tx_seq) - pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; - else - l2cap_retransmit_frame(sk, tx_seq); - } - else { - l2cap_retransmit_frame(sk, tx_seq); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { - pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; - } - } + case L2CAP_SUPER_SELECT_REJECT: + l2cap_data_channel_srejframe(sk, rx_control); break; case L2CAP_SUPER_RCV_NOT_READY: - pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); - - del_timer(&l2cap_pi(sk)->retrans_timer); - if (rx_control & L2CAP_CTRL_POLL) { - u16 control = L2CAP_CTRL_FINAL; - l2cap_send_rr_or_rnr(l2cap_pi(sk), control); - } + l2cap_data_channel_rnrframe(sk, rx_control); break; } + kfree_skb(skb); return 0; } @@ -3529,7 +4082,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk struct sock *sk; struct l2cap_pinfo *pi; u16 control, len; - u8 tx_seq; + u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset; sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); if (!sk) { @@ -3574,16 +4127,45 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk * Receiver will miss it and start proper recovery * procedures and ask retransmission. */ - if (len > L2CAP_DEFAULT_MAX_PDU_SIZE) + if (len > pi->mps) { + l2cap_send_disconn_req(pi->conn, sk); goto drop; + } if (l2cap_check_fcs(pi, skb)) goto drop; - if (__is_iframe(control)) + req_seq = __get_reqseq(control); + req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; + if (req_seq_offset < 0) + req_seq_offset += 64; + + next_tx_seq_offset = + (pi->next_tx_seq - pi->expected_ack_seq) % 64; + if (next_tx_seq_offset < 0) + next_tx_seq_offset += 64; + + /* check for invalid req-seq */ + if (req_seq_offset > next_tx_seq_offset) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + + if (__is_iframe(control)) { + if (len < 4) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + l2cap_data_channel_iframe(sk, control, skb); - else + } else { + if (len != 0) { + l2cap_send_disconn_req(pi->conn, sk); + goto drop; + } + l2cap_data_channel_sframe(sk, control, skb); + } goto done; @@ -3598,7 +4180,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (pi->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control)) + if (len > pi->mps || len < 4 || __is_sframe(control)) goto drop; if (l2cap_check_fcs(pi, skb)) @@ -3609,14 +4191,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (pi->expected_tx_seq == tx_seq) pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; else - pi->expected_tx_seq = tx_seq + 1; + pi->expected_tx_seq = (tx_seq + 1) % 64; - l2cap_sar_reassembly_sdu(sk, skb, control); + l2cap_streaming_reassembly_sdu(sk, skb, control); goto done; default: - BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode); + BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode); break; } @@ -3772,7 +4354,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) { - if (sk->sk_type != SOCK_SEQPACKET) + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) return; if (encrypt == 0x00) { @@ -4030,6 +4612,10 @@ static int __init l2cap_init(void) if (err < 0) return err; + _busy_wq = create_singlethread_workqueue("l2cap"); + if (!_busy_wq) + goto error; + err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); if (err < 0) { BT_ERR("L2CAP socket registration failed"); @@ -4064,6 +4650,9 @@ static void __exit l2cap_exit(void) { debugfs_remove(l2cap_debugfs); + flush_workqueue(_busy_wq); + destroy_workqueue(_busy_wq); + if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); @@ -4091,6 +4680,9 @@ MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode"); module_param(max_transmit, uint, 0644); MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)"); +module_param(tx_window, uint, 0644); +MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)"); + MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); MODULE_VERSION(VERSION); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index b406d3e..4767928a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -165,11 +165,11 @@ static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct so int err = 0; sco_conn_lock(conn); - if (conn->sk) { + if (conn->sk) err = -EBUSY; - } else { + else __sco_chan_add(conn, sk, parent); - } + sco_conn_unlock(conn); return err; } @@ -241,22 +241,19 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) BT_DBG("sk %p len %d", sk, len); count = min_t(unsigned int, conn->mtu, len); - if (!(skb = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) + skb = bt_skb_send_alloc(sk, count, + msg->msg_flags & MSG_DONTWAIT, &err); + if (!skb) return err; if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { - err = -EFAULT; - goto fail; + kfree_skb(skb); + return -EFAULT; } - if ((err = hci_send_sco(conn->hcon, skb)) < 0) - return err; + hci_send_sco(conn->hcon, skb); return count; - -fail: - kfree_skb(skb); - return err; } static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) @@ -626,7 +623,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - int err = 0; + int err; BT_DBG("sock %p, sk %p", sock, sk); @@ -851,7 +848,8 @@ static void sco_conn_ready(struct sco_conn *conn) bh_lock_sock(parent); - sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC); + sk = sco_sock_alloc(sock_net(parent), NULL, + BTPROTO_SCO, GFP_ATOMIC); if (!sk) { bh_unlock_sock(parent); goto done; |