18c2ecf20Sopenharmony_ci/********************************************************************** 28c2ecf20Sopenharmony_ci * Author: Cavium, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Contact: support@cavium.com 58c2ecf20Sopenharmony_ci * Please include "LiquidIO" in the subject. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 168c2ecf20Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more details. 178c2ecf20Sopenharmony_ci ***********************************************************************/ 188c2ecf20Sopenharmony_ci/*! \file octeon_main.h 198c2ecf20Sopenharmony_ci * \brief Host Driver: This file is included by all host driver source files 208c2ecf20Sopenharmony_ci * to include common definitions. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifndef _OCTEON_MAIN_H_ 248c2ecf20Sopenharmony_ci#define _OCTEON_MAIN_H_ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32 298c2ecf20Sopenharmony_ci#define CVM_CAST64(v) ((long long)(v)) 308c2ecf20Sopenharmony_ci#elif BITS_PER_LONG == 64 318c2ecf20Sopenharmony_ci#define CVM_CAST64(v) ((long long)(long)(v)) 328c2ecf20Sopenharmony_ci#else 338c2ecf20Sopenharmony_ci#error "Unknown system architecture" 348c2ecf20Sopenharmony_ci#endif 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define DRV_NAME "LiquidIO" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct octeon_device_priv { 398c2ecf20Sopenharmony_ci /** Tasklet structures for this device. */ 408c2ecf20Sopenharmony_ci struct tasklet_struct droq_tasklet; 418c2ecf20Sopenharmony_ci unsigned long napi_mask; 428c2ecf20Sopenharmony_ci struct octeon_device *dev; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/** This structure is used by NIC driver to store information required 468c2ecf20Sopenharmony_ci * to free the sk_buff when the packet has been fetched by Octeon. 478c2ecf20Sopenharmony_ci * Bytes offset below assume worst-case of a 64-bit system. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistruct octnet_buf_free_info { 508c2ecf20Sopenharmony_ci /** Bytes 1-8. Pointer to network device private structure. */ 518c2ecf20Sopenharmony_ci struct lio *lio; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /** Bytes 9-16. Pointer to sk_buff. */ 548c2ecf20Sopenharmony_ci struct sk_buff *skb; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /** Bytes 17-24. Pointer to gather list. */ 578c2ecf20Sopenharmony_ci struct octnic_gather *g; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /** Bytes 25-32. Physical address of skb->data or gather list. */ 608c2ecf20Sopenharmony_ci u64 dptr; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /** Bytes 33-47. Piggybacked soft command, if any */ 638c2ecf20Sopenharmony_ci struct octeon_soft_command *sc; 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* BQL-related functions */ 678c2ecf20Sopenharmony_ciint octeon_report_sent_bytes_to_bql(void *buf, int reqtype); 688c2ecf20Sopenharmony_civoid octeon_update_tx_completion_counters(void *buf, int reqtype, 698c2ecf20Sopenharmony_ci unsigned int *pkts_compl, 708c2ecf20Sopenharmony_ci unsigned int *bytes_compl); 718c2ecf20Sopenharmony_civoid octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl, 728c2ecf20Sopenharmony_ci unsigned int bytes_compl); 738c2ecf20Sopenharmony_civoid octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_civoid octeon_schedule_rxq_oom_work(struct octeon_device *oct, 768c2ecf20Sopenharmony_ci struct octeon_droq *droq); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/** Swap 8B blocks */ 798c2ecf20Sopenharmony_cistatic inline void octeon_swap_8B_data(u64 *data, u32 blocks) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci while (blocks) { 828c2ecf20Sopenharmony_ci cpu_to_be64s(data); 838c2ecf20Sopenharmony_ci blocks--; 848c2ecf20Sopenharmony_ci data++; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/** 898c2ecf20Sopenharmony_ci * \brief unmaps a PCI BAR 908c2ecf20Sopenharmony_ci * @param oct Pointer to Octeon device 918c2ecf20Sopenharmony_ci * @param baridx bar index 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_cistatic inline void octeon_unmap_pci_barx(struct octeon_device *oct, int baridx) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "Freeing PCI mapped regions for Bar%d\n", 968c2ecf20Sopenharmony_ci baridx); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (oct->mmio[baridx].done) 998c2ecf20Sopenharmony_ci iounmap(oct->mmio[baridx].hw_addr); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (oct->mmio[baridx].start) 1028c2ecf20Sopenharmony_ci pci_release_region(oct->pci_dev, baridx * 2); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/** 1068c2ecf20Sopenharmony_ci * \brief maps a PCI BAR 1078c2ecf20Sopenharmony_ci * @param oct Pointer to Octeon device 1088c2ecf20Sopenharmony_ci * @param baridx bar index 1098c2ecf20Sopenharmony_ci * @param max_map_len maximum length of mapped memory 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_cistatic inline int octeon_map_pci_barx(struct octeon_device *oct, 1128c2ecf20Sopenharmony_ci int baridx, int max_map_len) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci u32 mapped_len = 0; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) { 1178c2ecf20Sopenharmony_ci dev_err(&oct->pci_dev->dev, "pci_request_region failed for bar %d\n", 1188c2ecf20Sopenharmony_ci baridx); 1198c2ecf20Sopenharmony_ci return 1; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci oct->mmio[baridx].start = pci_resource_start(oct->pci_dev, baridx * 2); 1238c2ecf20Sopenharmony_ci oct->mmio[baridx].len = pci_resource_len(oct->pci_dev, baridx * 2); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci mapped_len = oct->mmio[baridx].len; 1268c2ecf20Sopenharmony_ci if (!mapped_len) 1278c2ecf20Sopenharmony_ci goto err_release_region; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (max_map_len && (mapped_len > max_map_len)) 1308c2ecf20Sopenharmony_ci mapped_len = max_map_len; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci oct->mmio[baridx].hw_addr = 1338c2ecf20Sopenharmony_ci ioremap(oct->mmio[baridx].start, mapped_len); 1348c2ecf20Sopenharmony_ci oct->mmio[baridx].mapped_len = mapped_len; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "BAR%d start: 0x%llx mapped %u of %u bytes\n", 1378c2ecf20Sopenharmony_ci baridx, oct->mmio[baridx].start, mapped_len, 1388c2ecf20Sopenharmony_ci oct->mmio[baridx].len); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (!oct->mmio[baridx].hw_addr) { 1418c2ecf20Sopenharmony_ci dev_err(&oct->pci_dev->dev, "error ioremap for bar %d\n", 1428c2ecf20Sopenharmony_ci baridx); 1438c2ecf20Sopenharmony_ci goto err_release_region; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci oct->mmio[baridx].done = 1; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci return 0; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cierr_release_region: 1508c2ecf20Sopenharmony_ci pci_release_region(oct->pci_dev, baridx * 2); 1518c2ecf20Sopenharmony_ci return 1; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/* input parameter: 1558c2ecf20Sopenharmony_ci * sc: pointer to a soft request 1568c2ecf20Sopenharmony_ci * timeout: milli sec which an application wants to wait for the 1578c2ecf20Sopenharmony_ci response of the request. 1588c2ecf20Sopenharmony_ci * 0: the request will wait until its response gets back 1598c2ecf20Sopenharmony_ci * from the firmware within LIO_SC_MAX_TMO_MS milli sec. 1608c2ecf20Sopenharmony_ci * It the response does not return within 1618c2ecf20Sopenharmony_ci * LIO_SC_MAX_TMO_MS milli sec, lio_process_ordered_list() 1628c2ecf20Sopenharmony_ci * will move the request to zombie response list. 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * return value: 1658c2ecf20Sopenharmony_ci * 0: got the response from firmware for the sc request. 1668c2ecf20Sopenharmony_ci * errno -EINTR: user abort the command. 1678c2ecf20Sopenharmony_ci * errno -ETIME: user spefified timeout value has been expired. 1688c2ecf20Sopenharmony_ci * errno -EBUSY: the response of the request does not return in 1698c2ecf20Sopenharmony_ci * resonable time (LIO_SC_MAX_TMO_MS). 1708c2ecf20Sopenharmony_ci * the sc wll be move to zombie response list by 1718c2ecf20Sopenharmony_ci * lio_process_ordered_list() 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * A request with non-zero return value, the sc->caller_is_done 1748c2ecf20Sopenharmony_ci * will be marked 1. 1758c2ecf20Sopenharmony_ci * When getting a request with zero return value, the requestor 1768c2ecf20Sopenharmony_ci * should mark sc->caller_is_done with 1 after examing the 1778c2ecf20Sopenharmony_ci * response of sc. 1788c2ecf20Sopenharmony_ci * lio_process_ordered_list() will free the soft command on behalf 1798c2ecf20Sopenharmony_ci * of the soft command requestor. 1808c2ecf20Sopenharmony_ci * This is to fix the possible race condition of both timeout process 1818c2ecf20Sopenharmony_ci * and lio_process_ordered_list()/callback function to free a 1828c2ecf20Sopenharmony_ci * sc strucutre. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_cistatic inline int 1858c2ecf20Sopenharmony_ciwait_for_sc_completion_timeout(struct octeon_device *oct_dev, 1868c2ecf20Sopenharmony_ci struct octeon_soft_command *sc, 1878c2ecf20Sopenharmony_ci unsigned long timeout) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci int errno = 0; 1908c2ecf20Sopenharmony_ci long timeout_jiff; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (timeout) 1938c2ecf20Sopenharmony_ci timeout_jiff = msecs_to_jiffies(timeout); 1948c2ecf20Sopenharmony_ci else 1958c2ecf20Sopenharmony_ci timeout_jiff = MAX_SCHEDULE_TIMEOUT; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci timeout_jiff = 1988c2ecf20Sopenharmony_ci wait_for_completion_interruptible_timeout(&sc->complete, 1998c2ecf20Sopenharmony_ci timeout_jiff); 2008c2ecf20Sopenharmony_ci if (timeout_jiff == 0) { 2018c2ecf20Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc is timeout\n", 2028c2ecf20Sopenharmony_ci __func__); 2038c2ecf20Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 2048c2ecf20Sopenharmony_ci errno = -ETIME; 2058c2ecf20Sopenharmony_ci } else if (timeout_jiff == -ERESTARTSYS) { 2068c2ecf20Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc is interrupted\n", 2078c2ecf20Sopenharmony_ci __func__); 2088c2ecf20Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 2098c2ecf20Sopenharmony_ci errno = -EINTR; 2108c2ecf20Sopenharmony_ci } else if (sc->sc_status == OCTEON_REQUEST_TIMEOUT) { 2118c2ecf20Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc has fatal timeout\n", 2128c2ecf20Sopenharmony_ci __func__); 2138c2ecf20Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 2148c2ecf20Sopenharmony_ci errno = -EBUSY; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return errno; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#ifndef ROUNDUP4 2218c2ecf20Sopenharmony_ci#define ROUNDUP4(val) (((val) + 3) & 0xfffffffc) 2228c2ecf20Sopenharmony_ci#endif 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci#ifndef ROUNDUP8 2258c2ecf20Sopenharmony_ci#define ROUNDUP8(val) (((val) + 7) & 0xfffffff8) 2268c2ecf20Sopenharmony_ci#endif 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#ifndef ROUNDUP16 2298c2ecf20Sopenharmony_ci#define ROUNDUP16(val) (((val) + 15) & 0xfffffff0) 2308c2ecf20Sopenharmony_ci#endif 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#ifndef ROUNDUP128 2338c2ecf20Sopenharmony_ci#define ROUNDUP128(val) (((val) + 127) & 0xffffff80) 2348c2ecf20Sopenharmony_ci#endif 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci#endif /* _OCTEON_MAIN_H_ */ 237