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
> > [email protected]
> > https://lists.gnu.org/mailman/listinfo/grub-devel
>
>
>
> _______________________________________________
> Grub-devel mailing list
> [email protected]
> https://lists.gnu.org/mailman/listinfo/grub-devel
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;
_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel