Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753490AbbF3Byw (ORCPT ); Mon, 29 Jun 2015 21:54:52 -0400 Received: from mail-ig0-f177.google.com ([209.85.213.177]:35363 "EHLO mail-ig0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752686AbbF3Byo (ORCPT ); Mon, 29 Jun 2015 21:54:44 -0400 MIME-Version: 1.0 In-Reply-To: <559168C1.5000206@intel.com> References: <1435539188-11360-1-git-send-email-reyad.attiyat@gmail.com> <559168C1.5000206@intel.com> From: Reyad Attiyat Date: Mon, 29 Jun 2015 20:54:24 -0500 Message-ID: Subject: Re: [PATCH v2] usb: xhci: Add support for URB_ZERO_PACKET to bulk/sg transfers To: Mathias Nyman Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5267 Lines: 127 Hey Mathias, The intention is to send an extra endpoint packet of length zero as my wireless card needs this to function properly. I have skimmed through the xhci spec and assumed that each td would generate a packet. That is why I do not chain the last trb or add a interrupt flag, since I don't want to call the urb completion function called twice or called with the incorrect td or length. I have since tried a patch that just chains the trbs together, with the zero-length trb, and this still creates a zero-length packet. I was thinking I could remove the use of the last_trb variable I was using and simply chain all the trbs together and place the interupt flag on the zero-length trb if it exsits. Also I noticed that the other host controller drivers (ehci and ohci) check to ensure that the endpoint is sending data out and that the urb length is greater than zero. I will add these checks as well to keep in line with the their implementation. Do you think this is the best method for creating a zero-length packet, will every trb convert into at least one endpoint packet? Thank you, Reyad Attiyat On Mon, Jun 29, 2015 at 10:48 AM, Mathias Nyman wrote: > Hi > > On 29.06.2015 03:53, Reyad Attiyat wrote: >> This commmit checks for the URB_ZERO_PACKET flag and creates an extra >> zero-length td if the urb transfer length is a multiple of the endpoint's >> max packet length. >> >> Signed-off-by: Reyad Attiyat >> --- > > Thanks for the patch. > Generic idea and implementation looks good, there are some opens though > See comments and questions inline. > >> drivers/usb/host/xhci-ring.c | 43 +++++++++++++++++++++++++++++++++---------- >> 1 file changed, 33 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c >> index 7d34cbf..3d57a7a 100644 >> --- a/drivers/usb/host/xhci-ring.c >> +++ b/drivers/usb/host/xhci-ring.c >> @@ -3040,7 +3040,9 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, >> int num_sgs; >> int trb_buff_len, this_sg_len, running_total; >> unsigned int total_packet_count; >> + bool zero_length_needed; >> bool first_trb; >> + int last_trb; > > last_trb isn't a really a good name as it might be confused with td->last_trb. > It's used for different purposes here. > >> u64 addr; >> bool more_trbs_coming; >> >> @@ -3056,6 +3058,14 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, >> total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, >> usb_endpoint_maxp(&urb->ep->desc)); >> >> + /* Deal with URB_ZERO_PACKET - need one more td/trb */ >> + zero_length_needed = (urb->transfer_flags & URB_ZERO_PACKET) >> + && !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc)); > > Please move the "&&" to end of previous line. > (minor thing but helps readability) > > Checkpatch also complains about missing whitespaces in the if () statements. > >> + if(zero_length_needed){ >> + num_trbs++; >> + xhci_dbg(xhci, "Creating zero length td.\n"); >> + } >> + >> trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], >> ep_index, urb->stream_id, >> num_trbs, urb, 0, mem_flags); >> @@ -3092,6 +3102,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, >> trb_buff_len = urb->transfer_buffer_length; >> >> first_trb = true; >> + last_trb = zero_length_needed ? 2 : 1; >> /* Queue the first TRB, even if it's zero-length */ >> do { >> u32 field = 0; >> @@ -3109,12 +3120,13 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, >> /* Chain all the TRBs together; clear the chain bit in the last >> * TRB to indicate it's the last TRB in the chain. >> */ >> - if (num_trbs > 1) { >> + if (num_trbs > last_trb) { >> field |= TRB_CHAIN; >> - } else { >> - /* FIXME - add check for ZERO_PACKET flag before this */ >> + } else if (num_trbs == last_trb) { >> td->last_trb = ep_ring->enqueue; >> field |= TRB_IOC; >> + } else if (zero_length_needed && num_trbs == 1) { >> + trb_buff_len = 0; >> } > > Normally chain bits are set for all TRBs except the last TRB, and the IOC (interrupt on completion) > is usually set for only the last TRB. > > In case last_trb == 2, the chain bit is now not set between the TRB containing the last data > and the actual last zero TRB, which is the last TRB in the TD. > It now also sets the interrupt on completion (IOC) for the TRB with the last data, > but not for the final last, zero lengt TRB in the TD. > > Is this intentional and how we want zero packet bulk transfers to behave? > > -Mathias > > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/