diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/net/usb/r8152.c | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/net/usb/r8152.c')
-rw-r--r-- | drivers/net/usb/r8152.c | 114 |
1 files changed, 64 insertions, 50 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 5107372..f3fce41 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -24,7 +24,7 @@ #include <linux/ipv6.h> /* Version Information */ -#define DRIVER_VERSION "v1.02.0 (2013/10/28)" +#define DRIVER_VERSION "v1.01.0 (2013/08/12)" #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" #define MODULENAME "r8152" @@ -307,22 +307,22 @@ enum rtl8152_flags { #define MCU_TYPE_USB 0x0000 struct rx_desc { - __le32 opts1; + u32 opts1; #define RX_LEN_MASK 0x7fff - __le32 opts2; - __le32 opts3; - __le32 opts4; - __le32 opts5; - __le32 opts6; + u32 opts2; + u32 opts3; + u32 opts4; + u32 opts5; + u32 opts6; }; struct tx_desc { - __le32 opts1; + u32 opts1; #define TX_FS (1 << 31) /* First segment of a packet */ #define TX_LS (1 << 30) /* Final segment of a packet */ #define TX_LEN_MASK 0x3ffff - __le32 opts2; + u32 opts2; #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ @@ -365,7 +365,6 @@ struct r8152 { struct mii_if_info mii; int intr_interval; u32 msg_enable; - u32 tx_qlen; u16 ocp_base; u8 *intr_buff; u8 version; @@ -877,7 +876,7 @@ static void write_bulk_callback(struct urb *urb) static void intr_callback(struct urb *urb) { struct r8152 *tp; - __le16 *d; + __u16 *d; int status = urb->status; int res; @@ -1137,14 +1136,14 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb) static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) { - int remain; + u32 remain; u8 *tx_data; tx_data = agg->head; agg->skb_num = agg->skb_len = 0; - remain = rx_buf_sz; + remain = rx_buf_sz - sizeof(struct tx_desc); - while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) { + while (remain >= ETH_ZLEN) { struct tx_desc *tx_desc; struct sk_buff *skb; unsigned int len; @@ -1153,14 +1152,12 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) if (!skb) break; - remain -= sizeof(*tx_desc); len = skb->len; if (remain < len) { skb_queue_head(&tp->tx_queue, skb); break; } - tx_data = tx_agg_align(tx_data); tx_desc = (struct tx_desc *)tx_data; tx_data += sizeof(*tx_desc); @@ -1170,18 +1167,11 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) agg->skb_len += len; dev_kfree_skb_any(skb); - tx_data += len; - remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head); + tx_data = tx_agg_align(tx_data + len); + remain = rx_buf_sz - sizeof(*tx_desc) - + (u32)((void *)tx_data - agg->head); } - netif_tx_lock(tp->netdev); - - if (netif_queue_stopped(tp->netdev) && - skb_queue_len(&tp->tx_queue) < tp->tx_qlen) - netif_wake_queue(tp->netdev); - - netif_tx_unlock(tp->netdev); - usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), agg->head, (int)(tx_data - (u8 *)agg->head), (usb_complete_t)write_bulk_callback, agg); @@ -1198,6 +1188,7 @@ static void rx_bottom(struct r8152 *tp) list_for_each_safe(cursor, next, &tp->rx_done) { struct rx_desc *rx_desc; struct rx_agg *agg; + unsigned pkt_len; int len_used = 0; struct urb *urb; u8 *rx_data; @@ -1213,22 +1204,17 @@ static void rx_bottom(struct r8152 *tp) rx_desc = agg->head; rx_data = agg->head; - len_used += sizeof(struct rx_desc); + pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; + len_used += sizeof(struct rx_desc) + pkt_len; - while (urb->actual_length > len_used) { + while (urb->actual_length >= len_used) { struct net_device *netdev = tp->netdev; struct net_device_stats *stats; - unsigned int pkt_len; struct sk_buff *skb; - pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; if (pkt_len < ETH_ZLEN) break; - len_used += pkt_len; - if (urb->actual_length < len_used) - break; - stats = rtl8152_get_stats(netdev); pkt_len -= 4; /* CRC */ @@ -1248,8 +1234,9 @@ static void rx_bottom(struct r8152 *tp) rx_data = rx_agg_align(rx_data + pkt_len + 4); rx_desc = (struct rx_desc *)rx_data; + pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; len_used = (int)(rx_data - (u8 *)agg->head); - len_used += sizeof(struct rx_desc); + len_used += sizeof(struct rx_desc) + pkt_len; } submit: @@ -1397,17 +1384,53 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct r8152 *tp = netdev_priv(netdev); + struct net_device_stats *stats = rtl8152_get_stats(netdev); + unsigned long flags; + struct tx_agg *agg = NULL; + struct tx_desc *tx_desc; + unsigned int len; + u8 *tx_data; + int res; skb_tx_timestamp(skb); - skb_queue_tail(&tp->tx_queue, skb); + /* If tx_queue is not empty, it means at least one previous packt */ + /* is waiting for sending. Don't send current one before it. */ + if (skb_queue_empty(&tp->tx_queue)) + agg = r8152_get_tx_agg(tp); - if (list_empty(&tp->tx_free) && - skb_queue_len(&tp->tx_queue) > tp->tx_qlen) - netif_stop_queue(netdev); + if (!agg) { + skb_queue_tail(&tp->tx_queue, skb); + return NETDEV_TX_OK; + } - if (!list_empty(&tp->tx_free)) - tasklet_schedule(&tp->tl); + tx_desc = (struct tx_desc *)agg->head; + tx_data = agg->head + sizeof(*tx_desc); + agg->skb_num = agg->skb_len = 0; + + len = skb->len; + r8152_tx_csum(tp, tx_desc, skb); + memcpy(tx_data, skb->data, len); + dev_kfree_skb_any(skb); + agg->skb_num++; + agg->skb_len += len; + usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), + agg->head, len + sizeof(*tx_desc), + (usb_complete_t)write_bulk_callback, agg); + res = usb_submit_urb(agg->urb, GFP_ATOMIC); + if (res) { + /* Can we get/handle EPIPE here? */ + if (res == -ENODEV) { + netif_device_detach(tp->netdev); + } else { + netif_warn(tp, tx_err, netdev, + "failed tx_urb %d\n", res); + stats->tx_dropped++; + spin_lock_irqsave(&tp->tx_lock, flags); + list_add_tail(&agg->list, &tp->tx_free); + spin_unlock_irqrestore(&tp->tx_lock, flags); + } + } return NETDEV_TX_OK; } @@ -1436,14 +1459,6 @@ static void rtl8152_nic_reset(struct r8152 *tp) } } -static void set_tx_qlen(struct r8152 *tp) -{ - struct net_device *netdev = tp->netdev; - - tp->tx_qlen = rx_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN + - sizeof(struct tx_desc)); -} - static inline u8 rtl8152_get_speed(struct r8152 *tp) { return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); @@ -1455,7 +1470,6 @@ static int rtl8152_enable(struct r8152 *tp) int i, ret; u8 speed; - set_tx_qlen(tp); speed = rtl8152_get_speed(tp); if (speed & _10bps) { ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); |