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

Commit 361459cd authored by Dmitry Bezrukov's avatar Dmitry Bezrukov Committed by David S. Miller
Browse files

net: usb: aqc111: Implement RX data path

parent 4a3576d2
Loading
Loading
Loading
Loading
+102 −0
Original line number Diff line number Diff line
@@ -294,6 +294,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)

	ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr);

	/* Set Rx urb size */
	dev->rx_urb_size = URB_SIZE;

	/* Set TX needed headroom & tailroom */
	dev->net->needed_headroom += sizeof(u64);
	dev->net->needed_tailroom += sizeof(u64);
@@ -519,6 +522,8 @@ static int aqc111_reset(struct usbnet *dev)
	struct aqc111_data *aqc111_data = dev->driver_priv;
	u8 reg8 = 0;

	dev->rx_urb_size = URB_SIZE;

	if (usb_device_no_sg_constraint(dev->udev))
		dev->can_dma_sg = 1;

@@ -578,6 +583,102 @@ static int aqc111_stop(struct usbnet *dev)
	return 0;
}

static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
	struct sk_buff *new_skb = NULL;
	u32 pkt_total_offset = 0;
	u64 *pkt_desc_ptr = NULL;
	u32 start_of_descs = 0;
	u32 desc_offset = 0; /*RX Header Offset*/
	u16 pkt_count = 0;
	u64 desc_hdr = 0;
	u32 skb_len = 0;

	if (!skb)
		goto err;

	if (skb->len == 0)
		goto err;

	skb_len = skb->len;
	/* RX Descriptor Header */
	skb_trim(skb, skb->len - sizeof(desc_hdr));
	desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb));

	/* Check these packets */
	desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >>
		      AQ_RX_DH_DESC_OFFSET_SHIFT;
	pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK;
	start_of_descs = skb_len - ((pkt_count + 1) *  sizeof(desc_hdr));

	/* self check descs position */
	if (start_of_descs != desc_offset)
		goto err;

	/* self check desc_offset from header*/
	if (desc_offset >= skb_len)
		goto err;

	if (pkt_count == 0)
		goto err;

	/* Get the first RX packet descriptor */
	pkt_desc_ptr = (u64 *)(skb->data + desc_offset);

	while (pkt_count--) {
		u64 pkt_desc = le64_to_cpup(pkt_desc_ptr);
		u32 pkt_len_with_padd = 0;
		u32 pkt_len = 0;

		pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >>
			  AQ_RX_PD_LEN_SHIFT);
		pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8);

		pkt_total_offset += pkt_len_with_padd;
		if (pkt_total_offset > desc_offset ||
		    (pkt_count == 0 && pkt_total_offset != desc_offset)) {
			goto err;
		}

		if (pkt_desc & AQ_RX_PD_DROP ||
		    !(pkt_desc & AQ_RX_PD_RX_OK) ||
		    pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) {
			skb_pull(skb, pkt_len_with_padd);
			/* Next RX Packet Descriptor */
			pkt_desc_ptr++;
			continue;
		}

		/* Clone SKB */
		new_skb = skb_clone(skb, GFP_ATOMIC);

		if (!new_skb)
			goto err;

		new_skb->len = pkt_len;
		skb_pull(new_skb, AQ_RX_HW_PAD);
		skb_set_tail_pointer(new_skb, new_skb->len);

		new_skb->truesize = SKB_TRUESIZE(new_skb->len);

		usbnet_skb_return(dev, new_skb);
		if (pkt_count == 0)
			break;

		skb_pull(skb, pkt_len_with_padd);

		/* Next RX Packet Header */
		pkt_desc_ptr++;

		new_skb = NULL;
	}

	return 1;

err:
	return 0;
}

static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
				       gfp_t flags)
{
@@ -637,6 +738,7 @@ static const struct driver_info aqc111_info = {
	.stop		= aqc111_stop,
	.flags		= FLAG_ETHER | FLAG_FRAMING_AX |
			  FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
	.rx_fixup	= aqc111_rx_fixup,
	.tx_fixup	= aqc111_tx_fixup,
};

+15 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
#ifndef __LINUX_USBNET_AQC111_H
#define __LINUX_USBNET_AQC111_H

#define URB_SIZE	(1024 * 62)

#define AQ_ACCESS_MAC			0x01
#define AQ_FLASH_PARAMETERS		0x20
#define AQ_PHY_POWER			0x31
@@ -157,6 +159,19 @@ struct aqc111_data {
#define AQ_TX_DESC_LEN_MASK	0x1FFFFF
#define AQ_TX_DESC_DROP_PADD	BIT(28)

#define AQ_RX_HW_PAD			0x02

/* RX Packet Descriptor */
#define AQ_RX_PD_RX_OK		BIT(11)
#define AQ_RX_PD_DROP		BIT(31)
#define AQ_RX_PD_LEN_MASK	0x7FFF0000
#define AQ_RX_PD_LEN_SHIFT	0x10

/* RX Descriptor header */
#define AQ_RX_DH_PKT_CNT_MASK		0x1FFF
#define AQ_RX_DH_DESC_OFFSET_MASK	0xFFFFE000
#define AQ_RX_DH_DESC_OFFSET_SHIFT	0x0D

static struct {
	unsigned char ctrl;
	unsigned char timer_l;