Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-30 Thread Enrico Mioso
Ok, for now I should let go of this - might be it was a little bit too much for 
the time constaints I am having.

But thank you for your effort Oliver.
Anyway, trying to write this new TX engine helped me in understand better 
things and conceive the patch I sent you affecting cdc_ncm.c, which triggers 
some OOPSes but not in a qemu vm, so I can't read them actually.


Any hint on my code is always apreciated, regardless.
Enrico
--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-26 Thread Oliver Neukum
On Thu, 2015-06-25 at 17:19 +0200, Enrico Mioso wrote:
 Hi Oliver! And thank you again.
 
 I like / recommend the usage of open messaging standards: my preferred XMPP ID
 (JID) is: mrk...@jit.si.
 
 On Thu, 25 Jun 2015, Oliver Neukum wrote:
 
  Date: Thu, 25 Jun 2015 15:38:46
  From: Oliver Neukum oneu...@suse.de
  To: Enrico Mioso mrkiko...@gmail.com
  Cc: linux-...@vger.kernel.org, netdev@vger.kernel.org
  Subject: Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack
  
  On Thu, 2015-06-25 at 13:44 +0200, Enrico Mioso wrote:
 
  On Thu, 25 Jun 2015, Oliver Neukum wrote:
 
  Is there any advantage in keeping this in a single function?
 
  I did this choice in the light of the fact I think the tx_fixup function 
  will
  become more complex than it is now, when aggregating frames.
 
  Yes, but that is a reason to split the helpers up not the opposite.
 Right - I understood only now your observation.
 
 the only reason to write the manager that way was that it shouldn't become 
 very 
 complex - it should simply do things to frames, helping out in building valid 
 NCM packages.
 
 
  I answer here your other message to make it more convenient to read: my
  intention for the tx_fixup function would be to:
  - aggregate frames
  - send them out when:
 - a timer expires
 
  How would you do that in tx_fixup()? If a timer is required then you
  need a separate function.
 
 Sure. I meant: I will adapt it in case needed, and expectin the code to 
 become 
 a little bit more convoluted.

You cannot become any more convoluted even if you try.

 OR
 - we have enough data in the aggregate, and cannot add more.
 
  Yes.
 
  You need a third case:
  - the interface is taken down.
 
  But in general the logic for that is already there. So can you explain
  what additional goals you have?
 regarding the timer logic I saw it in cdc_ncm.c, but I should study it in 
 more detail to understand it and implement it here where needed in case.

It is involved. Basically a timer for transmission creates locking
issues. cdc-ncm uses an hrtimer which calls a bottom half which
calls xmit with a NULL skb.

/* if there is a remaining skb, it gets priority */
if (skb != NULL) {
swap(skb, ctx-tx_rem_skb);
swap(sign, ctx-tx_rem_sign);
} else {
ready2send = 1;
}

The else branch here is the timer triggering.
The actual transmission is done in usbnet if cdc_ncm_fill_tx_frame()
returns an skb.

I doubt you can can come up with anything more convoluted
but it simplifies locking.

  Well, no, but it supposes a matched commit phase. Can you guarantee
  that? I was under the oppression that in that phase you want to actually
  give a frame over to the hardware.
 No. When Italk about committing, I think about writing things to out skb.
 another reason why i found confortable writing the code this way was to 
 maintain a kind of statefullness in a more clean way.
 But I understand this is kind of agruable, and I can if needed break it up as 
 desired.
 
 Regarding the commit phase - I am not sure I understand your comment, sorry
 about that.
 However, my intention would be to allow the caller to do calls in sequences 
 like:
 - init frame
 - ncm update
 - ncm update
 - ncm update
 ...
 - ncm update
 - ncm commit
 
 (to work in huawei mode)
 
 OR
 
 - ncm init frame
 - ncm commit
 - ncm update
 - ncm update
 - ncm update
 - ncm update
 - finalize nth
 
 (to work in cdc_ncm.c-mode)..

Sounds like a plan.

 But to prevent usbnet from submittinx RX'd packets, I should be doing 
 something 
 nasty here. And unfortunately don't understand why.

// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
if (info-tx_fixup) {
skb = info-tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) {
/* packet collected; minidriver waiting for more
*/
if (info-flags  FLAG_MULTI_PACKET)
goto not_drop;

So you just return NULL if you are ready to queue more. But you
need the FLAG_MULTI_PACKET flag.

Regards
Oliver


--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-26 Thread Enrico Mioso

Hi Oliver!
I wish sincerely to thank you again for your time and patience.

On Fri, 26 Jun 2015, Oliver Neukum wrote:


Date: Fri, 26 Jun 2015 10:14:02
From: Oliver Neukum oneu...@suse.com
To: Enrico Mioso mrkiko...@gmail.com
Cc: linux-...@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

On Thu, 2015-06-25 at 17:19 +0200, Enrico Mioso wrote:

Hi Oliver! And thank you again.

I like / recommend the usage of open messaging standards: my preferred XMPP ID
(JID) is: mrk...@jit.si.

On Thu, 25 Jun 2015, Oliver Neukum wrote:


Date: Thu, 25 Jun 2015 15:38:46
From: Oliver Neukum oneu...@suse.de
To: Enrico Mioso mrkiko...@gmail.com
Cc: linux-...@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

On Thu, 2015-06-25 at 13:44 +0200, Enrico Mioso wrote:


On Thu, 25 Jun 2015, Oliver Neukum wrote:



Is there any advantage in keeping this in a single function?


I did this choice in the light of the fact I think the tx_fixup function will
become more complex than it is now, when aggregating frames.


Yes, but that is a reason to split the helpers up not the opposite.

Right - I understood only now your observation.

the only reason to write the manager that way was that it shouldn't become very
complex - it should simply do things to frames, helping out in building valid
NCM packages.




I answer here your other message to make it more convenient to read: my
intention for the tx_fixup function would be to:
- aggregate frames
- send them out when:
- a timer expires


How would you do that in tx_fixup()? If a timer is required then you
need a separate function.


Sure. I meant: I will adapt it in case needed, and expectin the code to become
a little bit more convoluted.


You cannot become any more convoluted even if you try.


OR
- we have enough data in the aggregate, and cannot add more.


Yes.

You need a third case:
- the interface is taken down.

But in general the logic for that is already there. So can you explain
what additional goals you have?

regarding the timer logic I saw it in cdc_ncm.c, but I should study it in
more detail to understand it and implement it here where needed in case.


It is involved. Basically a timer for transmission creates locking
issues. cdc-ncm uses an hrtimer which calls a bottom half which
calls xmit with a NULL skb.

   /* if there is a remaining skb, it gets priority */
   if (skb != NULL) {
   swap(skb, ctx-tx_rem_skb);
   swap(sign, ctx-tx_rem_sign);
   } else {
   ready2send = 1;
   }

The else branch here is the timer triggering.
The actual transmission is done in usbnet if cdc_ncm_fill_tx_frame()
returns an skb.

I doubt you can can come up with anything more convoluted
but it simplifies locking.


Well, no, but it supposes a matched commit phase. Can you guarantee
that? I was under the oppression that in that phase you want to actually
give a frame over to the hardware.

No. When Italk about committing, I think about writing things to out skb.
another reason why i found confortable writing the code this way was to
maintain a kind of statefullness in a more clean way.
But I understand this is kind of agruable, and I can if needed break it up as
desired.

Regarding the commit phase - I am not sure I understand your comment, sorry
about that.
However, my intention would be to allow the caller to do calls in sequences
like:
- init frame
- ncm update
- ncm update
- ncm update
...
- ncm update
- ncm commit

(to work in huawei mode)

OR

- ncm init frame
- ncm commit
- ncm update
- ncm update
- ncm update
- ncm update
- finalize nth

(to work in cdc_ncm.c-mode)..


Sounds like a plan.


But to prevent usbnet from submittinx RX'd packets, I should be doing something
nasty here. And unfortunately don't understand why.


   // some devices want funky USB-level framing, for
   // win32 driver (usually) and/or hardware quirks
   if (info-tx_fixup) {
   skb = info-tx_fixup (dev, skb, GFP_ATOMIC);
   if (!skb) {
   /* packet collected; minidriver waiting for more
*/
   if (info-flags  FLAG_MULTI_PACKET)
   goto not_drop;

So you just return NULL if you are ready to queue more. But you
need the FLAG_MULTI_PACKET flag.


Unfortuantely I might have not explained myself better.
I should thank you for this illumination on the timer part: since I know I'll 
need this.
But what's stopping me right now is actually the RX, not the TX part.
Sure, the RX function I am using comes from cdc_ncm.c and works fine: 
unfortunately, usbnet will not call it.
Infact, my dmesg ends up FULL of 
kevent 2 may have been dropped messages.
And looking around I discovered I end up triggering a memory check in usbnet.c, 
at line 475


skb = __netdev_alloc_skb_ip_align(dev-net, size, flags

Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-25 Thread Oliver Neukum
On Thu, 2015-06-25 at 13:44 +0200, Enrico Mioso wrote:

 On Thu, 25 Jun 2015, Oliver Neukum wrote:

  Is there any advantage in keeping this in a single function?
 
 I did this choice in the light of the fact I think the tx_fixup function will 
 become more complex than it is now, when aggregating frames.

Yes, but that is a reason to split the helpers up not the opposite.

 I answer here your other message to make it more convenient to read: my 
 intention for the tx_fixup function would be to:
 - aggregate frames
 - send them out when:
   - a timer expires

How would you do that in tx_fixup()? If a timer is required then you
need a separate function.

   OR
   - we have enough data in the aggregate, and cannot add more.

Yes.

You need a third case:
- the interface is taken down.

But in general the logic for that is already there. So can you explain
what additional goals you have?

 This is something done in cdc_ncm.c for example.
 But here I have a question: by reading the comment in file 
 drivers/net/usb/rndis_host.c at line 572, there seem to be different opinions 
 in this matter.

That is a very old comment written for much slower devices.
rndis_host doesn't get much love nowadays.

 What to do ?
 
  +int
  +huawei_ncm_mgmt(struct usbnet *dev,
  +  struct huawei_cdc_ncm_state *drvstate, struct sk_buff *skb_out, 
  int mode) {
  +  struct usb_cdc_ncm_nth16 *nth16 = (struct usb_cdc_ncm_nth16 
  *)skb_out-data;
  +  struct cdc_ncm_ctx *ctx = drvstate-ctx;
  +  struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
  +  int ret = -EINVAL;
  +  u16 ndplen, index;
  +
  +  switch (mode) {
  +  case NCM_INIT_FRAME:
  +
  +  /* Write a new NTH16 header */
  +  nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, 
  sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
  +  if (!nth16) {
  +  ret = -EINVAL;
  +  goto error;
  +  }
  +
  +  /* NTH16 signature and header length are known a-priori. */
  +  nth16-dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
  +  nth16-wHeaderLength = cpu_to_le16(sizeof(struct 
  usb_cdc_ncm_nth16));
  +
  +  /* TX sequence numbering */
  +  nth16-wSequence = cpu_to_le16(ctx-tx_seq++);
  +
  +  /* Forget about previous SKB NDP */
  +  drvstate-skb_ndp = NULL;
 
  This is probably better done after you know you cannot fail.
 Sure. Thank you.
 
  +
  +  /* Allocate a new NDP */
  +  ndp16 = kzalloc(ctx-max_ndp_size, GFP_NOIO);
 
  Where is this freed?
 The intention wqas to free it in the NCM_COMMIT_NDP case.
 Infact after allocating the pointer, I make a copy of it in the driver state 
 (drvstate) variable, and get back to it later.
 Is this wrong?

Well, no, but it supposes a matched commit phase. Can you guarantee
that? I was under the oppression that in that phase you want to actually
give a frame over to the hardware.



--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-25 Thread Enrico Mioso

Hi Oliver.
Thank you for your patience, and review. I apreciated it very much.

On Thu, 25 Jun 2015, Oliver Neukum wrote:


Date: Thu, 25 Jun 2015 11:49:29
From: Oliver Neukum oneu...@suse.com
To: Enrico Mioso mrkiko...@gmail.com
Cc: linux-...@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

On Tue, 2015-06-23 at 00:32 +0200, Enrico Mioso wrote:

This patch introduces a new NCM tx engine, able to operate in standard-
and huawei-style mode.
In the first case, the NDP is disposed after the initial headers and
before any datagram.

What works:
- is able to communicate with compliant NCM devices:
I tested this with a board running the Linux g_ncm gadget driver.

What doesn't work:
- After some packets I start gettint LOTS of EVENT_RX_MEMORY from usbnet,
which fails to allocate an RX SKB in rx_submit(). Don't understand why,
any suggestion would be very welcome.

The tx_fixup function given here, even if actually working, should be
considered as an example: the NCM manager is used here simulating the
cdc_ncm.c behaviour.

Signed-off-by: Enrico Mioso mrkiko...@gmail.com
---
 drivers/net/usb/huawei_cdc_ncm.c | 187 ++-
 1 file changed, 185 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c
index 735f7da..217802a 100644
--- a/drivers/net/usb/huawei_cdc_ncm.c
+++ b/drivers/net/usb/huawei_cdc_ncm.c
@@ -29,6 +29,35 @@
 #include linux/usb/cdc-wdm.h
 #include linux/usb/cdc_ncm.h

+/* NCM management operations: */
+
+/* NCM_INIT_FRAME: prepare for a new frame.
+ * NTH16 header is written to output SKB, NDP data is reset and last
+ * committed NDP pointer set to NULL.
+ * Now, data may be added to this NCM package.
+ */
+#define NCM_INIT_FRAME 1
+
+/* NCM_UPDATE_NDP: adds data to an NDP structure, hence updating it.
+ * Some checks are performed to be sure data fits in, respecting device and
+ * spec constrains.
+ * Normally the NDP is kept in memory and committed to the SKB only when
+ * requested. However, calling this method after NCM_COMMIT_NDP, causes it to
+ * work directly on the already committed SKB copy. this allows for flexibility
+ * in frame ordering.
+ */
+#define NCM_UPDATE_NDP 2
+
+/* Write NDP: commits NDP to output SKB.
+ * This method should be called only once per frame.
+ */
+#define NCM_COMMIT_NDP 3
+
+/* Finalizes NTH16 header: to be called when working in
+ * update-already-committed mode.
+ */
+#define NCM_FINALIZE_NTH   5
+
 /* Driver data */
 struct huawei_cdc_ncm_state {
struct cdc_ncm_ctx *ctx;
@@ -36,6 +65,16 @@ struct huawei_cdc_ncm_state {
struct usb_driver *subdriver;
struct usb_interface *control;
struct usb_interface *data;
+
+   /* Keeps track of where data starts and ends in SKBs. */
+   int data_start;
+   int data_len;
+
+   /* Last committed NDP for post-commit operations. */
+   struct usb_cdc_ncm_ndp16 *skb_ndp;
+
+   /* Non-committed NDP */
+   struct usb_cdc_ncm_ndp16 *ndp;
 };

 static int huawei_cdc_ncm_manage_power(struct usbnet *usbnet_dev, int on)
@@ -53,6 +92,149 @@ static int huawei_cdc_ncm_manage_power(struct usbnet 
*usbnet_dev, int on)
return 0;
 }

+/* huawei_ncm_mgmt: flexible TX NCM manager.
+ *
+ * Once a non-zero status value is rturned, current frame should be discarded
+ * and operations restarted from scratch.
+ */


Is there any advantage in keeping this in a single function?

I did this choice in the light of the fact I think the tx_fixup function will 
become more complex than it is now, when aggregating frames.
I answer here your other message to make it more convenient to read: my 
intention for the tx_fixup function would be to:

- aggregate frames
- send them out when:
- a timer expires
OR
- we have enough data in the aggregate, and cannot add more.

This is something done in cdc_ncm.c for example.
But here I have a question: by reading the comment in file 
drivers/net/usb/rndis_host.c at line 572, there seem to be different opinions 
in this matter.

What to do ?


+int
+huawei_ncm_mgmt(struct usbnet *dev,
+   struct huawei_cdc_ncm_state *drvstate, struct sk_buff *skb_out, 
int mode) {
+   struct usb_cdc_ncm_nth16 *nth16 = (struct usb_cdc_ncm_nth16 
*)skb_out-data;
+   struct cdc_ncm_ctx *ctx = drvstate-ctx;
+   struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+   int ret = -EINVAL;
+   u16 ndplen, index;
+
+   switch (mode) {
+   case NCM_INIT_FRAME:
+
+   /* Write a new NTH16 header */
+   nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, 
sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+   if (!nth16) {
+   ret = -EINVAL;
+   goto error;
+   }
+
+   /* NTH16 signature and header length

Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-25 Thread Oliver Neukum
On Tue, 2015-06-23 at 00:32 +0200, Enrico Mioso wrote:
 This patch introduces a new NCM tx engine, able to operate in standard-
 and huawei-style mode.
 In the first case, the NDP is disposed after the initial headers and
 before any datagram.
 
 What works:
 - is able to communicate with compliant NCM devices:
   I tested this with a board running the Linux g_ncm gadget driver.
 
 What doesn't work:
 - After some packets I start gettint LOTS of EVENT_RX_MEMORY from usbnet,
   which fails to allocate an RX SKB in rx_submit(). Don't understand why,
   any suggestion would be very welcome.
 
 The tx_fixup function given here, even if actually working, should be
 considered as an example: the NCM manager is used here simulating the
 cdc_ncm.c behaviour.
 
 Signed-off-by: Enrico Mioso mrkiko...@gmail.com
 ---
  drivers/net/usb/huawei_cdc_ncm.c | 187 
 ++-
  1 file changed, 185 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/net/usb/huawei_cdc_ncm.c 
 b/drivers/net/usb/huawei_cdc_ncm.c
 index 735f7da..217802a 100644
 --- a/drivers/net/usb/huawei_cdc_ncm.c
 +++ b/drivers/net/usb/huawei_cdc_ncm.c
 @@ -29,6 +29,35 @@
  #include linux/usb/cdc-wdm.h
  #include linux/usb/cdc_ncm.h
  
 +/* NCM management operations: */
 +
 +/* NCM_INIT_FRAME: prepare for a new frame.
 + * NTH16 header is written to output SKB, NDP data is reset and last
 + * committed NDP pointer set to NULL.
 + * Now, data may be added to this NCM package.
 + */
 +#define NCM_INIT_FRAME   1
 +
 +/* NCM_UPDATE_NDP: adds data to an NDP structure, hence updating it.
 + * Some checks are performed to be sure data fits in, respecting device and
 + * spec constrains.
 + * Normally the NDP is kept in memory and committed to the SKB only when
 + * requested. However, calling this method after NCM_COMMIT_NDP, causes it 
 to
 + * work directly on the already committed SKB copy. this allows for 
 flexibility
 + * in frame ordering.
 + */
 +#define NCM_UPDATE_NDP   2
 +
 +/* Write NDP: commits NDP to output SKB.
 + * This method should be called only once per frame.
 + */
 +#define NCM_COMMIT_NDP   3
 +
 +/* Finalizes NTH16 header: to be called when working in
 + * update-already-committed mode.
 + */
 +#define NCM_FINALIZE_NTH 5
 +
  /* Driver data */
  struct huawei_cdc_ncm_state {
   struct cdc_ncm_ctx *ctx;
 @@ -36,6 +65,16 @@ struct huawei_cdc_ncm_state {
   struct usb_driver *subdriver;
   struct usb_interface *control;
   struct usb_interface *data;
 +
 + /* Keeps track of where data starts and ends in SKBs. */
 + int data_start;
 + int data_len;
 +
 + /* Last committed NDP for post-commit operations. */
 + struct usb_cdc_ncm_ndp16 *skb_ndp;
 +
 + /* Non-committed NDP */
 + struct usb_cdc_ncm_ndp16 *ndp;
  };
  
  static int huawei_cdc_ncm_manage_power(struct usbnet *usbnet_dev, int on)
 @@ -53,6 +92,149 @@ static int huawei_cdc_ncm_manage_power(struct usbnet 
 *usbnet_dev, int on)
   return 0;
  }
  
 +/* huawei_ncm_mgmt: flexible TX NCM manager.
 + *
 + * Once a non-zero status value is rturned, current frame should be discarded
 + * and operations restarted from scratch.
 + */

Is there any advantage in keeping this in a single function?

 +int
 +huawei_ncm_mgmt(struct usbnet *dev,
 + struct huawei_cdc_ncm_state *drvstate, struct sk_buff *skb_out, 
 int mode) {
 + struct usb_cdc_ncm_nth16 *nth16 = (struct usb_cdc_ncm_nth16 
 *)skb_out-data;
 + struct cdc_ncm_ctx *ctx = drvstate-ctx;
 + struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
 + int ret = -EINVAL;
 + u16 ndplen, index;
 +
 + switch (mode) {
 + case NCM_INIT_FRAME:
 +
 + /* Write a new NTH16 header */
 + nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, 
 sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
 + if (!nth16) {
 + ret = -EINVAL;
 + goto error;
 + }
 +
 + /* NTH16 signature and header length are known a-priori. */
 + nth16-dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
 + nth16-wHeaderLength = cpu_to_le16(sizeof(struct 
 usb_cdc_ncm_nth16));
 +
 + /* TX sequence numbering */
 + nth16-wSequence = cpu_to_le16(ctx-tx_seq++);
 +
 + /* Forget about previous SKB NDP */
 + drvstate-skb_ndp = NULL;

This is probably better done after you know you cannot fail.

 +
 + /* Allocate a new NDP */
 + ndp16 = kzalloc(ctx-max_ndp_size, GFP_NOIO);

Where is this freed?

 + if (!ndp16)
 + return ret;
 +
 + /* Prepare a new NDP to add data on subsequent calls. */
 + drvstate-ndp = memset(ndp16, 0, ctx-max_ndp_size);

Either kzalloc() or memset(). Using both never makes sense.

 +
 + /* Initial NDP length */
 + ndp16-wLength = 

Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-25 Thread Oliver Neukum
On Tue, 2015-06-23 at 00:32 +0200, Enrico Mioso wrote:

 +/* XXX rewrite, not multipacket */

Can you explain what you want to do here?
 +struct sk_buff *
 +huawei_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb_in, gfp_t flags) 
 {
 + struct huawei_cdc_ncm_state *drvstate = (void *)dev-data;
 + struct cdc_ncm_ctx *ctx = drvstate-ctx;
 + struct sk_buff *skb_out;
 + int status;
 +
 + skb_out = alloc_skb(ctx-tx_max, GFP_ATOMIC);

You must test this for NULL

Regards
Oliver



--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

2015-06-25 Thread Enrico Mioso

Hi Oliver! And thank you again.

I like / recommend the usage of open messaging standards: my preferred XMPP ID
(JID) is: mrk...@jit.si.

On Thu, 25 Jun 2015, Oliver Neukum wrote:


Date: Thu, 25 Jun 2015 15:38:46
From: Oliver Neukum oneu...@suse.de
To: Enrico Mioso mrkiko...@gmail.com
Cc: linux-...@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH RFC] 2/2 huawei_cdc_ncm: introduce new TX ncm stack

On Thu, 2015-06-25 at 13:44 +0200, Enrico Mioso wrote:


On Thu, 25 Jun 2015, Oliver Neukum wrote:



Is there any advantage in keeping this in a single function?


I did this choice in the light of the fact I think the tx_fixup function will
become more complex than it is now, when aggregating frames.


Yes, but that is a reason to split the helpers up not the opposite.

Right - I understood only now your observation.

the only reason to write the manager that way was that it shouldn't become very 
complex - it should simply do things to frames, helping out in building valid 
NCM packages.





I answer here your other message to make it more convenient to read: my
intention for the tx_fixup function would be to:
- aggregate frames
- send them out when:
- a timer expires


How would you do that in tx_fixup()? If a timer is required then you
need a separate function.

Sure. I meant: I will adapt it in case needed, and expectin the code to become 
a little bit more convoluted.

OR
- we have enough data in the aggregate, and cannot add more.


Yes.

You need a third case:
- the interface is taken down.

But in general the logic for that is already there. So can you explain
what additional goals you have?
regarding the timer logic I saw it in cdc_ncm.c, but I should study it in 
more detail to understand it and implement it here where needed in case.

And sure, the interface goes down case is important: didn't think about it.
Thanks for the point.

the only other additional goal is to use the manager in such a way that NDP 
will be disposed after frames.


I think that this split between NCM management and tx_fixup makes things more 
flexible in general: this is the reason for re-writing it.



This is something done in cdc_ncm.c for example.
But here I have a question: by reading the comment in file
drivers/net/usb/rndis_host.c at line 572, there seem to be different opinions
in this matter.


That is a very old comment written for much slower devices.
rndis_host doesn't get much love nowadays.

Fine.



What to do ?


+int
+huawei_ncm_mgmt(struct usbnet *dev,
+   struct huawei_cdc_ncm_state *drvstate, struct sk_buff *skb_out, 
int mode) {
+   struct usb_cdc_ncm_nth16 *nth16 = (struct usb_cdc_ncm_nth16 
*)skb_out-data;
+   struct cdc_ncm_ctx *ctx = drvstate-ctx;
+   struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+   int ret = -EINVAL;
+   u16 ndplen, index;
+
+   switch (mode) {
+   case NCM_INIT_FRAME:
+
+   /* Write a new NTH16 header */
+   nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, 
sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+   if (!nth16) {
+   ret = -EINVAL;
+   goto error;
+   }
+
+   /* NTH16 signature and header length are known a-priori. */
+   nth16-dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+   nth16-wHeaderLength = cpu_to_le16(sizeof(struct 
usb_cdc_ncm_nth16));
+
+   /* TX sequence numbering */
+   nth16-wSequence = cpu_to_le16(ctx-tx_seq++);
+
+   /* Forget about previous SKB NDP */
+   drvstate-skb_ndp = NULL;


This is probably better done after you know you cannot fail.

Sure. Thank you.



+
+   /* Allocate a new NDP */
+   ndp16 = kzalloc(ctx-max_ndp_size, GFP_NOIO);


Where is this freed?

The intention wqas to free it in the NCM_COMMIT_NDP case.
Infact after allocating the pointer, I make a copy of it in the driver state
(drvstate) variable, and get back to it later.
Is this wrong?


Well, no, but it supposes a matched commit phase. Can you guarantee
that? I was under the oppression that in that phase you want to actually
give a frame over to the hardware.

No. When Italk about committing, I think about writing things to out skb.
another reason why i found confortable writing the code this way was to 
maintain a kind of statefullness in a more clean way.
But I understand this is kind of agruable, and I can if needed break it up as 
desired.


Regarding the commit phase - I am not sure I understand your comment, sorry
about that.
However, my intention would be to allow the caller to do calls in sequences 
like:

- init frame
- ncm update
- ncm update
- ncm update
...
- ncm update
- ncm commit

(to work in huawei mode)

OR

- ncm init frame
- ncm commit
- ncm update
- ncm update
- ncm update
- ncm update
- finalize nth

(to work in cdc_ncm.c-mode)..


But to prevent