[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <e16b52130373edb985e68963e33f61fb092c1051.1542119058.git.igor.russkikh@aquantia.com>
Date: Tue, 13 Nov 2018 14:44:49 +0000
From: Igor Russkikh <Igor.Russkikh@...antia.com>
To: "David S . Miller" <davem@...emloft.net>
CC: "linux-usb@...r.kernel.org" <linux-usb@...r.kernel.org>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
Dmitry Bezrukov <Dmitry.Bezrukov@...antia.com>,
Igor Russkikh <Igor.Russkikh@...antia.com>
Subject: [PATCH v2 net-next 08/21] net: usb: aqc111: Implement TX data path
From: Dmitry Bezrukov <dmitry.bezrukov@...antia.com>
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@...antia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@...antia.com>
---
drivers/net/usb/aqc111.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/usb/aqc111.h | 8 ++++++
2 files changed, 80 insertions(+)
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 15b86dee7bca..b630a8342ef2 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -302,6 +302,9 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
static const struct net_device_ops aqc111_netdev_ops = {
.ndo_open = usbnet_open,
.ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_get_stats64 = usbnet_get_stats64,
.ndo_set_mac_address = aqc111_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@ -372,8 +375,19 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
goto out;
ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr);
+
+ /* Set TX needed headroom & tailroom */
+ dev->net->needed_headroom += sizeof(u64);
+ dev->net->needed_tailroom += sizeof(u64);
+
dev->net->netdev_ops = &aqc111_netdev_ops;
+ if (usb_device_no_sg_constraint(dev->udev))
+ dev->can_dma_sg = 1;
+
+ dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+ dev->net->features |= AQ_SUPPORT_FEATURE;
+
aqc111_read_fw_version(dev, aqc111_data);
aqc111_data->autoneg = AUTONEG_ENABLE;
aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
@@ -603,6 +617,12 @@ static int aqc111_reset(struct usbnet *dev)
u16 reg16 = 0;
u8 reg8 = 0;
+ if (usb_device_no_sg_constraint(dev->udev))
+ dev->can_dma_sg = 1;
+
+ dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+ dev->net->features |= AQ_SUPPORT_FEATURE;
+
/* Power up ethernet PHY */
aqc111_data->phy_cfg = AQ_PHY_POWER_EN;
if (aqc111_data->dpa) {
@@ -679,6 +699,55 @@ static int aqc111_stop(struct usbnet *dev)
return 0;
}
+static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ int frame_size = dev->maxpacket;
+ struct sk_buff *new_skb = NULL;
+ int padding_size = 0;
+ int headroom = 0;
+ int tailroom = 0;
+ u64 tx_desc = 0;
+
+ /*Length of actual data*/
+ tx_desc |= skb->len & AQ_TX_DESC_LEN_MASK;
+
+ headroom = (skb->len + sizeof(tx_desc)) % 8;
+ if (headroom != 0)
+ padding_size = 8 - headroom;
+
+ if (((skb->len + sizeof(tx_desc) + padding_size) % frame_size) == 0) {
+ padding_size += 8;
+ tx_desc |= AQ_TX_DESC_DROP_PADD;
+ }
+
+ if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
+ skb_linearize(skb))
+ return NULL;
+
+ headroom = skb_headroom(skb);
+ tailroom = skb_tailroom(skb);
+
+ if (!(headroom >= sizeof(tx_desc) && tailroom >= padding_size)) {
+ new_skb = skb_copy_expand(skb, sizeof(tx_desc),
+ padding_size, flags);
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ if (!skb)
+ return NULL;
+ }
+ if (padding_size != 0)
+ skb_put(skb, padding_size);
+ /* Copy TX header */
+ skb_push(skb, sizeof(tx_desc));
+ cpu_to_le64s(&tx_desc);
+ skb_copy_to_linear_data(skb, &tx_desc, sizeof(tx_desc));
+
+ usbnet_set_skb_tx_stats(skb, 1, 0);
+
+ return skb;
+}
+
static const struct driver_info aqc111_info = {
.description = "Aquantia AQtion USB to 5GbE Controller",
.bind = aqc111_bind,
@@ -687,6 +756,9 @@ static const struct driver_info aqc111_info = {
.link_reset = aqc111_link_reset,
.reset = aqc111_reset,
.stop = aqc111_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX |
+ FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+ .tx_fixup = aqc111_tx_fixup,
};
#define AQC111_USB_ETH_DEV(vid, pid, table) \
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index a6359ff759cd..a3d9d7dde240 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -60,6 +60,10 @@
#define AQ_USB_PHY_SET_TIMEOUT 10000
#define AQ_USB_SET_TIMEOUT 4000
+/* Feature. ********************************************/
+#define AQ_SUPPORT_FEATURE (NETIF_F_SG)
+#define AQ_SUPPORT_HW_FEATURE (NETIF_F_SG)
+
/* SFR Reg. ********************************************/
#define SFR_GENERAL_STATUS 0x03
@@ -192,6 +196,10 @@ struct aqc111_data {
#define AQ_INT_SPEED_1G 0x0011
#define AQ_INT_SPEED_100M 0x0013
+/* TX Descriptor */
+#define AQ_TX_DESC_LEN_MASK 0x1FFFFF
+#define AQ_TX_DESC_DROP_PADD BIT(28)
+
static struct {
unsigned char ctrl;
unsigned char timer_l;
--
2.7.4
Powered by blists - more mailing lists