22 |
22 |
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
23 |
23 |
*/
|
24 |
24 |
/*
|
25 |
|
* Copyright 2011, Nexenta Systems, Inc. All rights reserved.
|
|
25 |
* Copyright 2011, 2012, Nexenta Systems, Inc. All rights reserved.
|
26 |
26 |
*/
|
27 |
27 |
|
28 |
28 |
#include <sys/conf.h>
|
... | ... | |
65 |
65 |
#define MSG_ID_TM_BIT 0x8000000000000000
|
66 |
66 |
#define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
|
67 |
67 |
|
|
68 |
struct stmf_svc_clocks;
|
|
69 |
|
68 |
70 |
static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
|
69 |
71 |
static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
|
70 |
72 |
static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
|
... | ... | |
91 |
93 |
void stmf_svc(void *arg);
|
92 |
94 |
void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
|
93 |
95 |
static void stmf_svc_kill_obj_requests(void *obj);
|
94 |
|
static void stmf_svc_timeout(void);
|
|
96 |
static void stmf_svc_timeout(struct stmf_svc_clocks *);
|
95 |
97 |
void stmf_check_freetask();
|
96 |
98 |
void stmf_abort_target_reset(scsi_task_t *task);
|
97 |
99 |
stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
|
... | ... | |
7777 |
7779 |
return (STMF_SUCCESS);
|
7778 |
7780 |
}
|
7779 |
7781 |
|
|
7782 |
struct stmf_svc_clocks {
|
|
7783 |
clock_t drain_start, drain_next;
|
|
7784 |
clock_t timing_start, timing_next;
|
|
7785 |
clock_t worker_delay;
|
|
7786 |
};
|
|
7787 |
|
7780 |
7788 |
/* ARGSUSED */
|
7781 |
7789 |
void
|
7782 |
7790 |
stmf_svc(void *arg)
|
... | ... | |
7785 |
7793 |
stmf_lu_t *lu;
|
7786 |
7794 |
stmf_i_lu_t *ilu;
|
7787 |
7795 |
stmf_local_port_t *lport;
|
|
7796 |
struct stmf_svc_clocks clks = { 0 };
|
7788 |
7797 |
|
7789 |
7798 |
mutex_enter(&stmf_state.stmf_lock);
|
7790 |
7799 |
stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE;
|
7791 |
7800 |
|
7792 |
7801 |
while (!(stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE)) {
|
7793 |
7802 |
if (stmf_state.stmf_svc_active == NULL) {
|
7794 |
|
stmf_svc_timeout();
|
|
7803 |
stmf_svc_timeout(&clks);
|
7795 |
7804 |
continue;
|
7796 |
7805 |
}
|
7797 |
7806 |
|
... | ... | |
7846 |
7855 |
}
|
7847 |
7856 |
|
7848 |
7857 |
static void
|
7849 |
|
stmf_svc_timeout(void)
|
|
7858 |
stmf_svc_timeout(struct stmf_svc_clocks *clks)
|
7850 |
7859 |
{
|
7851 |
7860 |
clock_t td;
|
7852 |
|
clock_t drain_start, drain_next = 0;
|
7853 |
|
clock_t timing_start, timing_next = 0;
|
7854 |
|
clock_t worker_delay = 0;
|
7855 |
7861 |
stmf_i_local_port_t *ilport, *next_ilport;
|
7856 |
7862 |
stmf_i_scsi_session_t *iss;
|
7857 |
7863 |
|
... | ... | |
7861 |
7867 |
|
7862 |
7868 |
/* Do timeouts */
|
7863 |
7869 |
if (stmf_state.stmf_nlus &&
|
7864 |
|
((!timing_next) || (ddi_get_lbolt() >= timing_next))) {
|
|
7870 |
((!clks->timing_next) || (ddi_get_lbolt() >= clks->timing_next))) {
|
7865 |
7871 |
if (!stmf_state.stmf_svc_ilu_timing) {
|
7866 |
7872 |
/* we are starting a new round */
|
7867 |
7873 |
stmf_state.stmf_svc_ilu_timing =
|
7868 |
7874 |
stmf_state.stmf_ilulist;
|
7869 |
|
timing_start = ddi_get_lbolt();
|
|
7875 |
clks->timing_start = ddi_get_lbolt();
|
7870 |
7876 |
}
|
7871 |
7877 |
|
7872 |
7878 |
stmf_check_ilu_timing();
|
7873 |
7879 |
if (!stmf_state.stmf_svc_ilu_timing) {
|
7874 |
7880 |
/* we finished a complete round */
|
7875 |
|
timing_next = timing_start + drv_usectohz(5*1000*1000);
|
|
7881 |
clks->timing_next =
|
|
7882 |
clks->timing_start + drv_usectohz(5*1000*1000);
|
7876 |
7883 |
} else {
|
7877 |
7884 |
/* we still have some ilu items to check */
|
7878 |
|
timing_next =
|
|
7885 |
clks->timing_next =
|
7879 |
7886 |
ddi_get_lbolt() + drv_usectohz(1*1000*1000);
|
7880 |
7887 |
}
|
7881 |
7888 |
|
... | ... | |
7885 |
7892 |
|
7886 |
7893 |
/* Check if there are free tasks to clear */
|
7887 |
7894 |
if (stmf_state.stmf_nlus &&
|
7888 |
|
((!drain_next) || (ddi_get_lbolt() >= drain_next))) {
|
|
7895 |
((!clks->drain_next) || (ddi_get_lbolt() >= clks->drain_next))) {
|
7889 |
7896 |
if (!stmf_state.stmf_svc_ilu_draining) {
|
7890 |
7897 |
/* we are starting a new round */
|
7891 |
7898 |
stmf_state.stmf_svc_ilu_draining =
|
7892 |
7899 |
stmf_state.stmf_ilulist;
|
7893 |
|
drain_start = ddi_get_lbolt();
|
|
7900 |
clks->drain_start = ddi_get_lbolt();
|
7894 |
7901 |
}
|
7895 |
7902 |
|
7896 |
7903 |
stmf_check_freetask();
|
7897 |
7904 |
if (!stmf_state.stmf_svc_ilu_draining) {
|
7898 |
7905 |
/* we finished a complete round */
|
7899 |
|
drain_next =
|
7900 |
|
drain_start + drv_usectohz(10*1000*1000);
|
|
7906 |
clks->drain_next =
|
|
7907 |
clks->drain_start + drv_usectohz(10*1000*1000);
|
7901 |
7908 |
} else {
|
7902 |
7909 |
/* we still have some ilu items to check */
|
7903 |
|
drain_next =
|
|
7910 |
clks->drain_next =
|
7904 |
7911 |
ddi_get_lbolt() + drv_usectohz(1*1000*1000);
|
7905 |
7912 |
}
|
7906 |
7913 |
|
... | ... | |
7909 |
7916 |
}
|
7910 |
7917 |
|
7911 |
7918 |
/* Check if we need to run worker_mgmt */
|
7912 |
|
if (ddi_get_lbolt() > worker_delay) {
|
|
7919 |
if (ddi_get_lbolt() > clks->worker_delay) {
|
7913 |
7920 |
stmf_worker_mgmt();
|
7914 |
|
worker_delay = ddi_get_lbolt() +
|
|
7921 |
clks->worker_delay = ddi_get_lbolt() +
|
7915 |
7922 |
stmf_worker_mgmt_delay;
|
7916 |
7923 |
}
|
7917 |
7924 |
|