> From: Felipe Balbi [mailto:ba...@ti.com]
> Sent: Thursday, February 21, 2013 1:16 AM
> 
> On Tue, Feb 19, 2013 at 06:50:05PM -0800, Paul Zimmerman wrote:
> 
> > +#ifdef DWC2_TRACK_MISSED_SOFS
> > +#warning Compiling code to track missed SOFs
> > +#define FRAME_NUM_ARRAY_SIZE 1000
> > +
> > +/* This function is for debug only */
> > +static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
> > +{
> > +   static u16 frame_num_array[FRAME_NUM_ARRAY_SIZE];
> > +   static u16 last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
> 
> you could turn this into a list_head and everytime you find a missed
> sof, you allocate a e.g. struct dwc2_missec_isoc_data and add that to a
> list of missed isocs. The only "problem" is that you would have to
> allocate with GFP_ATOMIC.

Actually, this function is called on every SOF, not just when one is
missed, so that wouldn't make much difference. I guess I should
rename this to dwc2_track_sofs().

I didn't notice the static allocations before, I will change that to use
kmalloc() at init time.

> > +   static int frame_num_idx;
> > +   static u16 last_frame_num = HFNUM_MAX_FRNUM;
> > +   static int dumped_frame_num_array;
> > +   u16 curr_frame_number = hsotg->frame_number;
> > +
> > +   if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
> > +           if ((last_frame_num + 1 & HFNUM_MAX_FRNUM) !=
> > +               curr_frame_number) {
> > +                   frame_num_array[frame_num_idx] = curr_frame_number;
> > +                   last_frame_num_array[frame_num_idx++] = last_frame_num;
> > +           }
> > +   } else if (!dumped_frame_num_array) {
> > +           int i;
> > +
> > +           dev_info(hsotg->dev, "Frame     Last Frame\n");
> > +           dev_info(hsotg->dev, "-----     ----------\n");
> > +           for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
> > +                   dev_info(hsotg->dev, "0x%04x    0x%04x\n",
> > +                            frame_num_array[i], last_frame_num_array[i]);
> > +           }
> > +           dumped_frame_num_array = 1;
> > +   }
> > +   last_frame_num = curr_frame_number;
> > +}
> > +#endif
> 
> do you really need to dump this information at the time it happens ? I
> ask this because this looks like a very nice feature to have in
> production. You could just pack it under a debugfs interface and provide
> a Kconfig choice to enable (or not) debugfs support. Then driver can
> constantly track this information and let user see by "cat
> /sys/kernel/debug/dwc2/missed_sofs" or something similar.

Yes, that's a good suggestion. I will look into it.

> > +static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
> > +{
> > +   struct list_head *qh_entry;
> > +   struct dwc2_qh *qh;
> > +   u32 hfnum;
> > +   enum dwc2_transaction_type tr_type;
> > +
> > +#ifdef DEBUG_SOF
> > +   dev_vdbg(hsotg->dev, "--Start of Frame Interrupt--\n");
> > +#endif
> > +
> > +   hfnum = readl(hsotg->regs + HFNUM);
> > +   hsotg->frame_number = hfnum >> HFNUM_FRNUM_SHIFT &
> > +                       HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT;
> > +
> > +#ifdef DWC2_TRACK_MISSED_SOFS
> > +   dwc2_track_missed_sofs(hsotg);
> > +#endif
> 
> another suggestion, would be to move the ifdefs inside the function
> body, so that it's a no-op when DWC2_TRACK_MISSED_SOFS isn't set, which
> means you don't need to ifdef the call here.

Yep, will do.

> > +   if (chan->hcint & HCINTMSK_XFERCOMPL) {
> > +           /*
> > +            * Todo: This is here because of a possible hardware bug. Spec
> > +            * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
> > +            * interrupt w/ACK bit set should occur, but I only see the
> > +            * XFERCOMP bit, even with it masked out. This is a workaround
> > +            * for that behavior. Should fix this when hardware is fixed.
> > +            */
> > +           if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && !chan->ep_is_in)
> > +                   dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
> > +           dwc2_hc_xfercomp_intr(hsotg, chan, chnum, qtd);
> > +   } else if (chan->hcint & HCINTMSK_STALL) {
> > +           dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
> > +   } else if ((chan->hcint & HCINTMSK_XACTERR) &&
> > +              hsotg->core_params->dma_desc_enable <= 0) {
> > +           if (out_nak_enh) {
> > +                   if (chan->hcint &
> > +                       (HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) {
> > +                           dev_vdbg(hsotg->dev,
> > +                                    "XactErr with NYET/NAK/ACK\n");
> > +                           qtd->error_count = 0;
> > +                   } else {
> > +                           dev_vdbg(hsotg->dev,
> > +                                    "XactErr without NYET/NAK/ACK\n");
> > +                   }
> > +           }
> > +
> > +           /*
> > +            * Must handle xacterr before nak or ack. Could get a xacterr
> > +            * at the same time as either of these on a BULK/CONTROL OUT
> > +            * that started with a PING. The xacterr takes precedence.
> > +            */
> > +           dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
> > +   } else if ((chan->hcint & HCINTMSK_XCS_XACT) &&
> > +              hsotg->core_params->dma_desc_enable > 0) {
> 
> are all these really mutually exclusive ? I mean, can you get XACTERR
> and AHBERR simultaneously ?

Yes, you can. I will fix this so they are not mutually exclusive.

-- 
Paul

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to