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