Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a3576d2 authored by Dmitry Bezrukov's avatar Dmitry Bezrukov Committed by David S. Miller
Browse files

net: usb: aqc111: Implement TX data path

parent df2d59a2
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -222,6 +222,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,
};
@@ -290,8 +293,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) ?
@@ -505,6 +519,12 @@ static int aqc111_reset(struct usbnet *dev)
	struct aqc111_data *aqc111_data = dev->driver_priv;
	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;
	aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
@@ -558,6 +578,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;
	u64 *tx_desc_ptr = 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_zero(skb, padding_size);
	/* Copy TX header */
	tx_desc_ptr = skb_push(skb, sizeof(tx_desc));
	*tx_desc_ptr = cpu_to_le64(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,
@@ -566,6 +635,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) \
+8 −0
Original line number Diff line number Diff line
@@ -18,6 +18,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
@@ -149,6 +153,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;