19c067b84SDoug Ambrisko /* SPDX-License-Identifier: BSD-3-Clause 29c067b84SDoug Ambrisko * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. 39c067b84SDoug Ambrisko * Copyright 2007 Nuova Systems, Inc. All rights reserved. 49c067b84SDoug Ambrisko */ 59c067b84SDoug Ambrisko 69c067b84SDoug Ambrisko #include "enic.h" 79c067b84SDoug Ambrisko #include "vnic_dev.h" 89c067b84SDoug Ambrisko #include "vnic_rq.h" 99c067b84SDoug Ambrisko 109c067b84SDoug Ambrisko void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, 119c067b84SDoug Ambrisko unsigned int fetch_index, unsigned int posted_index, 129c067b84SDoug Ambrisko unsigned int error_interrupt_enable, 139c067b84SDoug Ambrisko unsigned int error_interrupt_offset) 149c067b84SDoug Ambrisko { 159c067b84SDoug Ambrisko u64 paddr; 169c067b84SDoug Ambrisko unsigned int count = rq->ring.desc_count; 179c067b84SDoug Ambrisko 189c067b84SDoug Ambrisko paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET; 199c067b84SDoug Ambrisko ENIC_BUS_WRITE_8(rq->ctrl, RX_RING_BASE, paddr); 209c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_RING_SIZE, count); 219c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_CQ_INDEX, cq_index); 229c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_ERROR_INTR_ENABLE, error_interrupt_enable); 239c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_ERROR_INTR_OFFSET, error_interrupt_offset); 249c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_ERROR_STATUS, 0); 259c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_FETCH_INDEX, fetch_index); 269c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_POSTED_INDEX, posted_index); 279c067b84SDoug Ambrisko } 289c067b84SDoug Ambrisko 299c067b84SDoug Ambrisko void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, 309c067b84SDoug Ambrisko unsigned int error_interrupt_enable, 319c067b84SDoug Ambrisko unsigned int error_interrupt_offset) 329c067b84SDoug Ambrisko { 339c067b84SDoug Ambrisko u32 fetch_index = 0; 349c067b84SDoug Ambrisko 359c067b84SDoug Ambrisko /* Use current fetch_index as the ring starting point */ 369c067b84SDoug Ambrisko fetch_index = ENIC_BUS_READ_4(rq->ctrl, RX_FETCH_INDEX); 379c067b84SDoug Ambrisko 389c067b84SDoug Ambrisko if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */ 399c067b84SDoug Ambrisko /* Hardware surprise removal: reset fetch_index */ 409c067b84SDoug Ambrisko fetch_index = 0; 419c067b84SDoug Ambrisko } 429c067b84SDoug Ambrisko 43*0acab8b3SDoug Ambrisko fetch_index = 0; 449c067b84SDoug Ambrisko vnic_rq_init_start(rq, cq_index, 459c067b84SDoug Ambrisko fetch_index, fetch_index, 469c067b84SDoug Ambrisko error_interrupt_enable, 479c067b84SDoug Ambrisko error_interrupt_offset); 489c067b84SDoug Ambrisko rq->rxst_idx = 0; 499c067b84SDoug Ambrisko rq->tot_pkts = 0; 509c067b84SDoug Ambrisko } 519c067b84SDoug Ambrisko 529c067b84SDoug Ambrisko unsigned int vnic_rq_error_status(struct vnic_rq *rq) 539c067b84SDoug Ambrisko { 54*0acab8b3SDoug Ambrisko return (ENIC_BUS_READ_4(rq->ctrl, RX_ERROR_STATUS)); 559c067b84SDoug Ambrisko } 569c067b84SDoug Ambrisko 579c067b84SDoug Ambrisko void vnic_rq_enable(struct vnic_rq *rq) 589c067b84SDoug Ambrisko { 599c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_ENABLE, 1); 609c067b84SDoug Ambrisko } 619c067b84SDoug Ambrisko 629c067b84SDoug Ambrisko int vnic_rq_disable(struct vnic_rq *rq) 639c067b84SDoug Ambrisko { 649c067b84SDoug Ambrisko unsigned int wait; 659c067b84SDoug Ambrisko 669c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_ENABLE, 0); 679c067b84SDoug Ambrisko 689c067b84SDoug Ambrisko /* Wait for HW to ACK disable request */ 699c067b84SDoug Ambrisko for (wait = 0; wait < 1000; wait++) { 709c067b84SDoug Ambrisko if (!(ENIC_BUS_READ_4(rq->ctrl, RX_RUNNING))) 719c067b84SDoug Ambrisko return 0; 729c067b84SDoug Ambrisko udelay(10); 739c067b84SDoug Ambrisko } 749c067b84SDoug Ambrisko 759c067b84SDoug Ambrisko pr_err("Failed to disable RQ[%d]\n", rq->index); 769c067b84SDoug Ambrisko 77*0acab8b3SDoug Ambrisko return (ETIMEDOUT); 789c067b84SDoug Ambrisko } 799c067b84SDoug Ambrisko 809c067b84SDoug Ambrisko void vnic_rq_clean(struct vnic_rq *rq) 819c067b84SDoug Ambrisko { 829c067b84SDoug Ambrisko u32 fetch_index; 839c067b84SDoug Ambrisko unsigned int count = rq->ring.desc_count; 849c067b84SDoug Ambrisko 859c067b84SDoug Ambrisko rq->ring.desc_avail = count - 1; 869c067b84SDoug Ambrisko rq->rx_nb_hold = 0; 879c067b84SDoug Ambrisko 889c067b84SDoug Ambrisko /* Use current fetch_index as the ring starting point */ 899c067b84SDoug Ambrisko fetch_index = ENIC_BUS_READ_4(rq->ctrl, RX_FETCH_INDEX); 909c067b84SDoug Ambrisko if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */ 919c067b84SDoug Ambrisko /* Hardware surprise removal: reset fetch_index */ 929c067b84SDoug Ambrisko fetch_index = 0; 939c067b84SDoug Ambrisko } 949c067b84SDoug Ambrisko 959c067b84SDoug Ambrisko ENIC_BUS_WRITE_4(rq->ctrl, RX_POSTED_INDEX, fetch_index); 969c067b84SDoug Ambrisko 979c067b84SDoug Ambrisko vnic_dev_clear_desc_ring(&rq->ring); 989c067b84SDoug Ambrisko } 99