diff options
| author | Manoj Chourasia <mchourasia@nvidia.com> | 2016-08-30 01:59:42 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-16 06:05:52 -0400 |
| commit | f6978ee69cd95c5e794d027f4fd5277f2aa26ed2 (patch) | |
| tree | bb00026986b742c152afd8c6b69d919463bbe642 | |
| parent | 66dfaf34e5085d01c40c349ff51b97cf77cd3940 (diff) | |
mttcan:wake netif queue if stopped
Check for Tx buffer space availabed before
queuing new tx requests.
ACK TX Interrupt independendly to prevent unintentional
reset of other interrupt.
Also check DLEC in PSR in case of interrupt of protocol
error in data phase.
Bug 200232485
Bug 1785239
Bug 200164764
Change-Id: Ibf972dbbda0da93e23e756479f7d76b0865e1f2f
Signed-off-by: Manoj Chourasia <mchourasia@nvidia.com>
Reviewed-on: http://git-master/r/1209559
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Rajesh Hosakote <rhosakote@nvidia.com>
Tested-by: Rajesh Hosakote <rhosakote@nvidia.com>
Reviewed-by: Sandeep Trasi <strasi@nvidia.com>
| -rw-r--r-- | drivers/staging/mttcan/hw/m_ttcan.c | 22 | ||||
| -rw-r--r-- | drivers/staging/mttcan/hw/m_ttcan.h | 2 | ||||
| -rw-r--r-- | drivers/staging/mttcan/hw/m_ttcan_linux.h | 3 | ||||
| -rw-r--r-- | drivers/staging/mttcan/m_ttcan_linux.c | 108 |
4 files changed, 81 insertions, 54 deletions
diff --git a/drivers/staging/mttcan/hw/m_ttcan.c b/drivers/staging/mttcan/hw/m_ttcan.c index 51c3af25b..227d1646f 100644 --- a/drivers/staging/mttcan/hw/m_ttcan.c +++ b/drivers/staging/mttcan/hw/m_ttcan.c | |||
| @@ -403,6 +403,19 @@ int ttcan_tx_buff_req_pending(struct ttcan_controller *ttcan, u8 index) | |||
| 403 | return 0; | 403 | return 0; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | int ttcan_tx_buffers_full(struct ttcan_controller *ttcan) | ||
| 407 | { | ||
| 408 | u32 txbrp_reg; | ||
| 409 | u32 mask = (1 << ttcan->mram_cfg[MRAM_TXB].num) - 1; | ||
| 410 | |||
| 411 | txbrp_reg = ttcan_read32(ttcan, ADR_MTTCAN_TXBRP); | ||
| 412 | |||
| 413 | if ((txbrp_reg & mask) == mask) | ||
| 414 | return 1; | ||
| 415 | else | ||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 406 | void ttcan_tx_ded_msg_write(struct ttcan_controller *ttcan, | 419 | void ttcan_tx_ded_msg_write(struct ttcan_controller *ttcan, |
| 407 | struct ttcanfd_frame *ttcanfd, | 420 | struct ttcanfd_frame *ttcanfd, |
| 408 | u8 index, bool tt_en) | 421 | u8 index, bool tt_en) |
| @@ -486,7 +499,7 @@ int ttcan_set_tx_buffer_addr(struct ttcan_controller *ttcan) | |||
| 486 | 499 | ||
| 487 | /* Queue Message in Tx Queue | 500 | /* Queue Message in Tx Queue |
| 488 | * Return | 501 | * Return |
| 489 | * -1 in case of error | 502 | * -ve in case of error |
| 490 | * idx written buffer index | 503 | * idx written buffer index |
| 491 | */ | 504 | */ |
| 492 | int ttcan_tx_fifo_queue_msg(struct ttcan_controller *ttcan, | 505 | int ttcan_tx_fifo_queue_msg(struct ttcan_controller *ttcan, |
| @@ -500,10 +513,9 @@ int ttcan_tx_fifo_queue_msg(struct ttcan_controller *ttcan, | |||
| 500 | if ((txfqs_reg & MTT_TXFQS_TFQF_MASK) == 0) { | 513 | if ((txfqs_reg & MTT_TXFQS_TFQF_MASK) == 0) { |
| 501 | ttcan_tx_ded_msg_write(ttcan, ttcanfd, put_idx, 0); | 514 | ttcan_tx_ded_msg_write(ttcan, ttcanfd, put_idx, 0); |
| 502 | return put_idx; | 515 | return put_idx; |
| 503 | } else { | ||
| 504 | pr_err("%s: Tx queue/FIFO full\n", __func__); | ||
| 505 | return -ENOMEM; | ||
| 506 | } | 516 | } |
| 517 | |||
| 518 | return -ENOMEM; | ||
| 507 | } | 519 | } |
| 508 | 520 | ||
| 509 | /* Check tx fifo status | 521 | /* Check tx fifo status |
| @@ -615,7 +627,6 @@ unsigned int ttcan_read_rx_fifo0(struct ttcan_controller *ttcan) | |||
| 615 | rxf0s_reg = ttcan_read32(ttcan, ADR_MTTCAN_RXF0S); | 627 | rxf0s_reg = ttcan_read32(ttcan, ADR_MTTCAN_RXF0S); |
| 616 | 628 | ||
| 617 | if (!(rxf0s_reg & MTT_RXF0S_F0FL_MASK)) { | 629 | if (!(rxf0s_reg & MTT_RXF0S_F0FL_MASK)) { |
| 618 | pr_info("%s: Rx fifo0 empty\n", __func__); | ||
| 619 | return msgs_read; | 630 | return msgs_read; |
| 620 | } | 631 | } |
| 621 | 632 | ||
| @@ -663,7 +674,6 @@ unsigned int ttcan_read_rx_fifo1(struct ttcan_controller *ttcan) | |||
| 663 | rxf1s_reg = ttcan_read32(ttcan, ADR_MTTCAN_RXF1S); | 674 | rxf1s_reg = ttcan_read32(ttcan, ADR_MTTCAN_RXF1S); |
| 664 | 675 | ||
| 665 | if (!(rxf1s_reg & MTT_RXF1S_F1FL_MASK)) { | 676 | if (!(rxf1s_reg & MTT_RXF1S_F1FL_MASK)) { |
| 666 | pr_info("%s: Rx fifo1 empty\n", __func__); | ||
| 667 | return msgs_read; | 677 | return msgs_read; |
| 668 | } | 678 | } |
| 669 | 679 | ||
diff --git a/drivers/staging/mttcan/hw/m_ttcan.h b/drivers/staging/mttcan/hw/m_ttcan.h index e1c2ed46d..e8f309675 100644 --- a/drivers/staging/mttcan/hw/m_ttcan.h +++ b/drivers/staging/mttcan/hw/m_ttcan.h | |||
| @@ -423,6 +423,8 @@ void ttcan_set_rx_buffers_elements(struct ttcan_controller *ttcan); | |||
| 423 | 423 | ||
| 424 | int ttcan_set_tx_buffer_addr(struct ttcan_controller *ttcan); | 424 | int ttcan_set_tx_buffer_addr(struct ttcan_controller *ttcan); |
| 425 | int ttcan_tx_fifo_full(struct ttcan_controller *ttcan); | 425 | int ttcan_tx_fifo_full(struct ttcan_controller *ttcan); |
| 426 | int ttcan_tx_buffers_full(struct ttcan_controller *ttcan); | ||
| 427 | |||
| 426 | int ttcan_tx_fifo_queue_msg(struct ttcan_controller *ttcan, | 428 | int ttcan_tx_fifo_queue_msg(struct ttcan_controller *ttcan, |
| 427 | struct ttcanfd_frame *ttcanfd); | 429 | struct ttcanfd_frame *ttcanfd); |
| 428 | int ttcan_tx_fifo_get_free_element(struct ttcan_controller *ttcan); | 430 | int ttcan_tx_fifo_get_free_element(struct ttcan_controller *ttcan); |
diff --git a/drivers/staging/mttcan/hw/m_ttcan_linux.h b/drivers/staging/mttcan/hw/m_ttcan_linux.h index 607c88738..5a5c0ef23 100644 --- a/drivers/staging/mttcan/hw/m_ttcan_linux.h +++ b/drivers/staging/mttcan/hw/m_ttcan_linux.h | |||
| @@ -46,9 +46,8 @@ | |||
| 46 | #define MTTCAN_RX_FIFO_INTR (0xFF) | 46 | #define MTTCAN_RX_FIFO_INTR (0xFF) |
| 47 | #define MTTCAN_RX_HP_INTR (0x1 << 8) | 47 | #define MTTCAN_RX_HP_INTR (0x1 << 8) |
| 48 | #define MTTCAN_TX_EV_FIFO_INTR (0xF << 12) | 48 | #define MTTCAN_TX_EV_FIFO_INTR (0xF << 12) |
| 49 | #define MTTCAN_DRX_INTR (0x1 << 19) | ||
| 50 | 49 | ||
| 51 | #define MTTCAN_ERR_INTR (0x3FF7 << 16) | 50 | #define MTTCAN_ERR_INTR (0x1FF9 << 17) |
| 52 | #define MTTCAN_BUS_OFF (1 << 25) | 51 | #define MTTCAN_BUS_OFF (1 << 25) |
| 53 | #define MTTCAN_ERR_WARN (1 << 24) | 52 | #define MTTCAN_ERR_WARN (1 << 24) |
| 54 | #define MTTCAN_ERR_PASS (1 << 23) | 53 | #define MTTCAN_ERR_PASS (1 << 23) |
diff --git a/drivers/staging/mttcan/m_ttcan_linux.c b/drivers/staging/mttcan/m_ttcan_linux.c index a32624370..43f54c419 100644 --- a/drivers/staging/mttcan/m_ttcan_linux.c +++ b/drivers/staging/mttcan/m_ttcan_linux.c | |||
| @@ -104,9 +104,6 @@ static __init int mttcan_hw_init(struct mttcan_priv *priv) | |||
| 104 | ttcan_prog_trigger_mem(ttcan, priv->tmc_shadow); | 104 | ttcan_prog_trigger_mem(ttcan, priv->tmc_shadow); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | ttcan_clear_intr(ttcan); | ||
| 108 | ttcan_clear_tt_intr(ttcan); | ||
| 109 | |||
| 110 | ttcan_print_version(ttcan); | 107 | ttcan_print_version(ttcan); |
| 111 | 108 | ||
| 112 | return err; | 109 | return err; |
| @@ -161,8 +158,6 @@ static __init int mttcan_hw_reinit(const struct mttcan_priv *priv) | |||
| 161 | if (ttcan->mram_cfg[MRAM_TMC].num) | 158 | if (ttcan->mram_cfg[MRAM_TMC].num) |
| 162 | ttcan_prog_trigger_mem(ttcan, priv->tmc_shadow); | 159 | ttcan_prog_trigger_mem(ttcan, priv->tmc_shadow); |
| 163 | 160 | ||
| 164 | ttcan_clear_intr(ttcan); | ||
| 165 | ttcan_clear_tt_intr(ttcan); | ||
| 166 | return err; | 161 | return err; |
| 167 | } | 162 | } |
| 168 | 163 | ||
| @@ -538,13 +533,12 @@ static void mttcan_tx_event(struct net_device *dev) | |||
| 538 | 533 | ||
| 539 | static void mttcan_tx_complete(struct net_device *dev) | 534 | static void mttcan_tx_complete(struct net_device *dev) |
| 540 | { | 535 | { |
| 541 | u32 completed_tx; | ||
| 542 | u32 msg_no; | 536 | u32 msg_no; |
| 543 | 537 | ||
| 544 | struct mttcan_priv *priv = netdev_priv(dev); | 538 | struct mttcan_priv *priv = netdev_priv(dev); |
| 545 | struct net_device_stats *stats = &dev->stats; | 539 | struct net_device_stats *stats = &dev->stats; |
| 546 | 540 | ||
| 547 | completed_tx = ttcan_read_tx_complete_reg(priv->ttcan); | 541 | u32 completed_tx = ttcan_read_tx_complete_reg(priv->ttcan); |
| 548 | 542 | ||
| 549 | /*TODO:- fix how to handle wrap around of tx_next and echo */ | 543 | /*TODO:- fix how to handle wrap around of tx_next and echo */ |
| 550 | for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { | 544 | for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { |
| @@ -568,9 +562,6 @@ static void mttcan_tx_complete(struct net_device *dev) | |||
| 568 | } | 562 | } |
| 569 | 563 | ||
| 570 | if (netif_queue_stopped(dev)) | 564 | if (netif_queue_stopped(dev)) |
| 571 | netif_start_queue(dev); | ||
| 572 | |||
| 573 | if ((priv->tx_next - priv->tx_echo) > 0) | ||
| 574 | netif_wake_queue(dev); | 565 | netif_wake_queue(dev); |
| 575 | } | 566 | } |
| 576 | 567 | ||
| @@ -626,6 +617,8 @@ static int mttcan_poll_ir(struct napi_struct *napi, int quota) | |||
| 626 | if (ir & MTTCAN_ERR_INTR) { | 617 | if (ir & MTTCAN_ERR_INTR) { |
| 627 | psr = ttcan_read_psr(priv->ttcan); | 618 | psr = ttcan_read_psr(priv->ttcan); |
| 628 | priv->ttcan->proto_state = psr; | 619 | priv->ttcan->proto_state = psr; |
| 620 | ack = ir & MTTCAN_ERR_INTR; | ||
| 621 | ttcan_ir_write(priv->ttcan, ack); | ||
| 629 | if ((ir & MTT_IR_EW_MASK) && (psr & MTT_PSR_EW_MASK)) { | 622 | if ((ir & MTT_IR_EW_MASK) && (psr & MTT_PSR_EW_MASK)) { |
| 630 | work_done += mttcan_state_change(dev, | 623 | work_done += mttcan_state_change(dev, |
| 631 | CAN_STATE_ERROR_WARNING); | 624 | CAN_STATE_ERROR_WARNING); |
| @@ -660,9 +653,14 @@ static int mttcan_poll_ir(struct napi_struct *napi, int quota) | |||
| 660 | if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { | 653 | if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { |
| 661 | if ((ir & MTT_IR_PED_MASK) || | 654 | if ((ir & MTT_IR_PED_MASK) || |
| 662 | (ir & MTT_IR_PEA_MASK)) { | 655 | (ir & MTT_IR_PEA_MASK)) { |
| 663 | enum ttcan_lec_type lec = | 656 | enum ttcan_lec_type lec; |
| 664 | (psr & MTT_PSR_LEC_MASK) | 657 | |
| 665 | >> MTT_PSR_LEC_SHIFT; | 658 | if (ir & MTT_IR_PEA_MASK) |
| 659 | lec = (psr & MTT_PSR_LEC_MASK) | ||
| 660 | >> MTT_PSR_LEC_SHIFT; | ||
| 661 | else | ||
