RE: [PATCH v5 6/8] thunderbolt: Networking transmit and receive

2016-07-31 Thread Levy, Amir (Jer)
On Sun, Jul 31 2016, 09:45 PM, David Miller wrote:
> From: "Levy, Amir (Jer)" 
> Date: Sun, 31 Jul 2016 10:15:52 +
> 
> > The network stack thinks it is Ethernet, it might not accept Runt
> > frames, so the driver pads the frame in receive.
> 
> The network stack doesn't care about this at all.  It's wasted effort on your
> part.

Great, I'll remove this code.


Re: [PATCH v5 6/8] thunderbolt: Networking transmit and receive

2016-07-31 Thread David Miller
From: "Levy, Amir (Jer)" 
Date: Sun, 31 Jul 2016 10:15:52 +

> The network stack thinks it is Ethernet, it might not accept Runt
> frames, so the driver pads the frame in receive.

The network stack doesn't care about this at all.  It's wasted effort
on your part.



RE: [PATCH v5 6/8] thunderbolt: Networking transmit and receive

2016-07-31 Thread Levy, Amir (Jer)
On Sat, Jul 30 2016, 12:07 AM, Stephen Hemminger wrote:
> On Thu, 28 Jul 2016 11:15:19 +0300
> Amir Levy  wrote:
> 
> > +   /* pad short packets */
> > +   if (unlikely(skb->len < ETH_ZLEN)) {
> > +   int pad_len = ETH_ZLEN - skb->len;
> > +
> > +   /* The skb is freed on error */
> > +   if (unlikely(skb_pad(skb, pad_len))) {
> > +   cleaned_count += frame_count;
> > +   continue;
> > +   }
> > +   __skb_put(skb, pad_len);
> > +   }
> 
> Packets should be padded on transmit, not on receive??

This driver emulates an Ethernet adapter on top of Thunderbolt technology.
The Thunderbolt medium hasn't any restriction on minimum frame size and doesn't 
have the Ethernet collision detection limitation.
So moving this code from transmit is actually an optimization - sending the 
minimum on the wire.
The network stack thinks it is Ethernet, it might not accept Runt frames, so 
the driver pads the frame in receive.

Looks like it deserves a comment in the code. Will add it.


Re: [PATCH v5 6/8] thunderbolt: Networking transmit and receive

2016-07-29 Thread Stephen Hemminger
On Thu, 28 Jul 2016 11:15:19 +0300
Amir Levy  wrote:

> + /* pad short packets */
> + if (unlikely(skb->len < ETH_ZLEN)) {
> + int pad_len = ETH_ZLEN - skb->len;
> +
> + /* The skb is freed on error */
> + if (unlikely(skb_pad(skb, pad_len))) {
> + cleaned_count += frame_count;
> + continue;
> + }
> + __skb_put(skb, pad_len);
> + }

Packets should be padded on transmit, not on receive??


[PATCH v5 6/8] thunderbolt: Networking transmit and receive

2016-07-28 Thread Amir Levy
Handling the transmission to second peer and receiving from it.
This includes communication with upper layer, the network stack
and configuration of Thunderbolt(TM) HW.

Signed-off-by: Amir Levy 
---
 drivers/thunderbolt/icm/icm_nhi.c |   15 +
 drivers/thunderbolt/icm/net.c | 1475 +
 2 files changed, 1490 insertions(+)

diff --git a/drivers/thunderbolt/icm/icm_nhi.c 
b/drivers/thunderbolt/icm/icm_nhi.c
index e491b0e..efadf9c 100644
--- a/drivers/thunderbolt/icm/icm_nhi.c
+++ b/drivers/thunderbolt/icm/icm_nhi.c
@@ -1055,6 +1055,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void 
*data)
 {
struct tbt_nhi_ctxt *nhi_ctxt = data;
u32 isr0, isr1, imr0, imr1;
+   int i;
 
/* clear on read */
isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE);
@@ -1077,6 +1078,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void 
*data)
 
spin_unlock(_ctxt->lock);
 
