Commit 4f837c3b authored by David S. Miller's avatar David S. Miller

Merge branch 'r8152'

Hayes Wang says:

====================
r8152 bug fixes

For the patch #3, I add netif_tx_lock() before checking the
netif_queue_stopped(). Besides, I add checking the skb queue
length before waking the tx queue.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b4789b8e 500b6d7e
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/ipv6.h> #include <linux/ipv6.h>
/* Version Information */ /* Version Information */
#define DRIVER_VERSION "v1.01.0 (2013/08/12)" #define DRIVER_VERSION "v1.02.0 (2013/10/28)"
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
#define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters"
#define MODULENAME "r8152" #define MODULENAME "r8152"
...@@ -307,22 +307,22 @@ enum rtl8152_flags { ...@@ -307,22 +307,22 @@ enum rtl8152_flags {
#define MCU_TYPE_USB 0x0000 #define MCU_TYPE_USB 0x0000
struct rx_desc { struct rx_desc {
u32 opts1; __le32 opts1;
#define RX_LEN_MASK 0x7fff #define RX_LEN_MASK 0x7fff
u32 opts2; __le32 opts2;
u32 opts3; __le32 opts3;
u32 opts4; __le32 opts4;
u32 opts5; __le32 opts5;
u32 opts6; __le32 opts6;
}; };
struct tx_desc { struct tx_desc {
u32 opts1; __le32 opts1;
#define TX_FS (1 << 31) /* First segment of a packet */ #define TX_FS (1 << 31) /* First segment of a packet */
#define TX_LS (1 << 30) /* Final segment of a packet */ #define TX_LS (1 << 30) /* Final segment of a packet */
#define TX_LEN_MASK 0x3ffff #define TX_LEN_MASK 0x3ffff
u32 opts2; __le32 opts2;
#define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */
#define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */
#define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */
...@@ -365,6 +365,7 @@ struct r8152 { ...@@ -365,6 +365,7 @@ struct r8152 {
struct mii_if_info mii; struct mii_if_info mii;
int intr_interval; int intr_interval;
u32 msg_enable; u32 msg_enable;
u32 tx_qlen;
u16 ocp_base; u16 ocp_base;
u8 *intr_buff; u8 *intr_buff;
u8 version; u8 version;
...@@ -876,7 +877,7 @@ static void write_bulk_callback(struct urb *urb) ...@@ -876,7 +877,7 @@ static void write_bulk_callback(struct urb *urb)
static void intr_callback(struct urb *urb) static void intr_callback(struct urb *urb)
{ {
struct r8152 *tp; struct r8152 *tp;
__u16 *d; __le16 *d;
int status = urb->status; int status = urb->status;
int res; int res;
...@@ -1136,14 +1137,14 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb) ...@@ -1136,14 +1137,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) static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
{ {
u32 remain; int remain;
u8 *tx_data; u8 *tx_data;
tx_data = agg->head; tx_data = agg->head;
agg->skb_num = agg->skb_len = 0; agg->skb_num = agg->skb_len = 0;
remain = rx_buf_sz - sizeof(struct tx_desc); remain = rx_buf_sz;
while (remain >= ETH_ZLEN) { while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
struct tx_desc *tx_desc; struct tx_desc *tx_desc;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int len; unsigned int len;
...@@ -1152,12 +1153,14 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) ...@@ -1152,12 +1153,14 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
if (!skb) if (!skb)
break; break;
remain -= sizeof(*tx_desc);
len = skb->len; len = skb->len;
if (remain < len) { if (remain < len) {
skb_queue_head(&tp->tx_queue, skb); skb_queue_head(&tp->tx_queue, skb);
break; break;
} }
tx_data = tx_agg_align(tx_data);
tx_desc = (struct tx_desc *)tx_data; tx_desc = (struct tx_desc *)tx_data;
tx_data += sizeof(*tx_desc); tx_data += sizeof(*tx_desc);
...@@ -1167,11 +1170,18 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) ...@@ -1167,11 +1170,18 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
agg->skb_len += len; agg->skb_len += len;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
tx_data = tx_agg_align(tx_data + len); tx_data += len;
remain = rx_buf_sz - sizeof(*tx_desc) - remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
(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), usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
agg->head, (int)(tx_data - (u8 *)agg->head), agg->head, (int)(tx_data - (u8 *)agg->head),
(usb_complete_t)write_bulk_callback, agg); (usb_complete_t)write_bulk_callback, agg);
...@@ -1188,7 +1198,6 @@ static void rx_bottom(struct r8152 *tp) ...@@ -1188,7 +1198,6 @@ static void rx_bottom(struct r8152 *tp)
list_for_each_safe(cursor, next, &tp->rx_done) { list_for_each_safe(cursor, next, &tp->rx_done) {
struct rx_desc *rx_desc; struct rx_desc *rx_desc;
struct rx_agg *agg; struct rx_agg *agg;
unsigned pkt_len;
int len_used = 0; int len_used = 0;
struct urb *urb; struct urb *urb;
u8 *rx_data; u8 *rx_data;
...@@ -1204,17 +1213,22 @@ static void rx_bottom(struct r8152 *tp) ...@@ -1204,17 +1213,22 @@ static void rx_bottom(struct r8152 *tp)
rx_desc = agg->head; rx_desc = agg->head;
rx_data = agg->head; rx_data = agg->head;
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; len_used += sizeof(struct rx_desc);
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 *netdev = tp->netdev;
struct net_device_stats *stats; struct net_device_stats *stats;
unsigned int pkt_len;
struct sk_buff *skb; struct sk_buff *skb;
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
if (pkt_len < ETH_ZLEN) if (pkt_len < ETH_ZLEN)
break; break;
len_used += pkt_len;
if (urb->actual_length < len_used)
break;
stats = rtl8152_get_stats(netdev); stats = rtl8152_get_stats(netdev);
pkt_len -= 4; /* CRC */ pkt_len -= 4; /* CRC */
...@@ -1234,9 +1248,8 @@ static void rx_bottom(struct r8152 *tp) ...@@ -1234,9 +1248,8 @@ static void rx_bottom(struct r8152 *tp)
rx_data = rx_agg_align(rx_data + pkt_len + 4); rx_data = rx_agg_align(rx_data + pkt_len + 4);
rx_desc = (struct rx_desc *)rx_data; 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 = (int)(rx_data - (u8 *)agg->head);
len_used += sizeof(struct rx_desc) + pkt_len; len_used += sizeof(struct rx_desc);
} }
submit: submit:
...@@ -1384,53 +1397,17 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, ...@@ -1384,53 +1397,17 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
struct net_device *netdev) struct net_device *netdev)
{ {
struct r8152 *tp = netdev_priv(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_tx_timestamp(skb);
/* If tx_queue is not empty, it means at least one previous packt */ skb_queue_tail(&tp->tx_queue, skb);
/* 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 (!agg) {
skb_queue_tail(&tp->tx_queue, skb);
return NETDEV_TX_OK;
}
tx_desc = (struct tx_desc *)agg->head; if (list_empty(&tp->tx_free) &&
tx_data = agg->head + sizeof(*tx_desc); skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
agg->skb_num = agg->skb_len = 0; netif_stop_queue(netdev);
len = skb->len; if (!list_empty(&tp->tx_free))
r8152_tx_csum(tp, tx_desc, skb); tasklet_schedule(&tp->tl);
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; return NETDEV_TX_OK;
} }
...@@ -1459,6 +1436,14 @@ static void rtl8152_nic_reset(struct r8152 *tp) ...@@ -1459,6 +1436,14 @@ 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) static inline u8 rtl8152_get_speed(struct r8152 *tp)
{ {
return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
...@@ -1470,6 +1455,7 @@ static int rtl8152_enable(struct r8152 *tp) ...@@ -1470,6 +1455,7 @@ static int rtl8152_enable(struct r8152 *tp)
int i, ret; int i, ret;
u8 speed; u8 speed;
set_tx_qlen(tp);
speed = rtl8152_get_speed(tp); speed = rtl8152_get_speed(tp);
if (speed & _10bps) { if (speed & _10bps) {
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment