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