All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aleš Nesrsta" <starous@volny.cz>
To: The development of GNU GRUB <grub-devel@gnu.org>
Subject: Re: [PATCH] Long USB transfers problem
Date: Thu, 07 Mar 2013 20:19:46 +0100	[thread overview]
Message-ID: <1362683986.2567.59.camel@pracovna> (raw)
In-Reply-To: <512A6911.6080706@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1229 bytes --]

Hi Vladimir,

do you mean something like that ?

Or do you want also to change "int endpoint" to "struct
grub_usb_desc_endp *endpoint" - like in Your patch ?


Additionally some (unrelated) note:
There is also waiting important USB patch in bug
https://savannah.gnu.org/bugs/?36740
(related to USB 2.0 Split Transfers) - could You look there?


(Sorry about long delay, I was on foreign business trip where I was too
busy... And, unfortunately, I will go there next week again for approx.
one month.)

BR,
Ales


Vladimir 'φ-coder/phcoder' Serbinenko píše v Ne 24. 02. 2013 v 20:25
+0100:
> > What do you prefer - this "improved" bulk transfer limiting or the
> 
> > simple original one?
> 
> I misread what patch does. It looks better now. Can you propagate the
> change to bulk_write as well, like in the patch I sent?
> 
> > 
> > BR,
> > Ales
> > 
> > 
> > 
> > _______________________________________________
> > Grub-devel mailing list
> > Grub-devel@gnu.org
> > https://lists.gnu.org/mailman/listinfo/grub-devel
> 
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


[-- Attachment #2: usb_patch_130307_0 --]
[-- Type: text/x-patch, Size: 6996 bytes --]

diff -purB ./grub/grub-core/bus/usb/ehci.c ./grub_patched/grub-core/bus/usb/ehci.c
--- ./grub/grub-core/bus/usb/ehci.c	2013-01-27 22:12:17.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/ehci.c	2013-03-07 19:14:33.000000000 +0100
@@ -1902,7 +1902,9 @@ static struct grub_usb_controller_dev us
   .cancel_transfer = grub_ehci_cancel_transfer,
   .hubports = grub_ehci_hubports,
   .portstatus = grub_ehci_portstatus,
-  .detect_dev = grub_ehci_detect_dev
+  .detect_dev = grub_ehci_detect_dev,
+  /* estimated max. count of TDs for one bulk transfer */
+  .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 
 };
 
 GRUB_MOD_INIT (ehci)
diff -purB ./grub/grub-core/bus/usb/ohci.c ./grub_patched/grub-core/bus/usb/ohci.c
--- ./grub/grub-core/bus/usb/ohci.c	2013-01-27 22:12:17.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/ohci.c	2013-03-07 19:14:33.000000000 +0100
@@ -1431,7 +1431,9 @@ static struct grub_usb_controller_dev us
   .cancel_transfer = grub_ohci_cancel_transfer,
   .hubports = grub_ohci_hubports,
   .portstatus = grub_ohci_portstatus,
-  .detect_dev = grub_ohci_detect_dev
+  .detect_dev = grub_ohci_detect_dev,
+  /* estimated max. count of TDs for one bulk transfer */
+  .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
 };
 
 static struct grub_preboot *fini_hnd;
diff -purB ./grub/grub-core/bus/usb/uhci.c ./grub_patched/grub-core/bus/usb/uhci.c
--- ./grub/grub-core/bus/usb/uhci.c	2013-01-27 22:12:17.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/uhci.c	2013-03-07 19:14:33.000000000 +0100
@@ -823,7 +823,9 @@ static struct grub_usb_controller_dev us
   .cancel_transfer = grub_uhci_cancel_transfer,
   .hubports = grub_uhci_hubports,
   .portstatus = grub_uhci_portstatus,
-  .detect_dev = grub_uhci_detect_dev
+  .detect_dev = grub_uhci_detect_dev,
+  /* estimated max. count of TDs for one bulk transfer */
+  .max_bulk_tds = N_TD * 3 / 4
 };
 
 GRUB_MOD_INIT(uhci)
diff -purB ./grub/grub-core/bus/usb/usbtrans.c ./grub_patched/grub-core/bus/usb/usbtrans.c
--- ./grub/grub-core/bus/usb/usbtrans.c	2013-01-27 22:12:17.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/usbtrans.c	2013-03-07 20:09:38.000000000 +0100
@@ -25,6 +25,26 @@
 #include <grub/usbtrans.h>
 #include <grub/time.h>
 
+
+static inline unsigned int
+grub_usb_bulk_maxpacket (grub_usb_device_t dev, int endpoint)
+{
+  unsigned int max = 64;
+
+  /* Use the maximum packet size given in the endpoint descriptor.  */
+  if (dev->initialized)
+    {
+      struct grub_usb_desc_endp *endpdesc;
+      endpdesc = grub_usb_get_endpdescriptor (dev, endpoint);
+
+      if (endpdesc)
+	max = endpdesc->maxpacket;
+    }
+
+  return max;
+}
+
+
 static grub_usb_err_t
 grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, 
 				    grub_usb_transfer_t transfer,
