Print this page
XXXX introduce drv_sectohz


 908                 AACDB_PRINT(softs, CE_WARN, "failed to create aac node");
 909                 goto error;
 910         }
 911 
 912         /* Common attach is OK, so we are attached! */
 913         softs->state |= AAC_STATE_RUN;
 914 
 915         /* Create event thread */
 916         softs->fibctx_p = &softs->aifctx;
 917         if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread,
 918             softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) {
 919                 AACDB_PRINT(softs, CE_WARN, "aif thread create failed");
 920                 softs->state &= ~AAC_STATE_RUN;
 921                 goto error;
 922         }
 923 
 924         aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
 925 
 926         /* Create a thread for command timeout */
 927         softs->timeout_id = timeout(aac_timer, (void *)softs,
 928             (aac_tick * drv_usectohz(1000000)));
 929 
 930         /* Common attach is OK, so we are attached! */
 931         ddi_report_dev(dip);
 932         AACDB_PRINT(softs, CE_NOTE, "aac attached ok");
 933         return (DDI_SUCCESS);
 934 
 935 error:
 936         if (attach_state & AAC_ATTACH_CREATE_SCSI)
 937                 ddi_remove_minor_node(dip, "scsi");
 938         if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
 939                 ddi_remove_minor_node(dip, "devctl");
 940         if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
 941                 aac_common_detach(softs);
 942         if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) {
 943                 (void) scsi_hba_detach(dip);
 944                 scsi_hba_tran_free(AAC_DIP2TRAN(dip));
 945         }
 946         if (attach_state & AAC_ATTACH_KMUTEX_INITED) {
 947                 mutex_destroy(&softs->io_lock);
 948                 mutex_destroy(&softs->q_comp_mutex);


4363  */
4364 static void
4365 aac_check_drain(void *arg)
4366 {
4367         struct aac_softstate *softs = arg;
4368 
4369         mutex_enter(&softs->io_lock);
4370         if (softs->ndrains) {
4371                 softs->drain_timeid = 0;
4372                 /*
4373                  * If both ASYNC and SYNC bus throttle are held,
4374                  * wake up threads only when both are drained out.
4375                  */
4376                 if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 ||
4377                     softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) &&
4378                     (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 ||
4379                     softs->bus_ncmds[AAC_CMDQ_SYNC] == 0))
4380                         cv_broadcast(&softs->drain_cv);
4381                 else
4382                         softs->drain_timeid = timeout(aac_check_drain, softs,
4383                             AAC_QUIESCE_TICK * drv_usectohz(1000000));
4384         }
4385         mutex_exit(&softs->io_lock);
4386 }
4387 
4388 /*
4389  * If not draining the outstanding cmds, drain them. Otherwise,
4390  * only update ndrains.
4391  */
4392 static void
4393 aac_start_drain(struct aac_softstate *softs)
4394 {
4395         if (softs->ndrains == 0) {
4396                 ASSERT(softs->drain_timeid == 0);
4397                 softs->drain_timeid = timeout(aac_check_drain, softs,
4398                     AAC_QUIESCE_TICK * drv_usectohz(1000000));
4399         }
4400         softs->ndrains++;
4401 }
4402 
4403 /*
4404  * Stop the draining thread when no other threads use it any longer.
4405  * Side effect: io_lock may be released in the middle.
4406  */
4407 static void
4408 aac_stop_drain(struct aac_softstate *softs)
4409 {
4410         softs->ndrains--;
4411         if (softs->ndrains == 0) {
4412                 if (softs->drain_timeid != 0) {
4413                         timeout_id_t tid = softs->drain_timeid;
4414 
4415                         softs->drain_timeid = 0;
4416                         mutex_exit(&softs->io_lock);
4417                         (void) untimeout(tid);
4418                         mutex_enter(&softs->io_lock);


6668         do {
6669                 struct aac_cmd *acp;
6670 
6671                 time_out = 0;
6672                 for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
6673                         if (acp->timeout == 0)
6674                                 continue;
6675 
6676                         /*
6677                          * If timeout happened, update outstanding cmds
6678                          * to be checked later again.
6679                          */
6680                         if (time_adjust) {
6681                                 acp->timeout += time_adjust;
6682                                 continue;
6683                         }
6684 
6685                         if (acp->timeout <= softs_timebase) {
6686                                 aac_cmd_timeout(softs, acp);
6687                                 time_out = 1;
6688                                 time_adjust = aac_tick * drv_usectohz(1000000);
6689                                 break; /* timeout happened */
6690                         } else {
6691                                 break; /* no timeout */
6692                         }
6693                 }
6694         } while (time_out);
6695 
6696         mutex_enter(&softs->time_mutex);
6697         softs->time_out = softs->timebase + aac_tick;
6698         mutex_exit(&softs->time_mutex);
6699 }
6700 
6701 /*
6702  * The event thread handles various tasks serially for the other parts of
6703  * the driver, so that they can run fast.
6704  */
6705 static void
6706 aac_event_thread(struct aac_softstate *softs)
6707 {
6708         int run = 1;


6740         cv_signal(&softs->event_wait_cv);
6741         mutex_exit(&softs->ev_lock);
6742 }
6743 
6744 /*
6745  * Internal timer. It is only responsbile for time counting and report time
6746  * related events. Events handling is done by aac_event_thread(), so that
6747  * the timer itself could be as precise as possible.
6748  */
6749 static void
6750 aac_timer(void *arg)
6751 {
6752         struct aac_softstate *softs = arg;
6753         int events = 0;
6754 
6755         mutex_enter(&softs->time_mutex);
6756 
6757         /* If timer is being stopped, exit */
6758         if (softs->timeout_id) {
6759                 softs->timeout_id = timeout(aac_timer, (void *)softs,
6760                     (aac_tick * drv_usectohz(1000000)));
6761         } else {
6762                 mutex_exit(&softs->time_mutex);
6763                 return;
6764         }
6765 
6766         /* Time counting */
6767         softs->timebase += aac_tick;
6768 
6769         /* Check time related events */
6770         if (softs->time_out && softs->time_out <= softs->timebase)
6771                 events |= AAC_EVENT_TIMEOUT;
6772         if (softs->time_sync && softs->time_sync <= softs->timebase)
6773                 events |= AAC_EVENT_SYNCTICK;
6774 
6775         mutex_exit(&softs->time_mutex);
6776 
6777         if (events)
6778                 aac_event_disp(softs, events);
6779 }
6780 




 908                 AACDB_PRINT(softs, CE_WARN, "failed to create aac node");
 909                 goto error;
 910         }
 911 
 912         /* Common attach is OK, so we are attached! */
 913         softs->state |= AAC_STATE_RUN;
 914 
 915         /* Create event thread */
 916         softs->fibctx_p = &softs->aifctx;
 917         if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread,
 918             softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) {
 919                 AACDB_PRINT(softs, CE_WARN, "aif thread create failed");
 920                 softs->state &= ~AAC_STATE_RUN;
 921                 goto error;
 922         }
 923 
 924         aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
 925 
 926         /* Create a thread for command timeout */
 927         softs->timeout_id = timeout(aac_timer, (void *)softs,
 928             drv_sectohz(aac_tick));
 929 
 930         /* Common attach is OK, so we are attached! */
 931         ddi_report_dev(dip);
 932         AACDB_PRINT(softs, CE_NOTE, "aac attached ok");
 933         return (DDI_SUCCESS);
 934 
 935 error:
 936         if (attach_state & AAC_ATTACH_CREATE_SCSI)
 937                 ddi_remove_minor_node(dip, "scsi");
 938         if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
 939                 ddi_remove_minor_node(dip, "devctl");
 940         if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
 941                 aac_common_detach(softs);
 942         if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) {
 943                 (void) scsi_hba_detach(dip);
 944                 scsi_hba_tran_free(AAC_DIP2TRAN(dip));
 945         }
 946         if (attach_state & AAC_ATTACH_KMUTEX_INITED) {
 947                 mutex_destroy(&softs->io_lock);
 948                 mutex_destroy(&softs->q_comp_mutex);


4363  */
4364 static void
4365 aac_check_drain(void *arg)
4366 {
4367         struct aac_softstate *softs = arg;
4368 
4369         mutex_enter(&softs->io_lock);
4370         if (softs->ndrains) {
4371                 softs->drain_timeid = 0;
4372                 /*
4373                  * If both ASYNC and SYNC bus throttle are held,
4374                  * wake up threads only when both are drained out.
4375                  */
4376                 if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 ||
4377                     softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) &&
4378                     (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 ||
4379                     softs->bus_ncmds[AAC_CMDQ_SYNC] == 0))
4380                         cv_broadcast(&softs->drain_cv);
4381                 else
4382                         softs->drain_timeid = timeout(aac_check_drain, softs,
4383                             drv_sectohz(AAC_QUIESCE_TICK));
4384         }
4385         mutex_exit(&softs->io_lock);
4386 }
4387 
4388 /*
4389  * If not draining the outstanding cmds, drain them. Otherwise,
4390  * only update ndrains.
4391  */
4392 static void
4393 aac_start_drain(struct aac_softstate *softs)
4394 {
4395         if (softs->ndrains == 0) {
4396                 ASSERT(softs->drain_timeid == 0);
4397                 softs->drain_timeid = timeout(aac_check_drain, softs,
4398                     drv_sectohz(AAC_QUIESCE_TICK));
4399         }
4400         softs->ndrains++;
4401 }
4402 
4403 /*
4404  * Stop the draining thread when no other threads use it any longer.
4405  * Side effect: io_lock may be released in the middle.
4406  */
4407 static void
4408 aac_stop_drain(struct aac_softstate *softs)
4409 {
4410         softs->ndrains--;
4411         if (softs->ndrains == 0) {
4412                 if (softs->drain_timeid != 0) {
4413                         timeout_id_t tid = softs->drain_timeid;
4414 
4415                         softs->drain_timeid = 0;
4416                         mutex_exit(&softs->io_lock);
4417                         (void) untimeout(tid);
4418                         mutex_enter(&softs->io_lock);


6668         do {
6669                 struct aac_cmd *acp;
6670 
6671                 time_out = 0;
6672                 for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
6673                         if (acp->timeout == 0)
6674                                 continue;
6675 
6676                         /*
6677                          * If timeout happened, update outstanding cmds
6678                          * to be checked later again.
6679                          */
6680                         if (time_adjust) {
6681                                 acp->timeout += time_adjust;
6682                                 continue;
6683                         }
6684 
6685                         if (acp->timeout <= softs_timebase) {
6686                                 aac_cmd_timeout(softs, acp);
6687                                 time_out = 1;
6688                                 time_adjust = drv_sectohz(aac_tick);
6689                                 break; /* timeout happened */
6690                         } else {
6691                                 break; /* no timeout */
6692                         }
6693                 }
6694         } while (time_out);
6695 
6696         mutex_enter(&softs->time_mutex);
6697         softs->time_out = softs->timebase + aac_tick;
6698         mutex_exit(&softs->time_mutex);
6699 }
6700 
6701 /*
6702  * The event thread handles various tasks serially for the other parts of
6703  * the driver, so that they can run fast.
6704  */
6705 static void
6706 aac_event_thread(struct aac_softstate *softs)
6707 {
6708         int run = 1;


6740         cv_signal(&softs->event_wait_cv);
6741         mutex_exit(&softs->ev_lock);
6742 }
6743 
6744 /*
6745  * Internal timer. It is only responsbile for time counting and report time
6746  * related events. Events handling is done by aac_event_thread(), so that
6747  * the timer itself could be as precise as possible.
6748  */
6749 static void
6750 aac_timer(void *arg)
6751 {
6752         struct aac_softstate *softs = arg;
6753         int events = 0;
6754 
6755         mutex_enter(&softs->time_mutex);
6756 
6757         /* If timer is being stopped, exit */
6758         if (softs->timeout_id) {
6759                 softs->timeout_id = timeout(aac_timer, (void *)softs,
6760                     drv_sectohz(aac_tick));
6761         } else {
6762                 mutex_exit(&softs->time_mutex);
6763                 return;
6764         }
6765 
6766         /* Time counting */
6767         softs->timebase += aac_tick;
6768 
6769         /* Check time related events */
6770         if (softs->time_out && softs->time_out <= softs->timebase)
6771                 events |= AAC_EVENT_TIMEOUT;
6772         if (softs->time_sync && softs->time_sync <= softs->timebase)
6773                 events |= AAC_EVENT_SYNCTICK;
6774 
6775         mutex_exit(&softs->time_mutex);
6776 
6777         if (events)
6778                 aac_event_disp(softs, events);
6779 }
6780