diff options
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio-tx.c')
-rw-r--r-- | drivers/net/wimax/i2400m/sdio-tx.c | 35 |
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 | ||
150 | void i2400ms_tx_release(struct i2400ms *i2400ms) | 163 | void 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 | } |