+   for (i = 0; i < nhi_ctxt->num_ports; ++i) {
+   struct net_device *net_dev =
+   nhi_ctxt->net_devices[i].net_dev;
+   if (net_dev) {
+   u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i);
+
+   if (isr0 & REG_RING_INT_RX_PROCESSED(
+   path, nhi_ctxt->num_paths))
+   tbt_net_rx_msi(net_dev);
+   if (isr0 & REG_RING_INT_TX_PROCESSED(path))
+   tbt_net_tx_msi(net_dev);
+   }
+   }
+
if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM,
 nhi_ctxt->num_paths))
schedule_work(_ctxt->icm_msgs_work);
diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c
index 75801b5..6ce7c18 100644
--- a/drivers/thunderbolt/icm/net.c
+++ b/drivers/thunderbolt/icm/net.c
@@ -134,6 +134,17 @@ struct approve_inter_domain_connection_cmd {
 
 };
 
+struct tbt_frame_header {
+   /* size of the data with the frame */
+   __le32 frame_size;
+   /* running index on the frames */
+   __le16 frame_index;
+   /* ID of the frame to match frames to specific packet */
+   __le16 frame_id;
+   /* how many frames assembles a full packet */
+   __le32 frame_count;
+};
+
 enum neg_event {
RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES,
RECEIVE_LOGIN_RESPONSE,
@@ -141,15 +152,81 @@ enum neg_event {
NUM_NEG_EVENTS
 };
 
+enum frame_status {
+   GOOD_FRAME,
+   GOOD_AS_FIRST_FRAME,
+   GOOD_AS_FIRST_MULTICAST_FRAME,
+   FRAME_NOT_READY,
+   FRAME_ERROR,
+};
+
+enum packet_filter {
+   /* all multicast MAC addresses */
+   PACKET_TYPE_ALL_MULTICAST,
+   /* all types of MAC addresses: multicast, unicast and broadcast */
+   PACKET_TYPE_PROMISCUOUS,
+   /* all unicast MAC addresses */
+   PACKET_TYPE_UNICAST_PROMISCUOUS,
+};
+
 enum disconnect_path_stage {
STAGE_1 = BIT(0),
STAGE_2 = BIT(1)
 };
 
+struct tbt_net_stats {
+   u64 tx_packets;
+   u64 tx_bytes;
+   u64 tx_errors;
+   u64 rx_packets;
+   u64 rx_bytes;
+   u64 rx_length_errors;
+   u64 rx_over_errors;
+   u64 rx_crc_errors;
+   u64 rx_missed_errors;
+   u64 multicast;
+};
+
+static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = {
+   "tx_packets",
+   "tx_bytes",
+   "tx_errors",
+   "rx_packets",
+   "rx_bytes",
+   "rx_length_errors",
+   "rx_over_errors",
+   "rx_crc_errors",
+   "rx_missed_errors",
+   "multicast",
+};
+
+struct tbt_buffer {
+   dma_addr_t dma;
+   union {
+   struct tbt_frame_header *hdr;
+   struct page *page;
+   };
+   u32 page_offset;
+};
+
+struct tbt_desc_ring {
+   /* pointer to the descriptor ring memory */
+   struct tbt_buf_desc *desc;
+   /* physical address of the descriptor ring */
+   dma_addr_t dma;
+   /* array of buffer structs */
+   struct tbt_buffer *buffers;
+   /* last descriptor that was associated with a buffer */
+   u16 last_allocated;
+   /* next descriptor to check for DD status bit */
+   u16 next_to_clean;
+};
+
 /**
 *  struct tbt_port - the basic tbt_port structure
 *  @tbt_nhi_ctxt:  context of the nhi controller.
 *  @net_dev:   networking device object.
+*  @napi:  network API
 *  @login_retry_work:  work queue for sending login requests.
 *  @login_response_work:   work queue for sending login responses.
 *  @work_struct logout_work:   work queue for sending logout requests.
@@ -165,6 +242,11 @@ enum disconnect_path_stage {
 *  @login_retry_count: counts number of login retries sent.
 *  @local_depth:   depth of the remote peer in the chain.
 *  @transmit_path: routing parameter for the icm.
+*