[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

patch for aac



This patch is a partial fix for PR 2415.  It prevents a ccb from being
lost temporarily when the fib queue became full.  This ccb was being
removed from the ready queue and not going on the fib queue.  This was
only fixed after the timeout on the ccb fired, causing a hang until that
timeout fired.

It also incorporates a change from FreeBSD in the interrupt handler for a
possible race condition.  

There is still a problem with the driver though.  I am getting errors
like "not queued, error 5" when copying between two devices with dd.
This may be due to heavy usage or actually accessing two containers at 
the same time.  This error stems from aac_get_ccb() failing, apparently
due to lack of free ccb's.  This causes the process accessing the disk
to hang permanently.  Lowering sc->sc_link.openings seems to reduce the
errors but not eliminate them.

Index: aac.c
===================================================================
RCS file: /home/cvsup/src/sys/dev/ic/aac.c,v
retrieving revision 1.14
diff -c -r1.14 aac.c
*** aac.c       27 Mar 2002 15:02:59 -0000      1.14
--- aac.c       5 May 2002 12:38:34 -0000
***************
*** 83,89 ****
  void  aac_enqueue_ccb(struct aac_softc *, struct aac_ccb *);
  int   aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
  void  aac_eval_mapping(u_int32_t, int *, int *, int *);
! int   aac_exec_ccb(struct aac_ccb *);
  void  aac_free_ccb(struct aac_softc *, struct aac_ccb *);
  struct aac_ccb *aac_get_ccb(struct aac_softc *, int);
  #if 0
--- 83,89 ----
  void  aac_enqueue_ccb(struct aac_softc *, struct aac_ccb *);
  int   aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
  void  aac_eval_mapping(u_int32_t, int *, int *, int *);
! void  aac_build_ccb(struct aac_ccb *);
  void  aac_free_ccb(struct aac_softc *, struct aac_ccb *);
  struct aac_ccb *aac_get_ccb(struct aac_softc *, int);
  #if 0
***************
*** 938,952 ****

        /* Controller has a message for us? */
        if (reason & AAC_DB_COMMAND_READY) {
-               aac_host_command(sc);
                AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
                claimed = 1;
        }

        /* Controller has a response for us? */
        if (reason & AAC_DB_RESPONSE_READY) {
-               aac_host_response(sc);
                AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
                claimed = 1;
        }

--- 938,952 ----

        /* Controller has a message for us? */
        if (reason & AAC_DB_COMMAND_READY) {
                AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
+               aac_host_command(sc);
                claimed = 1;
        }

        /* Controller has a response for us? */
        if (reason & AAC_DB_RESPONSE_READY) {
                AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
+               aac_host_response(sc);
                claimed = 1;
        }

***************
*** 1465,1486 ****
  {
        struct aac_ccb *ccb;
        struct scsi_xfer *xs;

        AAC_DPRINTF(AAC_D_QUEUE, ("aac_start_ccbs(%p) ", sc));

        while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {

                xs = ccb->ac_xs;
!               if (ccb->ac_flags & AAC_ACF_WATCHDOG)
                        timeout_del(&xs->stimeout);

!               if (aac_exec_ccb(ccb) == 0) {
                        ccb->ac_flags |= AAC_ACF_WATCHDOG;
                        timeout_set(&ccb->ac_xs->stimeout, aac_watchdog,
ccb);
                        timeout_add(&xs->stimeout,
                            (AAC_WATCH_TIMEOUT * hz) / 1000);
                        break;
                }
                TAILQ_REMOVE(&sc->sc_ccbq, ccb, ac_chain);

                if ((xs->flags & SCSI_POLL) == 0) {
--- 1465,1495 ----
  {
        struct aac_ccb *ccb;
        struct scsi_xfer *xs;
+       aac_lock_t lock;

        AAC_DPRINTF(AAC_D_QUEUE, ("aac_start_ccbs(%p) ", sc));

        while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {

                xs = ccb->ac_xs;
!
!               if (ccb->ac_flags & AAC_ACF_WATCHDOG) {
                        timeout_del(&xs->stimeout);
+               /* watchdog timer implies ccb already built */
+               } else {
+                       aac_build_ccb(ccb);
+               }

!               if (aac_start(ccb) == EBUSY) {
                        ccb->ac_flags |= AAC_ACF_WATCHDOG;
                        timeout_set(&ccb->ac_xs->stimeout, aac_watchdog,
ccb);
                        timeout_add(&xs->stimeout,
                            (AAC_WATCH_TIMEOUT * hz) / 1000);
                        break;
                }
+
+               xs->error = XS_NOERROR;
+               xs->resid = 0;
                TAILQ_REMOVE(&sc->sc_ccbq, ccb, ac_chain);

                if ((xs->flags & SCSI_POLL) == 0) {
***************
*** 1491,1498 ****
        }
  }

! int
! aac_exec_ccb(ccb)
        struct aac_ccb *ccb;
  {
        struct scsi_xfer *xs = ccb->ac_xs;
--- 1500,1507 ----
        }
  }

! void
! aac_build_ccb(ccb)
        struct aac_ccb *ccb;
  {
        struct scsi_xfer *xs = ccb->ac_xs;
***************
*** 1504,1510 ****
        struct aac_blockwrite *bw;
        bus_dmamap_t xfer;

!       AAC_DPRINTF(AAC_D_CMD, ("aac_exec_ccb(%p, %p) ", xs, ccb));

        /* build the FIB */
        fib = ccb->ac_fib;
--- 1513,1519 ----
        struct aac_blockwrite *bw;
        bus_dmamap_t xfer;

!       AAC_DPRINTF(AAC_D_CMD, ("aac_build_ccb(%p, %p) ", xs, ccb));

        /* build the FIB */
        fib = ccb->ac_fib;
***************
*** 1569,1579 ****
                    sizeof(struct aac_sg_entry);
        }

!       aac_start(ccb);
!
!       xs->error = XS_NOERROR;
!       xs->resid = 0;
!       return (1);
  }

  /********************************************************************************
--- 1578,1584 ----
                    sizeof(struct aac_sg_entry);
        }

!       return;
  }

  /********************************************************************************


-- 
Brandin Claar
Network Analyst 
Penn State Applied Research Lab