From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1UDgML-0004C0-93 for mharc-grub-devel@gnu.org; Thu, 07 Mar 2013 14:20:09 -0500 Received: from eggs.gnu.org ([208.118.235.92]:53309) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UDgMH-00048W-J8 for grub-devel@gnu.org; Thu, 07 Mar 2013 14:20:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UDgM9-0002ca-CH for grub-devel@gnu.org; Thu, 07 Mar 2013 14:20:05 -0500 Received: from smtp.volny.cz ([2001:4de8:71c:62::33]:41627) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UDgM8-0002Y6-UR for grub-devel@gnu.org; Thu, 07 Mar 2013 14:19:57 -0500 Received: from [192.168.6.163] (unknown [193.86.90.90]) (using SSLv3 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: starous) by smtp.volny.cz (Postfix) with ESMTPSA id 54F85260BF1 for ; Thu, 7 Mar 2013 20:19:53 +0100 (CET) Subject: Re: [PATCH] Long USB transfers problem From: =?UTF-8?Q?Ale=C5=A1?= Nesrsta To: The development of GNU GRUB In-Reply-To: <512A6911.6080706@gmail.com> References: <1354402009.2479.108.camel@pracovna> <50FC659C.6020105@gmail.com> <1360624408.2624.88.camel@pracovna> <512A6911.6080706@gmail.com> Content-Type: multipart/mixed; boundary="=-s6cHPnYfkDmvNt2q7Bhl" Date: Thu, 07 Mar 2013 20:19:46 +0100 Message-ID: <1362683986.2567.59.camel@pracovna> Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4de8:71c:62::33 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Mar 2013 19:20:08 -0000 --=-s6cHPnYfkDmvNt2q7Bhl Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable 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 '=CF=86-coder/phcoder' Serbinenko p=C3=AD=C5=A1e v Ne 24. 02. 20= 13 v 20:25 +0100: > > What do you prefer - this "improved" bulk transfer limiting or the >=20 > > simple original one? >=20 > 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? >=20 > >=20 > > BR, > > Ales > >=20 > >=20 > >=20 > > _______________________________________________ > > Grub-devel mailing list > > Grub-devel@gnu.org > > https://lists.gnu.org/mailman/listinfo/grub-devel >=20 >=20 >=20 > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel --=-s6cHPnYfkDmvNt2q7Bhl Content-Disposition: attachment; filename="usb_patch_130307_0" Content-Type: text/x-patch; name="usb_patch_130307_0"; charset="ISO-8859-2" Content-Transfer-Encoding: 7bit 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 #include + +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; --=-s6cHPnYfkDmvNt2q7Bhl--