Merge changes I05a7d9c4,Ib568df71,Ibd79e983 into msm-3.0
* changes:
msm: bam_dmux: Prevent UL Powerdown due to modem flow control
msm: bam_dmux: cleanup ioremap_nocache() handle during error handling
msm: bam_dmux: extend tx list lock around sps_transfer_one()
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 0e4c756..d001282 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -63,6 +63,7 @@
static uint32_t bam_dmux_write_cpy_cnt;
static uint32_t bam_dmux_write_cpy_bytes;
static uint32_t bam_dmux_tx_sps_failure_cnt;
+static uint32_t bam_dmux_tx_stall_cnt;
#define DBG(x...) do { \
if (msm_bam_dmux_debug_enable) \
@@ -96,12 +97,17 @@
bam_dmux_tx_sps_failure_cnt++; \
} while (0)
+#define DBG_INC_TX_STALL_CNT() do { \
+ bam_dmux_tx_stall_cnt++; \
+} while (0)
+
#else
#define DBG(x...) do { } while (0)
#define DBG_INC_READ_CNT(x...) do { } while (0)
#define DBG_INC_WRITE_CNT(x...) do { } while (0)
#define DBG_INC_WRITE_CPY(x...) do { } while (0)
#define DBG_INC_TX_SPS_FAILURE_CNT() do { } while (0)
+#define DBG_INC_TX_STALL_CNT() do { } while (0)
#endif
struct bam_ch_info {
@@ -551,16 +557,16 @@
INIT_WORK(&pkt->work, bam_mux_write_done);
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
kfree(pkt);
+ } else {
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
}
ul_packet_written = 1;
@@ -718,12 +724,10 @@
INIT_WORK(&pkt->work, bam_mux_write_done);
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
@@ -731,6 +735,7 @@
if (new_skb)
dev_kfree_skb_any(new_skb);
} else {
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
spin_lock_irqsave(&bam_ch[id].lock, flags);
bam_ch[id].num_tx_pkts++;
spin_unlock_irqrestore(&bam_ch[id].lock, flags);
@@ -1124,10 +1129,12 @@
i += scnprintf(buf + i, max - i,
"skb copy cnt: %u\n"
"skb copy bytes: %u\n"
- "sps tx failures: %u\n",
+ "sps tx failures: %u\n"
+ "sps tx stalls: %u\n",
bam_dmux_write_cpy_cnt,
bam_dmux_write_cpy_bytes,
- bam_dmux_tx_sps_failure_cnt
+ bam_dmux_tx_sps_failure_cnt,
+ bam_dmux_tx_stall_cnt
);
return i;
@@ -1352,6 +1359,21 @@
return;
}
if (bam_is_connected) {
+ if (!ul_packet_written) {
+ spin_lock(&bam_tx_pool_spinlock);
+ if (!list_empty(&bam_tx_pool)) {
+ struct tx_pkt_info *info;
+
+ info = list_first_entry(&bam_tx_pool,
+ struct tx_pkt_info, list_node);
+ DMUX_LOG_KERR("%s: UL delayed ts=%u.%09lu\n",
+ __func__, info->ts_sec, info->ts_nsec);
+ DBG_INC_TX_STALL_CNT();
+ ul_packet_written = 1;
+ }
+ spin_unlock(&bam_tx_pool_spinlock);
+ }
+
if (ul_packet_written) {
bam_dmux_log("%s: packet written\n", __func__);
ul_packet_written = 0;
@@ -1639,6 +1661,7 @@
int ret;
void *a2_virt_addr;
int i;
+ int skip_iounmap = 0;
vote_dfab();
/* init BAM */
@@ -1786,7 +1809,15 @@
sps_free_endpoint(bam_tx_pipe);
tx_mem_failed:
sps_deregister_bam_device(h);
+ /*
+ * sps_deregister_bam_device() calls iounmap. calling iounmap on the
+ * same handle below will cause a crash, so skip it if we've freed
+ * the handle here.
+ */
+ skip_iounmap = 1;
register_bam_failed:
+ if (!skip_iounmap)
+ iounmap(a2_virt_addr);
ioremap_failed:
/*destroy_workqueue(bam_mux_workqueue);*/
return ret;
@@ -1825,6 +1856,7 @@
return 0;
register_bam_failed:
+ iounmap(a2_virt_addr);
ioremap_failed:
return ret;
}