aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54spi.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
committerDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
commitbbb20089a3275a19e475dbc21320c3742e3ca423 (patch)
tree216fdc1cbef450ca688135c5b8969169482d9a48 /drivers/net/wireless/p54/p54spi.c
parent3e48e656903e9fd8bc805c6a2c4264d7808d315b (diff)
parent657a77fa7284d8ae28dfa48f1dc5d919bf5b2843 (diff)
Merge branch 'dmaengine' into async-tx-next
Conflicts: crypto/async_tx/async_xor.c drivers/dma/ioat/dma_v2.h drivers/dma/ioat/pci.c drivers/md/raid5.c
Diffstat (limited to 'drivers/net/wireless/p54/p54spi.c')
-rw-r--r--drivers/net/wireless/p54/p54spi.c175
1 files changed, 89 insertions, 86 deletions
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index d1fe577de3d4..83116baeb110 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -96,7 +96,7 @@ static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
96 spi_message_add_tail(&t[0], &m); 96 spi_message_add_tail(&t[0], &m);
97 97
98 t[1].tx_buf = buf; 98 t[1].tx_buf = buf;
99 t[1].len = len; 99 t[1].len = len & ~1;
100 spi_message_add_tail(&t[1], &m); 100 spi_message_add_tail(&t[1], &m);
101 101
102 if (len % 2) { 102 if (len % 2) {
@@ -167,15 +167,31 @@ static const struct p54spi_spi_reg p54spi_registers_array[] =
167static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) 167static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
168{ 168{
169 int i; 169 int i;
170 __le32 buffer;
171 170
172 for (i = 0; i < 2000; i++) { 171 for (i = 0; i < 2000; i++) {
173 p54spi_spi_read(priv, reg, &buffer, sizeof(buffer)); 172 __le32 buffer = p54spi_read32(priv, reg);
174 if (buffer == bits) 173 if ((buffer & bits) == bits)
175 return 1; 174 return 1;
175 }
176 return 0;
177}
176 178
177 msleep(1); 179static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
180 const void *buf, size_t len)
181{
182 if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
183 cpu_to_le32(HOST_ALLOWED))) {
184 dev_err(&priv->spi->dev, "spi_write_dma not allowed "
185 "to DMA write.\n");
186 return -EAGAIN;
178 } 187 }
188
189 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
190 cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
191
192 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len));
193 p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base);
194 p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len);
179 return 0; 195 return 0;
180} 196}
181 197
@@ -228,8 +244,15 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev)
228static int p54spi_upload_firmware(struct ieee80211_hw *dev) 244static int p54spi_upload_firmware(struct ieee80211_hw *dev)
229{ 245{
230 struct p54s_priv *priv = dev->priv; 246 struct p54s_priv *priv = dev->priv;
231 unsigned long fw_len, fw_addr; 247 unsigned long fw_len, _fw_len;
232 long _fw_len; 248 unsigned int offset = 0;
249 int err = 0;
250 u8 *fw;
251
252 fw_len = priv->firmware->size;
253 fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL);
254 if (!fw)
255 return -ENOMEM;
233 256
234 /* stop the device */ 257 /* stop the device */
235 p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( 258 p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
@@ -244,36 +267,17 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev)
244 267
245 msleep(TARGET_BOOT_SLEEP); 268 msleep(TARGET_BOOT_SLEEP);
246 269
247 fw_addr = ISL38XX_DEV_FIRMWARE_ADDR;
248 fw_len = priv->firmware->size;
249
250 while (fw_len > 0) { 270 while (fw_len > 0) {
251 _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); 271 _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE);
252 272
253 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, 273 err = p54spi_spi_write_dma(priv, cpu_to_le32(
254 cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); 274 ISL38XX_DEV_FIRMWARE_ADDR + offset),
255 275 (fw + offset), _fw_len);
256 if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, 276 if (err < 0)
257 cpu_to_le32(HOST_ALLOWED)) == 0) { 277 goto out;
258 dev_err(&priv->spi->dev, "fw_upload not allowed "
259 "to DMA write.");
260 return -EAGAIN;
261 }
262
263 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN,
264 cpu_to_le16(_fw_len));
265 p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE,
266 cpu_to_le32(fw_addr));
267
268 p54spi_spi_write(priv, SPI_ADRS_DMA_DATA,
269 &priv->firmware->data, _fw_len);
270 278
271 fw_len -= _fw_len; 279 fw_len -= _fw_len;
272 fw_addr += _fw_len; 280 offset += _fw_len;
273
274 /* FIXME: I think this doesn't work if firmware is large,
275 * this loop goes to second round. fw->data is not
276 * increased at all! */
277 } 281 }
278 282
279 BUG_ON(fw_len != 0); 283 BUG_ON(fw_len != 0);
@@ -292,7 +296,10 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev)
292 p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( 296 p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
293 SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT)); 297 SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT));
294 msleep(TARGET_BOOT_SLEEP); 298 msleep(TARGET_BOOT_SLEEP);
295 return 0; 299
300out:
301 kfree(fw);
302 return err;
296} 303}
297 304
298static void p54spi_power_off(struct p54s_priv *priv) 305static void p54spi_power_off(struct p54s_priv *priv)
@@ -318,29 +325,21 @@ static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val)
318 p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val)); 325 p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val));
319} 326}
320 327
321static void p54spi_wakeup(struct p54s_priv *priv) 328static int p54spi_wakeup(struct p54s_priv *priv)
322{ 329{
323 unsigned long timeout;
324 u32 ints;
325
326 /* wake the chip */ 330 /* wake the chip */
327 p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, 331 p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
328 cpu_to_le32(SPI_TARGET_INT_WAKEUP)); 332 cpu_to_le32(SPI_TARGET_INT_WAKEUP));
329 333
330 /* And wait for the READY interrupt */ 334 /* And wait for the READY interrupt */
331 timeout = jiffies + HZ; 335 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
332 336 cpu_to_le32(SPI_HOST_INT_READY))) {
333 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); 337 dev_err(&priv->spi->dev, "INT_READY timeout\n");
334 while (!(ints & SPI_HOST_INT_READY)) { 338 return -EBUSY;
335 if (time_after(jiffies, timeout))
336 goto out;
337 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
338 } 339 }
339 340
340 p54spi_int_ack(priv, SPI_HOST_INT_READY); 341 p54spi_int_ack(priv, SPI_HOST_INT_READY);
341 342 return 0;
342out:
343 return;
344} 343}
345 344
346static inline void p54spi_sleep(struct p54s_priv *priv) 345static inline void p54spi_sleep(struct p54s_priv *priv)
@@ -372,27 +371,48 @@ static int p54spi_rx(struct p54s_priv *priv)
372{ 371{
373 struct sk_buff *skb; 372 struct sk_buff *skb;
374 u16 len; 373 u16 len;
374 u16 rx_head[2];
375#define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16))
375 376
376 p54spi_wakeup(priv); 377 if (p54spi_wakeup(priv) < 0)
377 378 return -EBUSY;
378 /* dummy read to flush SPI DMA controller bug */
379 p54spi_read16(priv, SPI_ADRS_GEN_PURP_1);
380 379
381 len = p54spi_read16(priv, SPI_ADRS_DMA_DATA); 380 /* Read data size and first data word in one SPI transaction
381 * This is workaround for firmware/DMA bug,
382 * when first data word gets lost under high load.
383 */
384 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head));
385 len = rx_head[0];
382 386
383 if (len == 0) { 387 if (len == 0) {
384 dev_err(&priv->spi->dev, "rx request of zero bytes"); 388 p54spi_sleep(priv);
389 dev_err(&priv->spi->dev, "rx request of zero bytes\n");
385 return 0; 390 return 0;
386 } 391 }
387 392
388 skb = dev_alloc_skb(len); 393 /* Firmware may insert up to 4 padding bytes after the lmac header,
394 * but it does not amend the size of SPI data transfer.
395 * Such packets has correct data size in header, thus referencing
396 * past the end of allocated skb. Reserve extra 4 bytes for this case */
397 skb = dev_alloc_skb(len + 4);
389 if (!skb) { 398 if (!skb) {
399 p54spi_sleep(priv);
390 dev_err(&priv->spi->dev, "could not alloc skb"); 400 dev_err(&priv->spi->dev, "could not alloc skb");
391 return 0; 401 return -ENOMEM;
392 } 402 }
393 403
394 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); 404 if (len <= READAHEAD_SZ) {
405 memcpy(skb_put(skb, len), rx_head + 1, len);
406 } else {
407 memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ);
408 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA,
409 skb_put(skb, len - READAHEAD_SZ),
410 len - READAHEAD_SZ);
411 }
395 p54spi_sleep(priv); 412 p54spi_sleep(priv);
413 /* Put additional bytes to compensate for the possible
414 * alignment-caused truncation */
415 skb_put(skb, 4);
396 416
397 if (p54_rx(priv->hw, skb) == 0) 417 if (p54_rx(priv->hw, skb) == 0)
398 dev_kfree_skb(skb); 418 dev_kfree_skb(skb);
@@ -414,39 +434,28 @@ static irqreturn_t p54spi_interrupt(int irq, void *config)
414static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) 434static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
415{ 435{
416 struct p54_hdr *hdr = (struct p54_hdr *) skb->data; 436 struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
417 struct p54s_dma_regs dma_regs;
418 unsigned long timeout;
419 int ret = 0; 437 int ret = 0;
420 u32 ints;
421
422 p54spi_wakeup(priv);
423 438
424 dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE); 439 if (p54spi_wakeup(priv) < 0)
425 dma_regs.len = cpu_to_le16(skb->len); 440 return -EBUSY;
426 dma_regs.addr = hdr->req_id;
427 441
428 p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, 442 ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len);
429 sizeof(dma_regs)); 443 if (ret < 0)
430 444 goto out;
431 p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len);
432 445
433 timeout = jiffies + 2 * HZ; 446 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
434 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); 447 cpu_to_le32(SPI_HOST_INT_WR_READY))) {
435 while (!(ints & SPI_HOST_INT_WR_READY)) { 448 dev_err(&priv->spi->dev, "WR_READY timeout\n");
436 if (time_after(jiffies, timeout)) { 449 ret = -EAGAIN;
437 dev_err(&priv->spi->dev, "WR_READY timeout"); 450 goto out;
438 ret = -1;
439 goto out;
440 }
441 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
442 } 451 }
443 452
444 p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); 453 p54spi_int_ack(priv, SPI_HOST_INT_WR_READY);
445 p54spi_sleep(priv);
446 454
447out:
448 if (FREE_AFTER_TX(skb)) 455 if (FREE_AFTER_TX(skb))
449 p54_free_skb(priv->hw, skb); 456 p54_free_skb(priv->hw, skb);
457out:
458 p54spi_sleep(priv);
450 return ret; 459 return ret;
451} 460}
452 461
@@ -516,8 +525,7 @@ static void p54spi_work(struct work_struct *work)
516 525
517 mutex_lock(&priv->mutex); 526 mutex_lock(&priv->mutex);
518 527
519 if (priv->fw_state == FW_STATE_OFF && 528 if (priv->fw_state == FW_STATE_OFF)
520 priv->fw_state == FW_STATE_RESET)
521 goto out; 529 goto out;
522 530
523 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); 531 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
@@ -544,11 +552,6 @@ static void p54spi_work(struct work_struct *work)
544 } 552 }
545 553
546 ret = p54spi_wq_tx(priv); 554 ret = p54spi_wq_tx(priv);
547 if (ret < 0)
548 goto out;
549
550 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
551
552out: 555out:
553 mutex_unlock(&priv->mutex); 556 mutex_unlock(&priv->mutex);
554} 557}