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#ifndef _VNIC_WQ_COPY_H_ 198c2ecf20Sopenharmony_ci#define _VNIC_WQ_COPY_H_ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include "vnic_wq.h" 238c2ecf20Sopenharmony_ci#include "fcpio.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define VNIC_WQ_COPY_MAX 1 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct vnic_wq_copy { 288c2ecf20Sopenharmony_ci unsigned int index; 298c2ecf20Sopenharmony_ci struct vnic_dev *vdev; 308c2ecf20Sopenharmony_ci struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */ 318c2ecf20Sopenharmony_ci struct vnic_dev_ring ring; 328c2ecf20Sopenharmony_ci unsigned to_use_index; 338c2ecf20Sopenharmony_ci unsigned to_clean_index; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic inline unsigned int vnic_wq_copy_desc_avail(struct vnic_wq_copy *wq) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci return wq->ring.desc_avail; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic inline unsigned int vnic_wq_copy_desc_in_use(struct vnic_wq_copy *wq) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci return wq->ring.desc_count - 1 - wq->ring.desc_avail; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic inline void *vnic_wq_copy_next_desc(struct vnic_wq_copy *wq) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct fcpio_host_req *desc = wq->ring.descs; 498c2ecf20Sopenharmony_ci return &desc[wq->to_use_index]; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic inline void vnic_wq_copy_post(struct vnic_wq_copy *wq) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci ((wq->to_use_index + 1) == wq->ring.desc_count) ? 568c2ecf20Sopenharmony_ci (wq->to_use_index = 0) : (wq->to_use_index++); 578c2ecf20Sopenharmony_ci wq->ring.desc_avail--; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* Adding write memory barrier prevents compiler and/or CPU 608c2ecf20Sopenharmony_ci * reordering, thus avoiding descriptor posting before 618c2ecf20Sopenharmony_ci * descriptor is initialized. Otherwise, hardware can read 628c2ecf20Sopenharmony_ci * stale descriptor fields. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci wmb(); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci iowrite32(wq->to_use_index, &wq->ctrl->posted_index); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic inline void vnic_wq_copy_desc_process(struct vnic_wq_copy *wq, u16 index) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci unsigned int cnt; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (wq->to_clean_index <= index) 748c2ecf20Sopenharmony_ci cnt = (index - wq->to_clean_index) + 1; 758c2ecf20Sopenharmony_ci else 768c2ecf20Sopenharmony_ci cnt = wq->ring.desc_count - wq->to_clean_index + index + 1; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci wq->to_clean_index = ((index + 1) % wq->ring.desc_count); 798c2ecf20Sopenharmony_ci wq->ring.desc_avail += cnt; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline void vnic_wq_copy_service(struct vnic_wq_copy *wq, 848c2ecf20Sopenharmony_ci u16 completed_index, 858c2ecf20Sopenharmony_ci void (*q_service)(struct vnic_wq_copy *wq, 868c2ecf20Sopenharmony_ci struct fcpio_host_req *wq_desc)) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct fcpio_host_req *wq_desc = wq->ring.descs; 898c2ecf20Sopenharmony_ci unsigned int curr_index; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci while (1) { 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (q_service) 948c2ecf20Sopenharmony_ci (*q_service)(wq, &wq_desc[wq->to_clean_index]); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci wq->ring.desc_avail++; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci curr_index = wq->to_clean_index; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* increment the to-clean index so that we start 1018c2ecf20Sopenharmony_ci * with an unprocessed index next time we enter the loop 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci ((wq->to_clean_index + 1) == wq->ring.desc_count) ? 1048c2ecf20Sopenharmony_ci (wq->to_clean_index = 0) : (wq->to_clean_index++); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (curr_index == completed_index) 1078c2ecf20Sopenharmony_ci break; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* we have cleaned all the entries */ 1108c2ecf20Sopenharmony_ci if ((completed_index == (u16)-1) && 1118c2ecf20Sopenharmony_ci (wq->to_clean_index == wq->to_use_index)) 1128c2ecf20Sopenharmony_ci break; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_civoid vnic_wq_copy_enable(struct vnic_wq_copy *wq); 1178c2ecf20Sopenharmony_ciint vnic_wq_copy_disable(struct vnic_wq_copy *wq); 1188c2ecf20Sopenharmony_civoid vnic_wq_copy_free(struct vnic_wq_copy *wq); 1198c2ecf20Sopenharmony_ciint vnic_wq_copy_alloc(struct vnic_dev *vdev, struct vnic_wq_copy *wq, 1208c2ecf20Sopenharmony_ci unsigned int index, unsigned int desc_count, unsigned int desc_size); 1218c2ecf20Sopenharmony_civoid vnic_wq_copy_init(struct vnic_wq_copy *wq, unsigned int cq_index, 1228c2ecf20Sopenharmony_ci unsigned int error_interrupt_enable, 1238c2ecf20Sopenharmony_ci unsigned int error_interrupt_offset); 1248c2ecf20Sopenharmony_civoid vnic_wq_copy_clean(struct vnic_wq_copy *wq, 1258c2ecf20Sopenharmony_ci void (*q_clean)(struct vnic_wq_copy *wq, 1268c2ecf20Sopenharmony_ci struct fcpio_host_req *wq_desc)); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#endif /* _VNIC_WQ_COPY_H_ */ 129