diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2009-03-25 23:38:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:54:27 -0400 |
commit | 4f5cab969bdbec1ab0c5b690282372b4978123ac (patch) | |
tree | 86e829b073bf47b1dcd01abfe13d9e668dd49a8c | |
parent | 684d6b360222f31b6b9be9a63aa5c6ed5674c890 (diff) |
p54spi: fix p54spi_tx_frame DMA transfer initiation and skb cleanup
p54spi_tx_frame wasn't waiting for HOST_ALLOWED in SPI_ADRS_DMA_WRITE_CTRL.
This resulted in frequent 'WR_READY timeout' on beacon resubmission.
Also don't free skb on error path, as it gets freed on p54spi_wq_tx.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/p54/p54spi.c | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index bed894ae04b5..f8af09610180 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -179,6 +179,25 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) | |||
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base, | ||
183 | const void *buf, size_t len) | ||
184 | { | ||
185 | p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, | ||
186 | cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); | ||
187 | |||
188 | if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, | ||
189 | cpu_to_le32(HOST_ALLOWED)) == 0) { | ||
190 | dev_err(&priv->spi->dev, "spi_write_dma not allowed " | ||
191 | "to DMA write."); | ||
192 | return -EAGAIN; | ||
193 | } | ||
194 | |||
195 | p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len)); | ||
196 | p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base); | ||
197 | p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
182 | static int p54spi_request_firmware(struct ieee80211_hw *dev) | 201 | static int p54spi_request_firmware(struct ieee80211_hw *dev) |
183 | { | 202 | { |
184 | struct p54s_priv *priv = dev->priv; | 203 | struct p54s_priv *priv = dev->priv; |
@@ -254,24 +273,11 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) | |||
254 | while (fw_len > 0) { | 273 | while (fw_len > 0) { |
255 | _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); | 274 | _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); |
256 | 275 | ||
257 | p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, | 276 | err = p54spi_spi_write_dma(priv, cpu_to_le32( |
258 | cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); | 277 | ISL38XX_DEV_FIRMWARE_ADDR + offset), |
259 | 278 | (fw + offset), _fw_len); | |
260 | if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, | 279 | if (err < 0) |
261 | cpu_to_le32(HOST_ALLOWED)) == 0) { | ||
262 | dev_err(&priv->spi->dev, "fw_upload not allowed " | ||
263 | "to DMA write."); | ||
264 | err = -EAGAIN; | ||
265 | goto out; | 280 | goto out; |
266 | } | ||
267 | |||
268 | p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, | ||
269 | cpu_to_le16(_fw_len)); | ||
270 | p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, cpu_to_le32( | ||
271 | ISL38XX_DEV_FIRMWARE_ADDR + offset)); | ||
272 | |||
273 | p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, | ||
274 | (fw + offset), _fw_len); | ||
275 | 281 | ||
276 | fw_len -= _fw_len; | 282 | fw_len -= _fw_len; |
277 | offset += _fw_len; | 283 | offset += _fw_len; |
@@ -418,27 +424,21 @@ static irqreturn_t p54spi_interrupt(int irq, void *config) | |||
418 | static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) | 424 | static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) |
419 | { | 425 | { |
420 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; | 426 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; |
421 | struct p54s_dma_regs dma_regs; | ||
422 | unsigned long timeout; | 427 | unsigned long timeout; |
423 | int ret = 0; | 428 | int ret = 0; |
424 | u32 ints; | 429 | u32 ints; |
425 | 430 | ||
426 | p54spi_wakeup(priv); | 431 | p54spi_wakeup(priv); |
427 | 432 | ||
428 | dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE); | 433 | ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len); |
429 | dma_regs.len = cpu_to_le16(skb->len); | 434 | if (ret < 0) |
430 | dma_regs.addr = hdr->req_id; | 435 | goto out; |
431 | |||
432 | p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, | ||
433 | sizeof(dma_regs)); | ||
434 | |||
435 | p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len); | ||
436 | 436 | ||
437 | timeout = jiffies + 2 * HZ; | 437 | timeout = jiffies + 2 * HZ; |
438 | ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); | 438 | ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); |
439 | while (!(ints & SPI_HOST_INT_WR_READY)) { | 439 | while (!(ints & SPI_HOST_INT_WR_READY)) { |
440 | if (time_after(jiffies, timeout)) { | 440 | if (time_after(jiffies, timeout)) { |
441 | dev_err(&priv->spi->dev, "WR_READY timeout"); | 441 | dev_err(&priv->spi->dev, "WR_READY timeout\n"); |
442 | ret = -1; | 442 | ret = -1; |
443 | goto out; | 443 | goto out; |
444 | } | 444 | } |
@@ -448,9 +448,9 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) | |||
448 | p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); | 448 | p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); |
449 | p54spi_sleep(priv); | 449 | p54spi_sleep(priv); |
450 | 450 | ||
451 | out: | ||
452 | if (FREE_AFTER_TX(skb)) | 451 | if (FREE_AFTER_TX(skb)) |
453 | p54_free_skb(priv->hw, skb); | 452 | p54_free_skb(priv->hw, skb); |
453 | out: | ||
454 | return ret; | 454 | return ret; |
455 | } | 455 | } |
456 | 456 | ||