aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/driver.c
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-07 08:43:10 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 02:56:19 -0400
commita0beba21c3e2dff9a31739f1660ba3ff8c7150a7 (patch)
treec38d559fd600274c4526f835c2b614a55df5d4c6 /drivers/net/wimax/i2400m/driver.c
parentaf77dfa7811cd4e533003a9e7e9bf27dece96c6d (diff)
wimax/i2400m: queue device's report until the driver is ready for them
The i2400m might start sending reports to the driver before it is done setting up all the infrastructure needed for handling them. Currently we were just dropping them when the driver wasn't ready and that is bad in certain situations, as the sync between the driver's idea of the device's state and the device's state dissapears. This changes that by implementing a queue for handling reports. Incoming reports are appended to it and a workstruct is woken to process the list of queued reports. When the device is not yet ready to handle them, the workstruct is not woken, but at soon as the device becomes ready again, the queue is processed. As a consequence of this, i2400m_queue_work() is no longer used, and thus removed. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m/driver.c')
-rw-r--r--drivers/net/wimax/i2400m/driver.c74
1 files changed, 4 insertions, 70 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 9b78e059563d..42102ebad1ad 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -128,76 +128,6 @@ struct i2400m_work *__i2400m_work_setup(
128} 128}
129 129
130 130
131/**
132 * i2400m_queue_work - schedule work on a i2400m's queue
133 *
134 * @i2400m: device descriptor
135 *
136 * @fn: function to run to execute work. It gets passed a 'struct
137 * work_struct' that is wrapped in a 'struct i2400m_work'. Once
138 * done, you have to (1) i2400m_put(i2400m_work->i2400m) and then
139 * (2) kfree(i2400m_work).
140 *
141 * @gfp_flags: GFP flags for memory allocation.
142 *
143 * @pl: pointer to a payload buffer that you want to pass to the _work
144 * function. Use this to pack (for example) a struct with extra
145 * arguments.
146 *
147 * @pl_size: size of the payload buffer.
148 *
149 * We do this quite often, so this just saves typing; allocate a
150 * wrapper for a i2400m, get a ref to it, pack arguments and launch
151 * the work.
152 *
153 * A usual workflow is:
154 *
155 * struct my_work_args {
156 * void *something;
157 * int whatever;
158 * };
159 * ...
160 *
161 * struct my_work_args my_args = {
162 * .something = FOO,
163 * .whaetever = BLAH
164 * };
165 * i2400m_queue_work(i2400m, 1, my_work_function, GFP_KERNEL,
166 * &args, sizeof(args))
167 *
168 * And now the work function can unpack the arguments and call the
169 * real function (or do the job itself):
170 *
171 * static
172 * void my_work_fn((struct work_struct *ws)
173 * {
174 * struct i2400m_work *iw =
175 * container_of(ws, struct i2400m_work, ws);
176 * struct my_work_args *my_args = (void *) iw->pl;
177 *
178 * my_work(iw->i2400m, my_args->something, my_args->whatevert);
179 * }
180 */
181int i2400m_queue_work(struct i2400m *i2400m,
182 void (*fn)(struct work_struct *), gfp_t gfp_flags,
183 const void *pl, size_t pl_size)
184{
185 int result;
186 struct i2400m_work *iw;
187
188 BUG_ON(i2400m->work_queue == NULL);
189 result = -ENOMEM;
190 iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size);
191 if (iw != NULL) {
192 result = queue_work(i2400m->work_queue, &iw->ws);
193 if (WARN_ON(result == 0))
194 result = -ENXIO;
195 }
196 return result;
197}
198EXPORT_SYMBOL_GPL(i2400m_queue_work);
199
200
201/* 131/*
202 * Schedule i2400m's specific work on the system's queue. 132 * Schedule i2400m's specific work on the system's queue.
203 * 133 *
@@ -459,6 +389,8 @@ retry:
459 goto error_bus_dev_start; 389 goto error_bus_dev_start;
460 i2400m->ready = 1; 390 i2400m->ready = 1;
461 wmb(); /* see i2400m->ready's documentation */ 391 wmb(); /* see i2400m->ready's documentation */
392 /* process pending reports from the device */
393 queue_work(i2400m->work_queue, &i2400m->rx_report_ws);
462 result = i2400m_firmware_check(i2400m); /* fw versions ok? */ 394 result = i2400m_firmware_check(i2400m); /* fw versions ok? */
463 if (result < 0) 395 if (result < 0)
464 goto error_fw_check; 396 goto error_fw_check;
@@ -868,6 +800,8 @@ void i2400m_init(struct i2400m *i2400m)
868 spin_lock_init(&i2400m->rx_lock); 800 spin_lock_init(&i2400m->rx_lock);
869 i2400m->rx_pl_min = UINT_MAX; 801 i2400m->rx_pl_min = UINT_MAX;
870 i2400m->rx_size_min = UINT_MAX; 802 i2400m->rx_size_min = UINT_MAX;
803 INIT_LIST_HEAD(&i2400m->rx_reports);
804 INIT_WORK(&i2400m->rx_report_ws, i2400m_report_hook_work);
871 805
872 mutex_init(&i2400m->msg_mutex); 806 mutex_init(&i2400m->msg_mutex);
873 init_completion(&i2400m->msg_completion); 807 init_completion(&i2400m->msg_completion);