mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-21 10:05:00 +08:00
f21fb3ed36
Following patch V8 adds support for Cavium Liquidio pci express based 10Gig ethernet adapters. 1) Consolidated all debug macros to either call dev_* or netdev_* macros directly, feedback from previous patch. 2) Changed soft commands to avoid crash when running in interrupt context. 3) Fixed link status not reflecting correct status when NetworkManager is running. Added MODULE_FIRMWARE declarations. Following were the previous patches. Patch V7: 1) Minor comments from v6 release regarding debug statements. 2) Fix for large multicast lists. 3) Fixed lockup issue if port initialization fails. 4) Enabled MSI by default. https://patchwork.ozlabs.org/patch/464441/ Patch V6: 1) Addressed the uint64 vs u64 issue, feedback from previous patch. 2) Consolidated some receive processing routines. 3) Removed link status polling method. https://patchwork.ozlabs.org/patch/459514/ Patch V5: Based on the feedback from earlier patches with regards to consolidation of common functions like device init, register programming for cn66xx and cn68xx devices. https://patchwork.ozlabs.org/patch/438979/ Patch V4: Following were the changes based on the feedback from earlier patch: 1) Added mmiowb while synchronizing queue updates and other hw interactions. 2) Statistics will now be incremented non-atomically per each ring. liquidio_get_stats will add stats of each ring while reporting the total statistics counts. 3) Modified liquidio_ioctl to return proper return codes. 4) Modified device naming to use standard Ethernet naming. 5) Global function names in the driver will have lio_/liquidio_/octeon_ prefix. 6) Ethtool related changes for: Removed redundant stats and jiffies. Use default ethtool handler of link status. Speed setting will make use of ethtool_cmd_speed_set. 7) Added checks for pci_map_* return codes. 8) Check for signals while waiting in interruptible mode https://patchwork.ozlabs.org/patch/435073/ Patch v3: Implemented feedback from previous patch like: Removed NAPI Config and DEBUG config options, added BQL and xmit_more support. https://patchwork.ozlabs.org/patch/422749/ Patch V2: Implemented feedback from previous patch. https://patchwork.ozlabs.org/patch/413539/ First Patch: https://patchwork.ozlabs.org/patch/412946/ Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com> Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com> Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com> Signed-off-by: Robert Richter <Robert.Richter@caviumnetworks.com> Signed-off-by: Aleksey Makarov <Aleksey.Makarov@caviumnetworks.com> Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
238 lines
5.9 KiB
C
238 lines
5.9 KiB
C
/**********************************************************************
|
|
* Author: Cavium, Inc.
|
|
*
|
|
* Contact: support@cavium.com
|
|
* Please include "LiquidIO" in the subject.
|
|
*
|
|
* Copyright (c) 2003-2015 Cavium, Inc.
|
|
*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, Version 2, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This file is distributed in the hope that it will be useful, but
|
|
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
|
|
* NONINFRINGEMENT. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* This file may also be available under a different license from Cavium.
|
|
* Contact Cavium, Inc. for more information
|
|
**********************************************************************/
|
|
|
|
/*! \file octeon_main.h
|
|
* \brief Host Driver: This file is included by all host driver source files
|
|
* to include common definitions.
|
|
*/
|
|
|
|
#ifndef _OCTEON_MAIN_H_
|
|
#define _OCTEON_MAIN_H_
|
|
|
|
#if BITS_PER_LONG == 32
|
|
#define CVM_CAST64(v) ((long long)(v))
|
|
#elif BITS_PER_LONG == 64
|
|
#define CVM_CAST64(v) ((long long)(long)(v))
|
|
#else
|
|
#error "Unknown system architecture"
|
|
#endif
|
|
|
|
#define DRV_NAME "LiquidIO"
|
|
|
|
/**
|
|
* \brief determines if a given console has debug enabled.
|
|
* @param console console to check
|
|
* @returns 1 = enabled. 0 otherwise
|
|
*/
|
|
int octeon_console_debug_enabled(u32 console);
|
|
|
|
/* BQL-related functions */
|
|
void octeon_report_sent_bytes_to_bql(void *buf, int reqtype);
|
|
void octeon_update_tx_completion_counters(void *buf, int reqtype,
|
|
unsigned int *pkts_compl,
|
|
unsigned int *bytes_compl);
|
|
void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
|
|
unsigned int bytes_compl);
|
|
|
|
/** Swap 8B blocks */
|
|
static inline void octeon_swap_8B_data(u64 *data, u32 blocks)
|
|
{
|
|
while (blocks) {
|
|
cpu_to_be64s(data);
|
|
blocks--;
|
|
data++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief unmaps a PCI BAR
|
|
* @param oct Pointer to Octeon device
|
|
* @param baridx bar index
|
|
*/
|
|
static inline void octeon_unmap_pci_barx(struct octeon_device *oct, int baridx)
|
|
{
|
|
dev_dbg(&oct->pci_dev->dev, "Freeing PCI mapped regions for Bar%d\n",
|
|
baridx);
|
|
|
|
if (oct->mmio[baridx].done)
|
|
iounmap(oct->mmio[baridx].hw_addr);
|
|
|
|
if (oct->mmio[baridx].start)
|
|
pci_release_region(oct->pci_dev, baridx * 2);
|
|
}
|
|
|
|
/**
|
|
* \brief maps a PCI BAR
|
|
* @param oct Pointer to Octeon device
|
|
* @param baridx bar index
|
|
* @param max_map_len maximum length of mapped memory
|
|
*/
|
|
static inline int octeon_map_pci_barx(struct octeon_device *oct,
|
|
int baridx, int max_map_len)
|
|
{
|
|
u32 mapped_len = 0;
|
|
|
|
if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
|
|
dev_err(&oct->pci_dev->dev, "pci_request_region failed for bar %d\n",
|
|
baridx);
|
|
return 1;
|
|
}
|
|
|
|
oct->mmio[baridx].start = pci_resource_start(oct->pci_dev, baridx * 2);
|
|
oct->mmio[baridx].len = pci_resource_len(oct->pci_dev, baridx * 2);
|
|
|
|
mapped_len = oct->mmio[baridx].len;
|
|
if (!mapped_len)
|
|
return 1;
|
|
|
|
if (max_map_len && (mapped_len > max_map_len))
|
|
mapped_len = max_map_len;
|
|
|
|
oct->mmio[baridx].hw_addr =
|
|
ioremap(oct->mmio[baridx].start, mapped_len);
|
|
oct->mmio[baridx].mapped_len = mapped_len;
|
|
|
|
dev_dbg(&oct->pci_dev->dev, "BAR%d start: 0x%llx mapped %u of %u bytes\n",
|
|
baridx, oct->mmio[baridx].start, mapped_len,
|
|
oct->mmio[baridx].len);
|
|
|
|
if (!oct->mmio[baridx].hw_addr) {
|
|
dev_err(&oct->pci_dev->dev, "error ioremap for bar %d\n",
|
|
baridx);
|
|
return 1;
|
|
}
|
|
oct->mmio[baridx].done = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void *
|
|
cnnic_alloc_aligned_dma(struct pci_dev *pci_dev,
|
|
u32 size,
|
|
u32 *alloc_size,
|
|
size_t *orig_ptr,
|
|
size_t *dma_addr __attribute__((unused)))
|
|
{
|
|
int retries = 0;
|
|
void *ptr = NULL;
|
|
|
|
#define OCTEON_MAX_ALLOC_RETRIES 1
|
|
do {
|
|
ptr =
|
|
(void *)__get_free_pages(GFP_KERNEL,
|
|
get_order(size));
|
|
if ((unsigned long)ptr & 0x07) {
|
|
free_pages((unsigned long)ptr, get_order(size));
|
|
ptr = NULL;
|
|
/* Increment the size required if the first
|
|
* attempt failed.
|
|
*/
|
|
if (!retries)
|
|
size += 7;
|
|
}
|
|
retries++;
|
|
} while ((retries <= OCTEON_MAX_ALLOC_RETRIES) && !ptr);
|
|
|
|
*alloc_size = size;
|
|
*orig_ptr = (unsigned long)ptr;
|
|
if ((unsigned long)ptr & 0x07)
|
|
ptr = (void *)(((unsigned long)ptr + 7) & ~(7UL));
|
|
return ptr;
|
|
}
|
|
|
|
#define cnnic_free_aligned_dma(pci_dev, ptr, size, orig_ptr, dma_addr) \
|
|
free_pages(orig_ptr, get_order(size))
|
|
|
|
static inline void
|
|
sleep_cond(wait_queue_head_t *wait_queue, int *condition)
|
|
{
|
|
wait_queue_t we;
|
|
|
|
init_waitqueue_entry(&we, current);
|
|
add_wait_queue(wait_queue, &we);
|
|
while (!(ACCESS_ONCE(*condition))) {
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
if (signal_pending(current))
|
|
goto out;
|
|
schedule();
|
|
}
|
|
out:
|
|
set_current_state(TASK_RUNNING);
|
|
remove_wait_queue(wait_queue, &we);
|
|
}
|
|
|
|
static inline void
|
|
sleep_atomic_cond(wait_queue_head_t *waitq, atomic_t *pcond)
|
|
{
|
|
wait_queue_t we;
|
|
|
|
init_waitqueue_entry(&we, current);
|
|
add_wait_queue(waitq, &we);
|
|
while (!atomic_read(pcond)) {
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
if (signal_pending(current))
|
|
goto out;
|
|
schedule();
|
|
}
|
|
out:
|
|
set_current_state(TASK_RUNNING);
|
|
remove_wait_queue(waitq, &we);
|
|
}
|
|
|
|
/* Gives up the CPU for a timeout period.
|
|
* Check that the condition is not true before we go to sleep for a
|
|
* timeout period.
|
|
*/
|
|
static inline void
|
|
sleep_timeout_cond(wait_queue_head_t *wait_queue,
|
|
int *condition,
|
|
int timeout)
|
|
{
|
|
wait_queue_t we;
|
|
|
|
init_waitqueue_entry(&we, current);
|
|
add_wait_queue(wait_queue, &we);
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
if (!(*condition))
|
|
schedule_timeout(timeout);
|
|
set_current_state(TASK_RUNNING);
|
|
remove_wait_queue(wait_queue, &we);
|
|
}
|
|
|
|
#ifndef ROUNDUP4
|
|
#define ROUNDUP4(val) (((val) + 3) & 0xfffffffc)
|
|
#endif
|
|
|
|
#ifndef ROUNDUP8
|
|
#define ROUNDUP8(val) (((val) + 7) & 0xfffffff8)
|
|
#endif
|
|
|
|
#ifndef ROUNDUP16
|
|
#define ROUNDUP16(val) (((val) + 15) & 0xfffffff0)
|
|
#endif
|
|
|
|
#ifndef ROUNDUP128
|
|
#define ROUNDUP128(val) (((val) + 127) & 0xffffff80)
|
|
#endif
|
|
|
|
#endif /* _OCTEON_MAIN_H_ */
|