18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Cisco Systems, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright 2007 Nuova Systems, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This program is free software; you may redistribute it and/or modify 68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 78c2ecf20Sopenharmony_ci * the Free Software Foundation; version 2 of the License. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 108c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 118c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 128c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 138c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 148c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 158c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 168c2ecf20Sopenharmony_ci * SOFTWARE. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/errno.h> 208c2ecf20Sopenharmony_ci#include <linux/types.h> 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include <linux/delay.h> 238c2ecf20Sopenharmony_ci#include "vnic_wq_copy.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_civoid vnic_wq_copy_enable(struct vnic_wq_copy *wq) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci iowrite32(1, &wq->ctrl->enable); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciint vnic_wq_copy_disable(struct vnic_wq_copy *wq) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci unsigned int wait; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->enable); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* Wait for HW to ACK disable request */ 378c2ecf20Sopenharmony_ci for (wait = 0; wait < 100; wait++) { 388c2ecf20Sopenharmony_ci if (!(ioread32(&wq->ctrl->running))) 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci udelay(1); 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci printk(KERN_ERR "Failed to disable Copy WQ[%d]," 448c2ecf20Sopenharmony_ci " fetch index=%d, posted_index=%d\n", 458c2ecf20Sopenharmony_ci wq->index, ioread32(&wq->ctrl->fetch_index), 468c2ecf20Sopenharmony_ci ioread32(&wq->ctrl->posted_index)); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return -ENODEV; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_civoid vnic_wq_copy_clean(struct vnic_wq_copy *wq, 528c2ecf20Sopenharmony_ci void (*q_clean)(struct vnic_wq_copy *wq, 538c2ecf20Sopenharmony_ci struct fcpio_host_req *wq_desc)) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci BUG_ON(ioread32(&wq->ctrl->enable)); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci if (vnic_wq_copy_desc_in_use(wq)) 588c2ecf20Sopenharmony_ci vnic_wq_copy_service(wq, -1, q_clean); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci wq->to_use_index = wq->to_clean_index = 0; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->fetch_index); 638c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->posted_index); 648c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->error_status); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci vnic_dev_clear_desc_ring(&wq->ring); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_civoid vnic_wq_copy_free(struct vnic_wq_copy *wq) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct vnic_dev *vdev; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci vdev = wq->vdev; 748c2ecf20Sopenharmony_ci vnic_dev_free_desc_ring(vdev, &wq->ring); 758c2ecf20Sopenharmony_ci wq->ctrl = NULL; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciint vnic_wq_copy_alloc(struct vnic_dev *vdev, struct vnic_wq_copy *wq, 798c2ecf20Sopenharmony_ci unsigned int index, unsigned int desc_count, 808c2ecf20Sopenharmony_ci unsigned int desc_size) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci wq->index = index; 838c2ecf20Sopenharmony_ci wq->vdev = vdev; 848c2ecf20Sopenharmony_ci wq->to_use_index = wq->to_clean_index = 0; 858c2ecf20Sopenharmony_ci wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index); 868c2ecf20Sopenharmony_ci if (!wq->ctrl) { 878c2ecf20Sopenharmony_ci printk(KERN_ERR "Failed to hook COPY WQ[%d] resource\n", index); 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci vnic_wq_copy_disable(wq); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_civoid vnic_wq_copy_init(struct vnic_wq_copy *wq, unsigned int cq_index, 978c2ecf20Sopenharmony_ci unsigned int error_interrupt_enable, 988c2ecf20Sopenharmony_ci unsigned int error_interrupt_offset) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci u64 paddr; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET; 1038c2ecf20Sopenharmony_ci writeq(paddr, &wq->ctrl->ring_base); 1048c2ecf20Sopenharmony_ci iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size); 1058c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->fetch_index); 1068c2ecf20Sopenharmony_ci iowrite32(0, &wq->ctrl->posted_index); 1078c2ecf20Sopenharmony_ci iowrite32(cq_index, &wq->ctrl->cq_index); 1088c2ecf20Sopenharmony_ci iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable); 1098c2ecf20Sopenharmony_ci iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 112