aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-03-02 14:49:26 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:28 -0400
commit7c40a8035815479c7c12ab0cdcea71e0f4c3a9c8 (patch)
tree43290f7b96374f0ff8e80ad5e8620f3dc8242f1a /drivers/scsi/isci
parent150fc6fc725055b400a8865e6785dc8dd0a2225d (diff)
isci: rework timer api
Prepare the timer api for the arrival of dynamic creation and destruction events from the core. It pretended to do this previously but the core to date only used it in a static init-time only fashion. This is an interim fix until a cleaner event queue can be developed. 1/ make all locking external to the api (add WARN_ONCE to verify) 2/ add a timer_destroy interface (to be used by the core) 3/ use del_timer_sync() prior to deallocating timer data 4/ delete the "timer_list" indirection, we only have timers allocated for the isci_host 5/ fix detection of timer list allocation errors Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r--drivers/scsi/isci/events.c49
-rw-r--r--drivers/scsi/isci/events.h3
-rw-r--r--drivers/scsi/isci/host.c32
-rw-r--r--drivers/scsi/isci/host.h2
-rw-r--r--drivers/scsi/isci/task.c17
-rw-r--r--drivers/scsi/isci/timers.c173
-rw-r--r--drivers/scsi/isci/timers.h60
7 files changed, 104 insertions, 232 deletions
diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c
index 8872f4ca6aaa..c5cbaedac041 100644
--- a/drivers/scsi/isci/events.c
+++ b/drivers/scsi/isci/events.c
@@ -75,35 +75,23 @@
75 * whenever the timer expires. 75 * whenever the timer expires.
76 * @controller: This parameter specifies the controller with which this timer 76 * @controller: This parameter specifies the controller with which this timer
77 * is to be associated. 77 * is to be associated.
78 * @cookie: This parameter specifies a piece of information that the user must 78 * @cb_param: opaque callback parameter
79 * retain. This cookie is to be supplied by the user anytime a timeout
80 * occurs for the created timer.
81 * 79 *
82 * This method returns a handle to a timer object created by the user. The 80 * This method returns a handle to a timer object created by the user. The
83 * handle will be utilized for all further interactions relating to this timer. 81 * handle will be utilized for all further interactions relating to this timer.
84 */ 82 */
85void *isci_event_timer_create( 83void *isci_event_timer_create(struct scic_sds_controller *scic,
86 struct scic_sds_controller *controller, 84 void (*timer_callback)(void *),
87 void (*timer_callback)(void *), 85 void *cb_param)
88 void *cookie)
89{ 86{
90 struct isci_host *isci_host; 87 struct isci_host *ihost = sci_object_get_association(scic);
91 struct isci_timer *timer = NULL; 88 struct isci_timer *itimer;
92
93 isci_host = (struct isci_host *)sci_object_get_association(controller);
94 89
95 dev_dbg(&isci_host->pdev->dev, 90 itimer = isci_timer_create(ihost, cb_param, timer_callback);
96 "%s: isci_host = %p",
97 __func__, isci_host);
98
99 timer = isci_timer_create(&isci_host->timer_list_struct,
100 isci_host,
101 cookie,
102 timer_callback);
103 91
104 dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer); 92 dev_dbg(&ihost->pdev->dev, "%s: timer = %p\n", __func__, itimer);
105 93
106 return (void *)timer; 94 return itimer;
107} 95}
108 96
109 97
@@ -146,14 +134,9 @@ void isci_event_timer_start(
146 * @timer: This parameter specifies the timer to be stopped. 134 * @timer: This parameter specifies the timer to be stopped.
147 * 135 *
148 */ 136 */
149void isci_event_timer_stop( 137void isci_event_timer_stop(struct scic_sds_controller *controller, void *timer)
150 struct scic_sds_controller *controller,
151 void *timer)
152{ 138{
153 struct isci_host *isci_host; 139 struct isci_host *isci_host = sci_object_get_association(controller);
154
155 isci_host =
156 (struct isci_host *)sci_object_get_association(controller);
157 140
158 dev_dbg(&isci_host->pdev->dev, 141 dev_dbg(&isci_host->pdev->dev,
159 "%s: isci_host = %p, timer = %p\n", 142 "%s: isci_host = %p, timer = %p\n",
@@ -162,6 +145,16 @@ void isci_event_timer_stop(
162 isci_timer_stop((struct isci_timer *)timer); 145 isci_timer_stop((struct isci_timer *)timer);
163} 146}
164 147
148void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer)
149{
150 struct isci_host *ihost = sci_object_get_association(scic);
151
152 dev_dbg(&ihost->pdev->dev, "%s: ihost = %p, timer = %p\n",
153 __func__, ihost, timer);
154
155 isci_del_timer(ihost, timer);
156}
157
165/** 158/**
166 * isci_event_controller_start_complete() - This user callback will inform the 159 * isci_event_controller_start_complete() - This user callback will inform the
167 * user that the controller has finished the start process. The associated 160 * user that the controller has finished the start process. The associated
diff --git a/drivers/scsi/isci/events.h b/drivers/scsi/isci/events.h
index 98526e9fb14a..fa2f6aa1093c 100644
--- a/drivers/scsi/isci/events.h
+++ b/drivers/scsi/isci/events.h
@@ -111,6 +111,9 @@ void isci_event_timer_stop(
111 struct scic_sds_controller *controller, 111 struct scic_sds_controller *controller,
112 void *timer); 112 void *timer);
113 113
114
115void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer);
116
114/** 117/**
115 * isci_event_controller_start_complete() - This user callback will inform the 118 * isci_event_controller_start_complete() - This user callback will inform the
116 * user that the controller has finished the start process. 119 * user that the controller has finished the start process.
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index d8d6f67bd69c..1bc91f2b4f93 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -349,9 +349,14 @@ void isci_host_deinit(struct isci_host *ihost)
349 } 349 }
350 350
351 set_bit(IHOST_STOP_PENDING, &ihost->flags); 351 set_bit(IHOST_STOP_PENDING, &ihost->flags);
352
353 spin_lock_irq(&ihost->scic_lock);
352 scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT); 354 scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT);
355 spin_unlock_irq(&ihost->scic_lock);
356
353 wait_for_stop(ihost); 357 wait_for_stop(ihost);
354 scic_controller_reset(scic); 358 scic_controller_reset(scic);
359 isci_timer_list_destroy(ihost);
355} 360}
356 361
357static void __iomem *scu_base(struct isci_host *isci_host) 362static void __iomem *scu_base(struct isci_host *isci_host)
@@ -370,8 +375,6 @@ static void __iomem *smu_base(struct isci_host *isci_host)
370 return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; 375 return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
371} 376}
372 377
373#define SCI_MAX_TIMER_COUNT 25
374
375int isci_host_init(struct isci_host *isci_host) 378int isci_host_init(struct isci_host *isci_host)
376{ 379{
377 int err = 0; 380 int err = 0;
@@ -382,11 +385,7 @@ int isci_host_init(struct isci_host *isci_host)
382 union scic_oem_parameters scic_oem_params; 385 union scic_oem_parameters scic_oem_params;
383 union scic_user_parameters scic_user_params; 386 union scic_user_parameters scic_user_params;
384 387
385 INIT_LIST_HEAD(&isci_host->timer_list_struct.timers); 388 isci_timer_list_construct(isci_host);
386 isci_timer_list_construct(
387 &isci_host->timer_list_struct,
388 SCI_MAX_TIMER_COUNT
389 );
390 389
391 controller = scic_controller_alloc(&isci_host->pdev->dev); 390 controller = scic_controller_alloc(&isci_host->pdev->dev);
392 391
@@ -473,7 +472,17 @@ int isci_host_init(struct isci_host *isci_host)
473 } 472 }
474 } 473 }
475 474
475 tasklet_init(&isci_host->completion_tasklet,
476 isci_host_completion_routine, (unsigned long)isci_host);
477
478 INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
479
480 INIT_LIST_HEAD(&isci_host->requests_to_complete);
481 INIT_LIST_HEAD(&isci_host->requests_to_abort);
482
483 spin_lock_irq(&isci_host->scic_lock);
476 status = scic_controller_initialize(isci_host->core_controller); 484 status = scic_controller_initialize(isci_host->core_controller);
485 spin_unlock_irq(&isci_host->scic_lock);
477 if (status != SCI_SUCCESS) { 486 if (status != SCI_SUCCESS) {
478 dev_warn(&isci_host->pdev->dev, 487 dev_warn(&isci_host->pdev->dev,
479 "%s: scic_controller_initialize failed -" 488 "%s: scic_controller_initialize failed -"
@@ -482,17 +491,8 @@ int isci_host_init(struct isci_host *isci_host)
482 return -ENODEV; 491 return -ENODEV;
483 } 492 }
484 493
485 tasklet_init(&isci_host->completion_tasklet,
486 isci_host_completion_routine, (unsigned long)isci_host);
487
488 INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
489
490 INIT_LIST_HEAD(&isci_host->requests_to_complete);
491 INIT_LIST_HEAD(&isci_host->requests_to_abort);
492
493 /* populate mdl with dma memory. scu_mdl_allocate_coherent() */ 494 /* populate mdl with dma memory. scu_mdl_allocate_coherent() */
494 err = isci_host_mdl_allocate_coherent(isci_host); 495 err = isci_host_mdl_allocate_coherent(isci_host);
495
496 if (err) 496 if (err)
497 return err; 497 return err;
498 498
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index b794dfd0819e..ef3e7d1440b0 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -87,7 +87,7 @@ struct isci_host {
87 union scic_oem_parameters oem_parameters; 87 union scic_oem_parameters oem_parameters;
88 88
89 int id; /* unique within a given pci device */ 89 int id; /* unique within a given pci device */
90 struct isci_timer_list timer_list_struct; 90 struct list_head timers;
91 void *core_ctrl_memory; 91 void *core_ctrl_memory;
92 struct dma_pool *dma_pool; 92 struct dma_pool *dma_pool;
93 unsigned int dma_pool_alloc_size; 93 unsigned int dma_pool_alloc_size;
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 6f98f6c74efb..232125eab523 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -475,14 +475,8 @@ int isci_task_execute_tmf(
475 } 475 }
476 476
477 /* Allocate the TMF timeout timer. */ 477 /* Allocate the TMF timeout timer. */
478 tmf->timeout_timer = isci_timer_create(
479 &isci_host->timer_list_struct,
480 isci_host,
481 request,
482 isci_tmf_timeout_cb
483 );
484
485 spin_lock_irqsave(&isci_host->scic_lock, flags); 478 spin_lock_irqsave(&isci_host->scic_lock, flags);
479 tmf->timeout_timer = isci_timer_create(isci_host, request, isci_tmf_timeout_cb);
486 480
487 /* Start the timer. */ 481 /* Start the timer. */
488 if (tmf->timeout_timer) 482 if (tmf->timeout_timer)
@@ -557,9 +551,7 @@ int isci_task_execute_tmf(
557 551
558 /* Clean up the timer if needed. */ 552 /* Clean up the timer if needed. */
559 if (tmf->timeout_timer) { 553 if (tmf->timeout_timer) {
560 isci_timer_stop(tmf->timeout_timer); 554 isci_del_timer(isci_host, tmf->timeout_timer);
561 isci_timer_free(&isci_host->timer_list_struct,
562 tmf->timeout_timer);
563 tmf->timeout_timer = NULL; 555 tmf->timeout_timer = NULL;
564 } 556 }
565 557
@@ -1468,10 +1460,7 @@ void isci_task_request_complete(
1468 1460
1469 /* Manage the timer if it is still running. */ 1461 /* Manage the timer if it is still running. */
1470 if (tmf->timeout_timer) { 1462 if (tmf->timeout_timer) {
1471 1463 isci_del_timer(isci_host, tmf->timeout_timer);
1472 isci_timer_stop(tmf->timeout_timer);
1473 isci_timer_free(&isci_host->timer_list_struct,
1474 tmf->timeout_timer);
1475 tmf->timeout_timer = NULL; 1464 tmf->timeout_timer = NULL;
1476 } 1465 }
1477 1466
diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c
index ca723089ee88..f33eff00dc01 100644
--- a/drivers/scsi/isci/timers.c
+++ b/drivers/scsi/isci/timers.c
@@ -56,96 +56,59 @@
56#include "isci.h" 56#include "isci.h"
57#include "timers.h" 57#include "timers.h"
58 58
59
60/** 59/**
61 * isci_timer_list_construct() - This method contrucst the SCI Timer List 60 * isci_timer_list_construct() - This method contrucst the SCI Timer List
62 * object used by the SCI Module class. The construction process involves 61 * object used by the SCI Module class. The construction process involves
63 * creating isci_timer objects and adding them to the SCI Timer List 62 * creating isci_timer objects and adding them to the SCI Timer List
64 * object's list member. The number of isci_timer objects is determined by 63 * object's list member. The number of isci_timer objects is determined by
65 * the timer_list_size parameter. 64 * the timer_list_size parameter.
66 * @isci_timer_list: This parameter points to the SCI Timer List object being 65 * @ihost: container of the timer list
67 * constructed. The calling routine is responsible for allocating the memory
68 * for isci_timer_list and initializing the timer list_head member of
69 * isci_timer_list.
70 * @timer_list_size: This parameter specifies the number of isci_timer objects
71 * contained by the SCI Timer List. which this timer is to be associated.
72 * 66 *
73 * This method returns an error code indicating sucess or failure. The user 67 * This method returns an error code indicating sucess or failure. The user
74 * should check for possible memory allocation error return otherwise, a zero 68 * should check for possible memory allocation error return otherwise, a zero
75 * indicates success. 69 * indicates success.
76 */ 70 */
77int isci_timer_list_construct( 71int isci_timer_list_construct(struct isci_host *ihost)
78 struct isci_timer_list *isci_timer_list,
79 int timer_list_size)
80{ 72{
81 struct isci_timer *isci_timer; 73 struct isci_timer *itimer;
82 int i; 74 int i, err = 0;
83 int err = 0;
84
85 75
86 for (i = 0; i < timer_list_size; i++) { 76 INIT_LIST_HEAD(&ihost->timers);
87 77 for (i = 0; i < SCI_MAX_TIMER_COUNT; i++) {
88 isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL); 78 itimer = devm_kzalloc(&ihost->pdev->dev, sizeof(*itimer), GFP_KERNEL);
89
90 if (!isci_timer) {
91 79
80 if (!itimer) {
92 err = -ENOMEM; 81 err = -ENOMEM;
93 break; 82 break;
94 } 83 }
95 isci_timer->used = 0; 84 init_timer(&itimer->timer);
96 isci_timer->stopped = 1; 85 itimer->used = 0;
97 isci_timer->parent = isci_timer_list; 86 itimer->stopped = 1;
98 list_add(&isci_timer->node, &isci_timer_list->timers); 87 list_add(&itimer->node, &ihost->timers);
99 } 88 }
100 89
101 return 0; 90 return err;
102
103} 91}
104 92
105
106/** 93/**
107 * isci_timer_list_destroy() - This method destroys the SCI Timer List object 94 * isci_timer_list_destroy() - This method destroys the SCI Timer List object
108 * used by the SCI Module class. The destruction process involves freeing 95 * used by the SCI Module class. The destruction process involves freeing
109 * memory allocated for isci_timer objects on the SCI Timer List object's 96 * memory allocated for isci_timer objects on the SCI Timer List object's
110 * timers list_head member. If any isci_timer objects are mark as "in use", 97 * timers list_head member. If any isci_timer objects are mark as "in use",
111 * they are not freed and the function returns an error code of -EBUSY. 98 * they are not freed and the function returns an error code of -EBUSY.
112 * @isci_timer_list: This parameter points to the SCI Timer List object being 99 * @ihost: container of the list to be destroyed
113 * destroyed.
114 *
115 * This method returns an error code indicating sucess or failure. The user
116 * should check for possible -EBUSY error return, in the event of one or more
117 * isci_timers still "in use", otherwise, a zero indicates success.
118 */ 100 */
119int isci_timer_list_destroy( 101void isci_timer_list_destroy(struct isci_host *ihost)
120 struct isci_timer_list *isci_timer_list)
121{ 102{
122 struct isci_timer *timer, *tmp; 103 struct isci_timer *timer;
123 104 LIST_HEAD(list);
124 list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) {
125 isci_timer_free(isci_timer_list, timer);
126 list_del(&timer->node);
127 kfree(timer);
128 }
129 return 0;
130}
131 105
106 spin_lock_irq(&ihost->scic_lock);
107 list_splice_init(&ihost->timers, &list);
108 spin_unlock_irq(&ihost->scic_lock);
132 109
133 110 list_for_each_entry(timer, &list, node)
134static void isci_timer_restart(struct isci_timer *isci_timer) 111 del_timer_sync(&timer->timer);
135{
136 struct timer_list *timer =
137 &isci_timer->timer;
138 unsigned long timeout;
139
140 dev_dbg(&isci_timer->isci_host->pdev->dev,
141 "%s: isci_timer = %p\n", __func__, isci_timer);
142
143 isci_timer->restart = 0;
144 isci_timer->stopped = 0;
145 timeout = isci_timer->timeout_value;
146 timeout = (timeout * HZ) / 1000;
147 timeout = timeout ? timeout : 1;
148 mod_timer(timer, jiffies + timeout);
149} 112}
150 113
151/** 114/**
@@ -169,7 +132,7 @@ static void isci_timer_restart(struct isci_timer *isci_timer)
169static void timer_function(unsigned long data) 132static void timer_function(unsigned long data)
170{ 133{
171 134
172 struct isci_timer *timer = (struct isci_timer *)data; 135 struct isci_timer *timer = (struct isci_timer *)data;
173 struct isci_host *isci_host = timer->isci_host; 136 struct isci_host *isci_host = timer->isci_host;
174 unsigned long flags; 137 unsigned long flags;
175 138
@@ -185,89 +148,66 @@ static void timer_function(unsigned long data)
185 148
186 if (!timer->stopped) { 149 if (!timer->stopped) {
187 timer->stopped = 1; 150 timer->stopped = 1;
188 timer->timer_callback(timer->cookie); 151 timer->timer_callback(timer->cb_param);
189
190 if (timer->restart)
191 isci_timer_restart(timer);
192 } 152 }
193 153
194 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 154 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
195} 155}
196 156
197 157
198struct isci_timer *isci_timer_create( 158struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param,
199 struct isci_timer_list *isci_timer_list, 159 void (*timer_callback)(void *))
200 struct isci_host *isci_host,
201 void *cookie,
202 void (*timer_callback)(void *))
203{ 160{
204
205 struct timer_list *timer; 161 struct timer_list *timer;
206 struct isci_timer *isci_timer; 162 struct isci_timer *isci_timer;
207 struct list_head *timer_list = 163 struct list_head *list = &ihost->timers;
208 &isci_timer_list->timers;
209 unsigned long flags;
210 164
211 spin_lock_irqsave(&isci_host->scic_lock, flags); 165 WARN_ONCE(!spin_is_locked(&ihost->scic_lock),
166 "%s: unlocked!\n", __func__);
212 167
213 if (list_empty(timer_list)) { 168 if (WARN_ONCE(list_empty(list), "%s: timer pool empty\n", __func__))
214 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
215 return NULL; 169 return NULL;
216 }
217 170
218 isci_timer = list_entry(timer_list->next, struct isci_timer, node); 171 isci_timer = list_entry(list->next, struct isci_timer, node);
219 172
220 if (isci_timer->used) {
221 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
222 return NULL;
223 }
224 isci_timer->used = 1; 173 isci_timer->used = 1;
225 isci_timer->stopped = 1; 174 isci_timer->stopped = 1;
226 list_move_tail(&isci_timer->node, timer_list); 175 /* FIXME: what!? we recycle the timer, rather than take it off
227 176 * the free list?
228 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 177 */
178 list_move_tail(&isci_timer->node, list);
229 179
230 timer = &isci_timer->timer; 180 timer = &isci_timer->timer;
231 timer->data = (unsigned long)isci_timer; 181 timer->data = (unsigned long)isci_timer;
232 timer->function = timer_function; 182 timer->function = timer_function;
233 isci_timer->cookie = cookie; 183 isci_timer->cb_param = cb_param;
234 isci_timer->timer_callback = timer_callback; 184 isci_timer->timer_callback = timer_callback;
235 isci_timer->isci_host = isci_host; 185 isci_timer->isci_host = ihost;
236 186
237 dev_dbg(&isci_host->pdev->dev, 187 dev_dbg(&ihost->pdev->dev,
238 "%s: isci_timer = %p\n", __func__, isci_timer); 188 "%s: isci_timer = %p\n", __func__, isci_timer);
239 189
240 return isci_timer; 190 return isci_timer;
241} 191}
242 192
243/** 193/* isci_del_timer() - This method frees the isci_timer, marking it "free to
244 * isci_timer_free() - This method frees the isci_timer, marking it "free to
245 * use", then places its back at the head of the timers list for the SCI 194 * use", then places its back at the head of the timers list for the SCI
246 * Timer List object specified. 195 * Timer List object specified.
247 * @isci_timer_list: This parameter points to the SCI Timer List from which the
248 * timer is reserved.
249 * @isci_timer: This parameter specifies the timer to be freed.
250 *
251 */ 196 */
252void isci_timer_free( 197void isci_del_timer(struct isci_host *ihost, struct isci_timer *isci_timer)
253 struct isci_timer_list *isci_timer_list,
254 struct isci_timer *isci_timer)
255{ 198{
256 struct list_head *timer_list = &isci_timer_list->timers; 199 struct list_head *list = &ihost->timers;
200
201 WARN_ONCE(!spin_is_locked(&ihost->scic_lock),
202 "%s unlocked!\n", __func__);
257 203
258 dev_dbg(&isci_timer->isci_host->pdev->dev, 204 dev_dbg(&isci_timer->isci_host->pdev->dev,
259 "%s: isci_timer = %p\n", __func__, isci_timer); 205 "%s: isci_timer = %p\n", __func__, isci_timer);
260 206
261 if (list_empty(timer_list))
262 return;
263
264 isci_timer->used = 0; 207 isci_timer->used = 0;
265 list_move(&isci_timer->node, timer_list); 208 list_move(&isci_timer->node, list);
266 209 del_timer(&isci_timer->timer);
267 if (!isci_timer->stopped) { 210 isci_timer->stopped = 1;
268 del_timer(&isci_timer->timer);
269 isci_timer->stopped = 1;
270 }
271} 211}
272 212
273/** 213/**
@@ -278,26 +218,15 @@ void isci_timer_free(
278 * the associated callback function will be called. 218 * the associated callback function will be called.
279 * 219 *
280 */ 220 */
281void isci_timer_start( 221void isci_timer_start(struct isci_timer *isci_timer, unsigned long tmo)
282 struct isci_timer *isci_timer,
283 unsigned long timeout)
284{ 222{
285 struct timer_list *timer = &isci_timer->timer; 223 struct timer_list *timer = &isci_timer->timer;
286 224
287 dev_dbg(&isci_timer->isci_host->pdev->dev, 225 dev_dbg(&isci_timer->isci_host->pdev->dev,
288 "%s: isci_timer = %p\n", __func__, isci_timer); 226 "%s: isci_timer = %p\n", __func__, isci_timer);
289 227
290 isci_timer->timeout_value = timeout;
291 init_timer(timer);
292 timeout = (timeout * HZ) / 1000;
293 timeout = timeout ? timeout : 1;
294
295 timer->expires = jiffies + timeout;
296 timer->data = (unsigned long)isci_timer;
297 timer->function = timer_function;
298 isci_timer->stopped = 0; 228 isci_timer->stopped = 0;
299 isci_timer->restart = 0; 229 mod_timer(timer, jiffies + msecs_to_jiffies(tmo));
300 add_timer(timer);
301} 230}
302 231
303/** 232/**
@@ -310,10 +239,6 @@ void isci_timer_stop(struct isci_timer *isci_timer)
310 dev_dbg(&isci_timer->isci_host->pdev->dev, 239 dev_dbg(&isci_timer->isci_host->pdev->dev,
311 "%s: isci_timer = %p\n", __func__, isci_timer); 240 "%s: isci_timer = %p\n", __func__, isci_timer);
312 241
313 if (isci_timer->stopped)
314 return;
315
316 isci_timer->stopped = 1; 242 isci_timer->stopped = 1;
317
318 del_timer(&isci_timer->timer); 243 del_timer(&isci_timer->timer);
319} 244}
diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h
index ca5c2159a1c2..8d8a892ad7f2 100644
--- a/drivers/scsi/isci/timers.h
+++ b/drivers/scsi/isci/timers.h
@@ -59,68 +59,30 @@
59#include <linux/timer.h> 59#include <linux/timer.h>
60#include <linux/types.h> 60#include <linux/types.h>
61 61
62/*************************************************** 62#define SCI_MAX_TIMER_COUNT 25
63 * isci_timer
64 ***************************************************
65 */
66/**
67 * struct isci_timer_list - This class is the container for all isci_timer
68 * objects
69 *
70 *
71 */
72struct isci_timer_list {
73
74 struct list_head timers;
75};
76 63
77/** 64/**
78 * struct isci_timer - This class represents the timer object used by SCIC. It 65 * struct isci_timer - This class represents the timer object used by SCIC. It
79 * wraps the Linux timer_list object. 66 * wraps the Linux timer_list object, and (TODO) should be removed in favor
80 * 67 * of a delayed-workqueue style interface with simpler locking
81 * 68 *
82 */ 69 */
83struct isci_timer { 70struct isci_timer {
84 int used; 71 int used;
85 int stopped; 72 int stopped;
86 int restart; 73 void *cb_param;
87 int timeout_value;
88 void *cookie;
89 void (*timer_callback)(void *); 74 void (*timer_callback)(void *);
90 struct list_head node; 75 struct list_head node;
91 struct timer_list timer; 76 struct timer_list timer;
92 struct isci_timer_list *parent;
93 struct isci_host *isci_host; 77 struct isci_host *isci_host;
94}; 78};
95 79
96#define to_isci_timer(t) \ 80int isci_timer_list_construct(struct isci_host *ihost);
97 container_of(t, struct isci_timer, timer); 81void isci_timer_list_destroy(struct isci_host *ihost);
98 82struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param,
99int isci_timer_list_construct( 83 void (*timer_callback)(void *));
100 struct isci_timer_list *isci_timer_list, 84void isci_del_timer(struct isci_host *ihost, struct isci_timer *itimer);
101 int timer_list_size); 85void isci_timer_start(struct isci_timer *isci_timer, unsigned long timeout);
102 86void isci_timer_stop(struct isci_timer *isci_timer);
103
104int isci_timer_list_destroy(
105 struct isci_timer_list *isci_timer_list);
106
107struct isci_timer *isci_timer_create(
108 struct isci_timer_list *isci_timer_list,
109 struct isci_host *isci_host,
110 void *cookie,
111 void (*timer_callback)(void *));
112
113void isci_timer_free(
114 struct isci_timer_list *isci_timer_list,
115 struct isci_timer *isci_timer);
116
117void isci_timer_start(
118 struct isci_timer *isci_timer,
119 unsigned long timeout);
120
121void isci_timer_stop(
122 struct isci_timer *isci_timer);
123
124 87
125#endif /* !defined (_SCI_TIMER_H_) */ 88#endif /* !defined (_SCI_TIMER_H_) */
126