@@ -224,20 +244,6 @@ grub_usb_bulk_setup_readwrite (grub_usb_
   if (type == GRUB_USB_TRANSFER_TYPE_OUT)
     grub_memcpy ((char *) data, data_in, size);
 
-  /* Use the maximum packet size given in the endpoint descriptor.  */
-  if (dev->initialized)
-    {
-      struct grub_usb_desc_endp *endpdesc;
-      endpdesc = grub_usb_get_endpdescriptor (dev, endpoint);
-
-      if (endpdesc)
-	max = endpdesc->maxpacket;
-      else
-	max = 64;
-    }
-  else
-    max = 64;
-
   /* Create a transfer.  */
   transfer = grub_malloc (sizeof (struct grub_usb_transfer));
   if (! transfer)
@@ -246,6 +252,8 @@ grub_usb_bulk_setup_readwrite (grub_usb_
       return NULL;
     }
 
+  max = grub_usb_bulk_maxpacket (dev, endpoint);
+
   datablocks = ((size + max - 1) / max);
   transfer->transcnt = datablocks;
   transfer->size = size - 1;
@@ -333,38 +341,36 @@ grub_usb_bulk_readwrite (grub_usb_device
   return err;
 }
 
-grub_usb_err_t
-grub_usb_bulk_write (grub_usb_device_t dev,
-		     int endpoint, grub_size_t size, char *data)
-{
-  grub_size_t actual;
-  grub_usb_err_t err;
-
-  err = grub_usb_bulk_readwrite (dev, endpoint, size, data,
-				 GRUB_USB_TRANSFER_TYPE_OUT, 1000, &actual);
-  if (!err && actual != size)
-    err = GRUB_USB_ERR_DATA;
-  return err;
-}
-
-grub_usb_err_t
-grub_usb_bulk_read (grub_usb_device_t dev,
-		    int endpoint, grub_size_t size, char *data)
+static grub_usb_err_t
+grub_usb_bulk_readwrite_packetize (grub_usb_device_t dev,
+				   int endpoint,
+				   grub_transfer_type_t type,
+				   grub_size_t size, char *data)
 {
   grub_size_t actual, transferred;
   grub_usb_err_t err;
   grub_size_t current_size, position;
+  grub_size_t max_bulk_transfer_len = MAX_USB_TRANSFER_LEN;
+  grub_size_t max;
+
+  if (dev->controller.dev->max_bulk_tds)
+    {
+      max = grub_usb_bulk_maxpacket (dev, endpoint);
+
+      /* Calculate max. possible length of bulk transfer */
+      max_bulk_transfer_len = dev->controller.dev->max_bulk_tds * max;
+    }
 
   for (position = 0, transferred = 0;
-       position < size; position += MAX_USB_TRANSFER_LEN)
+       position < size; position += max_bulk_transfer_len)
     {
       current_size = size - position;
-      if (current_size >= MAX_USB_TRANSFER_LEN)
-	current_size = MAX_USB_TRANSFER_LEN;
+      if (current_size >= max_bulk_transfer_len)
+	current_size = max_bulk_transfer_len;
       err = grub_usb_bulk_readwrite (dev, endpoint, current_size,
-              &data[position], GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual);
+              &data[position], type, 1000, &actual);
       transferred += actual;
-      if (err || (current_size != actual) ) break;
+      if (err || (current_size != actual)) break;
     }
 
   if (!err && transferred != size)
@@ -373,6 +379,24 @@ grub_usb_bulk_read (grub_usb_device_t de
 }
 
 grub_usb_err_t
+grub_usb_bulk_write (grub_usb_device_t dev,
+		     int endpoint, grub_size_t size, char *data)
+{
+  return grub_usb_bulk_readwrite_packetize (dev, endpoint,
+					    GRUB_USB_TRANSFER_TYPE_OUT,
+					    size, data);
+}
+
+grub_usb_err_t
+grub_usb_bulk_read (grub_usb_device_t dev,
+		    int endpoint, grub_size_t size, char *data)
+{
+  return grub_usb_bulk_readwrite_packetize (dev, endpoint,
+					    GRUB_USB_TRANSFER_TYPE_IN,
+					    size, data);
+}
+
+grub_usb_err_t
 grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual)
 {
   grub_usb_err_t err;
diff -purB ./grub/include/grub/usb.h ./grub_patched/include/grub/usb.h
--- ./grub/include/grub/usb.h	2013-01-27 22:12:17.000000000 +0100
+++ ./grub_patched/include/grub/usb.h	2013-03-07 19:14:33.000000000 +0100
@@ -124,6 +124,13 @@ struct grub_usb_controller_dev
 
   /* Per controller flag - port reset pending, don't do another reset */
   grub_uint64_t pending_reset;
+
+  /* Max. number of transfer descriptors used per one bulk transfer */
+  /* The reason is to prevent "exhausting" of TD by large bulk */
+  /* transfer - number of TD is limited in USB host driver */
+  /* Value is calculated/estimated in driver - some TDs should be */
+  /* reserved for posible concurrent control or "interrupt" transfers */
+  grub_size_t max_bulk_tds;
   
   /* The next host controller.  */
   struct grub_usb_controller_dev *next;

      reply	other threads:[~2013-03-07 19:20 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-01 22:46 [PATCH] Long USB transfers problem Aleš Nesrsta
2012-12-10 10:57 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-12-10 17:49   ` Aleš Nesrsta
2012-12-10 20:33     ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-12-11 20:40       ` Aleš Nesrsta
2013-01-20 21:46 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-02-11 23:13   ` Aleš Nesrsta
2013-02-24 18:37     ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-02-24 19:09     ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-02-24 19:25     ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-03-07 19:19       ` Aleš Nesrsta [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1362683986.2567.59.camel@pracovna \
    --to=starous@volny.cz \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.