Date: Thu, 21 May 2009 17:39:21 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r192552 - in head/sys/dev/usb: . controller Message-ID: <200905211739.n4LHdLjM073793@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: thompsa Date: Thu May 21 17:39:21 2009 New Revision: 192552 URL: http://svn.freebsd.org/changeset/base/192552 Log: Improve device mode (gadget) stall handling. Some hardware easily comes out of sync with regard to whether the current or the next control transfer should be stalled, if a stall command is always issued before receiving the SETUP packet. After this patch the stall command will only be issued when a transfer should actually be stalled. Submitted by: Hans Petter Selasky Modified: head/sys/dev/usb/controller/at91dci.c head/sys/dev/usb/controller/at91dci.h head/sys/dev/usb/controller/atmegadci.c head/sys/dev/usb/controller/atmegadci.h head/sys/dev/usb/controller/musb_otg.c head/sys/dev/usb/controller/musb_otg.h head/sys/dev/usb/controller/uss820dci.c head/sys/dev/usb/controller/uss820dci.h head/sys/dev/usb/usb_core.h head/sys/dev/usb/usb_transfer.c Modified: head/sys/dev/usb/controller/at91dci.c ============================================================================== --- head/sys/dev/usb/controller/at91dci.c Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/at91dci.c Thu May 21 17:39:21 2009 (r192552) @@ -848,7 +848,7 @@ at91dci_setup_standard_chain_sub(struct td->remainder = temp->len; td->fifo_bank = 0; td->error = 0; - td->did_stall = 0; + td->did_stall = temp->did_stall; td->short_pkt = temp->short_pkt; td->alt_next = temp->setup_alt_next; } @@ -879,6 +879,7 @@ at91dci_setup_standard_chain(struct usb2 temp.td_next = xfer->td_start[0]; temp.offset = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; + temp.did_stall = !xfer->flags_int.control_stall; sc = AT9100_DCI_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); Modified: head/sys/dev/usb/controller/at91dci.h ============================================================================== --- head/sys/dev/usb/controller/at91dci.h Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/at91dci.h Thu May 21 17:39:21 2009 (r192552) @@ -169,6 +169,7 @@ struct at91dci_std_temp { * short_pkt = 1: transfer should not be short terminated */ uint8_t setup_alt_next; + uint8_t did_stall; }; struct at91dci_config_desc { Modified: head/sys/dev/usb/controller/atmegadci.c ============================================================================== --- head/sys/dev/usb/controller/atmegadci.c Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/atmegadci.c Thu May 21 17:39:21 2009 (r192552) @@ -751,7 +751,7 @@ atmegadci_setup_standard_chain_sub(struc td->offset = temp->offset; td->remainder = temp->len; td->error = 0; - td->did_stall = 0; + td->did_stall = temp->did_stall; td->short_pkt = temp->short_pkt; td->alt_next = temp->setup_alt_next; } @@ -782,6 +782,7 @@ atmegadci_setup_standard_chain(struct us temp.td_next = xfer->td_start[0]; temp.offset = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; + temp.did_stall = !xfer->flags_int.control_stall; sc = ATMEGA_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); Modified: head/sys/dev/usb/controller/atmegadci.h ============================================================================== --- head/sys/dev/usb/controller/atmegadci.h Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/atmegadci.h Thu May 21 17:39:21 2009 (r192552) @@ -222,6 +222,7 @@ struct atmegadci_std_temp { * short_pkt = 1: transfer should not be short terminated */ uint8_t setup_alt_next; + uint8_t did_stall; }; struct atmegadci_config_desc { Modified: head/sys/dev/usb/controller/musb_otg.c ============================================================================== --- head/sys/dev/usb/controller/musb_otg.c Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/musb_otg.c Thu May 21 17:39:21 2009 (r192552) @@ -1099,7 +1099,7 @@ musbotg_setup_standard_chain_sub(struct td->offset = temp->offset; td->remainder = temp->len; td->error = 0; - td->did_stall = 0; + td->did_stall = temp->did_stall; td->short_pkt = temp->short_pkt; td->alt_next = temp->setup_alt_next; } @@ -1129,6 +1129,7 @@ musbotg_setup_standard_chain(struct usb2 temp.td_next = xfer->td_start[0]; temp.offset = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; + temp.did_stall = !xfer->flags_int.control_stall; sc = MUSBOTG_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); Modified: head/sys/dev/usb/controller/musb_otg.h ============================================================================== --- head/sys/dev/usb/controller/musb_otg.h Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/musb_otg.h Thu May 21 17:39:21 2009 (r192552) @@ -332,6 +332,7 @@ struct musbotg_std_temp { * short_pkt = 1: transfer should not be short terminated */ uint8_t setup_alt_next; + uint8_t did_stall; }; struct musbotg_config_desc { Modified: head/sys/dev/usb/controller/uss820dci.c ============================================================================== --- head/sys/dev/usb/controller/uss820dci.c Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/uss820dci.c Thu May 21 17:39:21 2009 (r192552) @@ -410,10 +410,10 @@ repeat: /* read out EPCON register */ /* enable RX input */ - if (!td->did_stall) { + if (!td->did_enable) { uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc), USS820_EPCON, 0xFF, USS820_EPCON_RXIE); - td->did_stall = 1; + td->did_enable = 1; } return (1); /* not complete */ } @@ -573,10 +573,10 @@ repeat: * Enable TX output, which must happen after that we have written * data into the FIFO. This is undocumented. */ - if (!td->did_stall) { + if (!td->did_enable) { uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc), USS820_EPCON, 0xFF, USS820_EPCON_TXOE); - td->did_stall = 1; + td->did_enable = 1; } /* check remainder */ if (td->remainder == 0) { @@ -813,7 +813,8 @@ uss820dci_setup_standard_chain_sub(struc td->offset = temp->offset; td->remainder = temp->len; td->error = 0; - td->did_stall = 0; + td->did_enable = 0; + td->did_stall = temp->did_stall; td->short_pkt = temp->short_pkt; td->alt_next = temp->setup_alt_next; } @@ -843,6 +844,7 @@ uss820dci_setup_standard_chain(struct us temp.td_next = xfer->td_start[0]; temp.offset = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; + temp.did_stall = !xfer->flags_int.control_stall; sc = USS820_DCI_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); Modified: head/sys/dev/usb/controller/uss820dci.h ============================================================================== --- head/sys/dev/usb/controller/uss820dci.h Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/controller/uss820dci.h Thu May 21 17:39:21 2009 (r192552) @@ -280,6 +280,7 @@ struct uss820dci_td { uint8_t short_pkt:1; uint8_t support_multi_buffer:1; uint8_t did_stall:1; + uint8_t did_enable:1; }; struct uss820_std_temp { @@ -296,6 +297,7 @@ struct uss820_std_temp { * short_pkt = 1: transfer should not be short terminated */ uint8_t setup_alt_next; + uint8_t did_stall; }; struct uss820dci_config_desc { Modified: head/sys/dev/usb/usb_core.h ============================================================================== --- head/sys/dev/usb/usb_core.h Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/usb_core.h Thu May 21 17:39:21 2009 (r192552) @@ -371,6 +371,7 @@ struct usb2_xfer_flags_int { uint8_t control_hdr:1; /* set if control header should be * sent */ uint8_t control_act:1; /* set if control transfer is active */ + uint8_t control_stall:1; /* set if control transfer should be stalled */ uint8_t short_frames_ok:1; /* filtered version */ uint8_t short_xfer_ok:1; /* filtered version */ Modified: head/sys/dev/usb/usb_transfer.c ============================================================================== --- head/sys/dev/usb/usb_transfer.c Thu May 21 17:26:20 2009 (r192551) +++ head/sys/dev/usb/usb_transfer.c Thu May 21 17:39:21 2009 (r192552) @@ -1225,9 +1225,13 @@ usb2_start_hardware_sub(struct usb2_xfer usb2_frlength_t len; /* Check for control endpoint stall */ - if (xfer->flags.stall_pipe) { - /* no longer active */ + if (xfer->flags.stall_pipe && xfer->flags_int.control_act) { + /* the control transfer is no longer active */ + xfer->flags_int.control_stall = 1; xfer->flags_int.control_act = 0; + } else { + /* don't stall control transfer by default */ + xfer->flags_int.control_stall = 0; } /* Check for invalid number of frames */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905211739.n4LHdLjM073793>