162306a36Sopenharmony_ci/********************************************************************** 262306a36Sopenharmony_ci * Author: Cavium, Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Contact: support@cavium.com 562306a36Sopenharmony_ci * Please include "LiquidIO" in the subject. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 1162306a36Sopenharmony_ci * published by the Free Software Foundation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 1662306a36Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more details. 1762306a36Sopenharmony_ci ***********************************************************************/ 1862306a36Sopenharmony_ci/*! \file octeon_main.h 1962306a36Sopenharmony_ci * \brief Host Driver: This file is included by all host driver source files 2062306a36Sopenharmony_ci * to include common definitions. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifndef _OCTEON_MAIN_H_ 2462306a36Sopenharmony_ci#define _OCTEON_MAIN_H_ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/sched/signal.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#if BITS_PER_LONG == 32 2962306a36Sopenharmony_ci#define CVM_CAST64(v) ((long long)(v)) 3062306a36Sopenharmony_ci#elif BITS_PER_LONG == 64 3162306a36Sopenharmony_ci#define CVM_CAST64(v) ((long long)(long)(v)) 3262306a36Sopenharmony_ci#else 3362306a36Sopenharmony_ci#error "Unknown system architecture" 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define DRV_NAME "LiquidIO" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistruct octeon_device_priv { 3962306a36Sopenharmony_ci /** Tasklet structures for this device. */ 4062306a36Sopenharmony_ci struct tasklet_struct droq_tasklet; 4162306a36Sopenharmony_ci unsigned long napi_mask; 4262306a36Sopenharmony_ci struct octeon_device *dev; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** This structure is used by NIC driver to store information required 4662306a36Sopenharmony_ci * to free the sk_buff when the packet has been fetched by Octeon. 4762306a36Sopenharmony_ci * Bytes offset below assume worst-case of a 64-bit system. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_cistruct octnet_buf_free_info { 5062306a36Sopenharmony_ci /** Bytes 1-8. Pointer to network device private structure. */ 5162306a36Sopenharmony_ci struct lio *lio; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /** Bytes 9-16. Pointer to sk_buff. */ 5462306a36Sopenharmony_ci struct sk_buff *skb; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /** Bytes 17-24. Pointer to gather list. */ 5762306a36Sopenharmony_ci struct octnic_gather *g; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /** Bytes 25-32. Physical address of skb->data or gather list. */ 6062306a36Sopenharmony_ci u64 dptr; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /** Bytes 33-47. Piggybacked soft command, if any */ 6362306a36Sopenharmony_ci struct octeon_soft_command *sc; 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* BQL-related functions */ 6762306a36Sopenharmony_ciint octeon_report_sent_bytes_to_bql(void *buf, int reqtype); 6862306a36Sopenharmony_civoid octeon_update_tx_completion_counters(void *buf, int reqtype, 6962306a36Sopenharmony_ci unsigned int *pkts_compl, 7062306a36Sopenharmony_ci unsigned int *bytes_compl); 7162306a36Sopenharmony_civoid octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl, 7262306a36Sopenharmony_ci unsigned int bytes_compl); 7362306a36Sopenharmony_civoid octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_civoid octeon_schedule_rxq_oom_work(struct octeon_device *oct, 7662306a36Sopenharmony_ci struct octeon_droq *droq); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/** Swap 8B blocks */ 7962306a36Sopenharmony_cistatic inline void octeon_swap_8B_data(u64 *data, u32 blocks) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci while (blocks) { 8262306a36Sopenharmony_ci cpu_to_be64s(data); 8362306a36Sopenharmony_ci blocks--; 8462306a36Sopenharmony_ci data++; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/** 8962306a36Sopenharmony_ci * \brief unmaps a PCI BAR 9062306a36Sopenharmony_ci * @param oct Pointer to Octeon device 9162306a36Sopenharmony_ci * @param baridx bar index 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_cistatic inline void octeon_unmap_pci_barx(struct octeon_device *oct, int baridx) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "Freeing PCI mapped regions for Bar%d\n", 9662306a36Sopenharmony_ci baridx); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (oct->mmio[baridx].done) 9962306a36Sopenharmony_ci iounmap(oct->mmio[baridx].hw_addr); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (oct->mmio[baridx].start) 10262306a36Sopenharmony_ci pci_release_region(oct->pci_dev, baridx * 2); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/** 10662306a36Sopenharmony_ci * \brief maps a PCI BAR 10762306a36Sopenharmony_ci * @param oct Pointer to Octeon device 10862306a36Sopenharmony_ci * @param baridx bar index 10962306a36Sopenharmony_ci * @param max_map_len maximum length of mapped memory 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cistatic inline int octeon_map_pci_barx(struct octeon_device *oct, 11262306a36Sopenharmony_ci int baridx, int max_map_len) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci u32 mapped_len = 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) { 11762306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, "pci_request_region failed for bar %d\n", 11862306a36Sopenharmony_ci baridx); 11962306a36Sopenharmony_ci return 1; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci oct->mmio[baridx].start = pci_resource_start(oct->pci_dev, baridx * 2); 12362306a36Sopenharmony_ci oct->mmio[baridx].len = pci_resource_len(oct->pci_dev, baridx * 2); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci mapped_len = oct->mmio[baridx].len; 12662306a36Sopenharmony_ci if (!mapped_len) 12762306a36Sopenharmony_ci goto err_release_region; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (max_map_len && (mapped_len > max_map_len)) 13062306a36Sopenharmony_ci mapped_len = max_map_len; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci oct->mmio[baridx].hw_addr = 13362306a36Sopenharmony_ci ioremap(oct->mmio[baridx].start, mapped_len); 13462306a36Sopenharmony_ci oct->mmio[baridx].mapped_len = mapped_len; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci dev_dbg(&oct->pci_dev->dev, "BAR%d start: 0x%llx mapped %u of %u bytes\n", 13762306a36Sopenharmony_ci baridx, oct->mmio[baridx].start, mapped_len, 13862306a36Sopenharmony_ci oct->mmio[baridx].len); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (!oct->mmio[baridx].hw_addr) { 14162306a36Sopenharmony_ci dev_err(&oct->pci_dev->dev, "error ioremap for bar %d\n", 14262306a36Sopenharmony_ci baridx); 14362306a36Sopenharmony_ci goto err_release_region; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci oct->mmio[baridx].done = 1; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci return 0; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cierr_release_region: 15062306a36Sopenharmony_ci pci_release_region(oct->pci_dev, baridx * 2); 15162306a36Sopenharmony_ci return 1; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* input parameter: 15562306a36Sopenharmony_ci * sc: pointer to a soft request 15662306a36Sopenharmony_ci * timeout: milli sec which an application wants to wait for the 15762306a36Sopenharmony_ci response of the request. 15862306a36Sopenharmony_ci * 0: the request will wait until its response gets back 15962306a36Sopenharmony_ci * from the firmware within LIO_SC_MAX_TMO_MS milli sec. 16062306a36Sopenharmony_ci * It the response does not return within 16162306a36Sopenharmony_ci * LIO_SC_MAX_TMO_MS milli sec, lio_process_ordered_list() 16262306a36Sopenharmony_ci * will move the request to zombie response list. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * return value: 16562306a36Sopenharmony_ci * 0: got the response from firmware for the sc request. 16662306a36Sopenharmony_ci * errno -EINTR: user abort the command. 16762306a36Sopenharmony_ci * errno -ETIME: user spefified timeout value has been expired. 16862306a36Sopenharmony_ci * errno -EBUSY: the response of the request does not return in 16962306a36Sopenharmony_ci * resonable time (LIO_SC_MAX_TMO_MS). 17062306a36Sopenharmony_ci * the sc wll be move to zombie response list by 17162306a36Sopenharmony_ci * lio_process_ordered_list() 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * A request with non-zero return value, the sc->caller_is_done 17462306a36Sopenharmony_ci * will be marked 1. 17562306a36Sopenharmony_ci * When getting a request with zero return value, the requestor 17662306a36Sopenharmony_ci * should mark sc->caller_is_done with 1 after examing the 17762306a36Sopenharmony_ci * response of sc. 17862306a36Sopenharmony_ci * lio_process_ordered_list() will free the soft command on behalf 17962306a36Sopenharmony_ci * of the soft command requestor. 18062306a36Sopenharmony_ci * This is to fix the possible race condition of both timeout process 18162306a36Sopenharmony_ci * and lio_process_ordered_list()/callback function to free a 18262306a36Sopenharmony_ci * sc strucutre. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistatic inline int 18562306a36Sopenharmony_ciwait_for_sc_completion_timeout(struct octeon_device *oct_dev, 18662306a36Sopenharmony_ci struct octeon_soft_command *sc, 18762306a36Sopenharmony_ci unsigned long timeout) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci int errno = 0; 19062306a36Sopenharmony_ci long timeout_jiff; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (timeout) 19362306a36Sopenharmony_ci timeout_jiff = msecs_to_jiffies(timeout); 19462306a36Sopenharmony_ci else 19562306a36Sopenharmony_ci timeout_jiff = MAX_SCHEDULE_TIMEOUT; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci timeout_jiff = 19862306a36Sopenharmony_ci wait_for_completion_interruptible_timeout(&sc->complete, 19962306a36Sopenharmony_ci timeout_jiff); 20062306a36Sopenharmony_ci if (timeout_jiff == 0) { 20162306a36Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc is timeout\n", 20262306a36Sopenharmony_ci __func__); 20362306a36Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 20462306a36Sopenharmony_ci errno = -ETIME; 20562306a36Sopenharmony_ci } else if (timeout_jiff == -ERESTARTSYS) { 20662306a36Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc is interrupted\n", 20762306a36Sopenharmony_ci __func__); 20862306a36Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 20962306a36Sopenharmony_ci errno = -EINTR; 21062306a36Sopenharmony_ci } else if (sc->sc_status == OCTEON_REQUEST_TIMEOUT) { 21162306a36Sopenharmony_ci dev_err(&oct_dev->pci_dev->dev, "%s: sc has fatal timeout\n", 21262306a36Sopenharmony_ci __func__); 21362306a36Sopenharmony_ci WRITE_ONCE(sc->caller_is_done, true); 21462306a36Sopenharmony_ci errno = -EBUSY; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci return errno; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#ifndef ROUNDUP4 22162306a36Sopenharmony_ci#define ROUNDUP4(val) (((val) + 3) & 0xfffffffc) 22262306a36Sopenharmony_ci#endif 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci#ifndef ROUNDUP8 22562306a36Sopenharmony_ci#define ROUNDUP8(val) (((val) + 7) & 0xfffffff8) 22662306a36Sopenharmony_ci#endif 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#ifndef ROUNDUP16 22962306a36Sopenharmony_ci#define ROUNDUP16(val) (((val) + 15) & 0xfffffff0) 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#ifndef ROUNDUP128 23362306a36Sopenharmony_ci#define ROUNDUP128(val) (((val) + 127) & 0xffffff80) 23462306a36Sopenharmony_ci#endif 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci#endif /* _OCTEON_MAIN_H_ */ 237