aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/sdio-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio-tx.c')
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
index de66d068c9cb..b53cd1c80e3e 100644
--- a/drivers/net/wimax/i2400m/sdio-tx.c
+++ b/drivers/net/wimax/i2400m/sdio-tx.c
@@ -98,6 +98,10 @@ void i2400ms_tx_submit(struct work_struct *ws)
98 tx_msg_size, result); 98 tx_msg_size, result);
99 } 99 }
100 100
101 if (result == -ETIMEDOUT) {
102 i2400m_error_recovery(i2400m);
103 break;
104 }
101 d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size); 105 d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
102 } 106 }
103 107
@@ -114,13 +118,17 @@ void i2400ms_bus_tx_kick(struct i2400m *i2400m)
114{ 118{
115 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); 119 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
116 struct device *dev = &i2400ms->func->dev; 120 struct device *dev = &i2400ms->func->dev;
121 unsigned long flags;
117 122
118 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m); 123 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
119 124
120 /* schedule tx work, this is because tx may block, therefore 125 /* schedule tx work, this is because tx may block, therefore
121 * it has to run in a thread context. 126 * it has to run in a thread context.
122 */ 127 */
123 queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker); 128 spin_lock_irqsave(&i2400m->tx_lock, flags);
129 if (i2400ms->tx_workqueue != NULL)
130 queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
131 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
124 132
125 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); 133 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
126} 134}
@@ -130,27 +138,40 @@ int i2400ms_tx_setup(struct i2400ms *i2400ms)
130 int result; 138 int result;
131 struct device *dev = &i2400ms->func->dev; 139 struct device *dev = &i2400ms->func->dev;
132 struct i2400m *i2400m = &i2400ms->i2400m; 140 struct i2400m *i2400m = &i2400ms->i2400m;
141 struct workqueue_struct *tx_workqueue;
142 unsigned long flags;
133 143
134 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); 144 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
135 145
136 INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit); 146 INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
137 snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name), 147 snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
138 "%s-tx", i2400m->wimax_dev.name); 148 "%s-tx", i2400m->wimax_dev.name);
139 i2400ms->tx_workqueue = 149 tx_workqueue =
140 create_singlethread_workqueue(i2400ms->tx_wq_name); 150 create_singlethread_workqueue(i2400ms->tx_wq_name);
141 if (NULL == i2400ms->tx_workqueue) { 151 if (tx_workqueue == NULL) {
142 dev_err(dev, "TX: failed to create workqueue\n"); 152 dev_err(dev, "TX: failed to create workqueue\n");
143 result = -ENOMEM; 153 result = -ENOMEM;
144 } else 154 } else
145 result = 0; 155 result = 0;
156 spin_lock_irqsave(&i2400m->tx_lock, flags);
157 i2400ms->tx_workqueue = tx_workqueue;
158 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
146 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); 159 d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
147 return result; 160 return result;
148} 161}
149 162
150void i2400ms_tx_release(struct i2400ms *i2400ms) 163void i2400ms_tx_release(struct i2400ms *i2400ms)
151{ 164{
152 if (i2400ms->tx_workqueue) { 165 struct i2400m *i2400m = &i2400ms->i2400m;
153 destroy_workqueue(i2400ms->tx_workqueue); 166 struct workqueue_struct *tx_workqueue;
154 i2400ms->tx_workqueue = NULL; 167 unsigned long flags;
155 } 168
169 tx_workqueue = i2400ms->tx_workqueue;
170
171 spin_lock_irqsave(&i2400m->tx_lock, flags);
172 i2400ms->tx_workqueue = NULL;
173 spin_unlock_irqrestore(&i2400m->tx_lock, flags);
174
175 if (tx_workqueue)
176 destroy_workqueue(tx_workqueue);
156} 177}