Commit 8a5068c7 authored by Jens Korinth's avatar Jens Korinth

Backport new VC709 driver to Tapasco

parent 4f9d515b
......@@ -6,7 +6,7 @@ obj-m := ffLink.o
# composition of files needed to compile
# one can exchange dual_dma_ctrl with cdma_dma_ctrl, when dma engine from Xilinx is used
ffLink-objs := pcie_device.o dual_dma_ctrl.o char_device_dma.o char_device_user.o ffLink_driver.o
ffLink-objs := pcie_device.o blue_dma_ctrl.o char_device_dma.o char_device_user.o ffLink_driver.o dual_dma_ctrl.o dma_ctrl.o
# Path to kernel headers for compilation (path to home can be specific to os)
LNX=$(shell uname -r)
......
//
// Copyright (C) 2014 David de la Chevallerie, TU Darmstadt
// Copyright (C) 2017 Jaco A. Hofmann, TU Darmstadt
//
// This file is part of Tapasco (TPC).
//
......@@ -17,8 +17,8 @@
// along with Tapasco. If not, see <http://www.gnu.org/licenses/>.
//
/**
* @file cdma_dma_ctrl.c
* @brief Implementation of Xilinx dma engine specific code
* @file dual_dma_ctrl.c
* @brief Implementation of custom dma engine specific code
Strips the layout of the dma-registers and setup stuff to start a dma transfer
in addition calls to acknowledge the interrupt in hw is given
* */
......@@ -30,21 +30,13 @@
/******************************************************************************/
/* Register Map and commands */
#define REG_CDMACR 0x00 /* slv_reg0 = CDMA Control */
#define REG_CDMASR 0x04 /* slv_reg1 = CDMA Status */
#define REG_CURDESC_PNTR 0x08 /* slv_reg2 = Current Descriptor Pointer */
#define REG_CURDESC_PNTR_MSB 0x0C /* slv_reg3 = Current Descriptor Pointer (MSB 32 bits) */
#define REG_TAILDESC_PNTR 0x10 /* slv_reg4 = Tail Descriptor Pointer */
#define REG_TAILDESC_PNTR_MSB 0x14 /* slv_reg5 = Tail Descriptor Pointer (MSB 32 bits) */
#define REG_SA 0x18 /* slv_reg6 = Source Address */
#define REG_SA_MSB 0x1C /* slv_reg7 = Source Address (MSB 32 bits) */
#define REG_DA 0x20 /* slv_reg8 = Destination Address */
#define REG_DA_MSB 0x24 /* slv_reg9 = Destination Address (MSB 32 bits) */
#define REG_BTT 0x28 /* slv_regA = Bytes to Transfer */
#define REG_HOST_ADDR 0x00 /* slv_reg0 = PCIe addr */
#define REG_FPGA_ADDR 0x08 /* slv_reg1 = FPGA addr */
#define REG_BTT 0x10 /* slv_reg2 = bytes to transfer */
#define REG_CMD 0x20 /* slv_reg3 = CMD */
#define CMD_IRQ_EN 0x00001000 /* enables interrupt for transfers in control register */
#define CMD_ACK 0x00001000 /* acknowledge data transfer to toggle interrupt in status register */
#define PCIE_OFF 0x00000008 /* offset to address pcie core */
#define CMD_READ 0x10001000 /* from m64 fpga memory to m64 host memory */
#define CMD_WRITE 0x10000001 /* from m64 host memory to m64 fpga memory */
/* mutex to sequentialize access to dma registers */
//static DEFINE_MUTEX(dma_regs_mutex);
......@@ -52,73 +44,14 @@
/******************************************************************************/
/* functions for irq-handling */
/**
* @brief Acknowledge interrupt in hardware and wake up corresponding process
* @param i minor node corresponding to this irq
* @return none
* */
void ack_irq(int i)
{
fflink_info("Handle device number %d\n", i);
/* ack interrupt */
pcie_writel(CMD_ACK, get_dev_addr(i) + REG_CDMASR);
/* Set priv data for more minor nodes accordingly */
wake_up_queue(i);
}
/**
* @brief Interrupt handler for dma engine 0
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_0(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(0);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 1
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_1(int irq, void * dev_id)
irqreturn_t blue_dma_intr_handler(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(1);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 2
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_2(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(2);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 3
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_3(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(3);
return IRQ_HANDLED;
}
......@@ -132,24 +65,22 @@ irqreturn_t intr_handler_dma_3(int irq, void * dev_id)
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
void blue_dma_transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_info("dev_buf %lX dma_handle %lX \nsize %d dev_base %lX\n", (unsigned long) device_buffer, (unsigned long) host_handle, btt, (unsigned long) device_base_addr);
//if(mutex_lock_interruptible(&dma_regs_mutex))
// fflink_warn("got killed while aquiring the mutex\n");
/* activate interrupts */
pcie_writel(CMD_IRQ_EN, device_base_addr + REG_CDMACR);
/* SA */
pcie_writel((unsigned long) device_buffer, device_base_addr + REG_SA);
pcie_writel(0, device_base_addr + REG_SA_MSB);
pcie_writel((unsigned long)device_buffer, device_base_addr + REG_FPGA_ADDR);
/* DA */
pcie_writel(host_handle, device_base_addr + REG_DA);
pcie_writel(PCIE_OFF, device_base_addr + REG_DA_MSB);
pcie_writel(host_handle, device_base_addr + REG_HOST_ADDR);
/* btt */
pcie_writel(btt, device_base_addr + REG_BTT);
/* presvious data have to be written first */
wmb();
/* btt and start */
pcie_writel(btt, device_base_addr + REG_BTT);
/* start cmd */
pcie_writel(CMD_READ, device_base_addr + REG_CMD);
//mutex_unlock(&dma_regs_mutex);
}
......@@ -162,24 +93,22 @@ void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt,
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
void blue_dma_transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_info("dev_buf %lX dma_handle %lX \nsize %d dev_base %lX\n", (unsigned long) device_buffer, (unsigned long) host_handle, btt, (unsigned long) device_base_addr);
//if(mutex_lock_interruptible(&dma_regs_mutex))
// fflink_warn("got killed while aquiring the mutex\n");
/* activate interrupts */
pcie_writel(CMD_IRQ_EN, device_base_addr + REG_CDMACR);
/* SA */
pcie_writel(host_handle, device_base_addr + REG_SA);
pcie_writel(PCIE_OFF, device_base_addr + REG_SA_MSB);
pcie_writel(host_handle, device_base_addr + REG_HOST_ADDR);
/* DA */
pcie_writel((unsigned long) device_buffer, device_base_addr + REG_DA);
pcie_writel(0, device_base_addr + REG_DA_MSB);
pcie_writel((unsigned long)device_buffer, device_base_addr + REG_FPGA_ADDR);
/* btt */
pcie_writel(btt, device_base_addr + REG_BTT);
/* presvious data have to be written first */
wmb();
/* btt and start */
pcie_writel(btt, device_base_addr + REG_BTT);
/* start cmd */
pcie_writel(CMD_WRITE, device_base_addr + REG_CMD);
//mutex_unlock(&dma_regs_mutex);
}
......
This diff is collapsed.
......@@ -73,53 +73,31 @@
/******************************************************************************/
/* number of device, which will be created for dma engines */
#define FFLINK_DMA_NODES 1
/* activate double buffering ( == 1) */
#define FFLINK_DOUBLE_BUFFERING 2
/* physical address of dma core in register map from vivado */
#define DMA_BASE_ADDR_0 0x300000
#define DMA_BASE_ADDR_1 0x310000
#define DMA_BASE_ADDR_2 0x320000
#define DMA_BASE_ADDR_3 0x330000
#define AXI_CTRL_BASE_ADDR 0x100000
/* BRAM standard address */
#define RAM_BASE_ADDR_0 0x80000000
#define RAM_BASE_ADDR_1 0xA0000000
#define RAM_BASE_ADDR_2 0xC0000000
#define RAM_BASE_ADDR_3 0xE0000000
/* to change buffer_size increase or decrease the order of pages */
#define BUFFER_ORDER (MAX_ORDER -1)
#define BUFFER_SIZE (PAGE_SIZE * (1 << BUFFER_ORDER))
/* change size, when double buffering becomes activated */
#define DOUBLE_BUFFER_LIMIT 262144
#define BUFFER_SIZE_USED (PAGE_SIZE * (1 << (MAX_ORDER -3)))
/* device name to register fops with
* fops will append a number to name for multiple minor nodes */
#define FFLINK_DMA_NAME "FFLINK_DMA_DEVICE"
/* Count of buffers allocated for each device in each direction */
#define PBUF_SIZE 3
/******************************************************************************/
/* struct array to hold data over multiple fops-calls */
struct priv_data_struct {
unsigned int minor;
struct page * pbuf_h2l[PBUF_SIZE];
struct page * pbuf_l2h[PBUF_SIZE];
void * kvirt_pbuf_h2l[PBUF_SIZE];
void * kvirt_pbuf_l2h[PBUF_SIZE];
dma_addr_t dma_handle_h2l[PBUF_SIZE];
dma_addr_t dma_handle_l2h[PBUF_SIZE];
void * kvirt_h2l;
void * kvirt_l2h;
dma_addr_t dma_handle_h2l;
dma_addr_t dma_handle_l2h;
void * mem_addr_l2h;
void * mem_addr_h2l;
......@@ -133,9 +111,6 @@ struct priv_data_struct {
unsigned int cache_lsize;
unsigned int cache_mask;
struct mutex mmap_rbuf_mutex;
struct mutex mmap_wbuf_mutex;
};
/******************************************************************************/
......@@ -146,28 +121,21 @@ static int dma_close(struct inode *, struct file *);
static long dma_ioctl(struct file *, unsigned int, unsigned long);
static ssize_t dma_read(struct file *, char __user *, size_t count, loff_t *);
static ssize_t dma_write(struct file *, const char __user *, size_t count, loff_t *);
static int dma_mmap(struct file *filp, struct vm_area_struct *vma);
/******************************************************************************/
/* helper functions called for sys-calls */
static void dma_page_to_virt(struct priv_data_struct * p);
static unsigned int dma_cache_fit(unsigned int btt);
static int dma_alloc_pbufs(struct page * p[], dma_addr_t handle[], gfp_t, int);
static void dma_free_pbufs(struct page * p[], dma_addr_t handle[], int direction);
static int dma_alloc_pbufs(void** p, dma_addr_t *handle, gfp_t zone, int direction);
static void dma_free_pbufs(void *p, dma_addr_t handle, int direction);
static void transmit_to_user(void *, void *, dma_addr_t, int);
static void transmit_from_user(void *, void *, dma_addr_t, int);
static unsigned int calc_transfer_size(int count);
static void switch_index(unsigned int * a, unsigned int * b);
/******************************************************************************/
/* overload function to exchange bounce-/double-buffering */
static int read_with_double(int count, char __user *buf, void * mem_addr, struct priv_data_struct *p);
static int read_with_bounce(int count, char __user *buf, void * mem_addr, struct priv_data_struct *p);
static inline int read_device(int count, char __user *buf, void * mem_addr, struct priv_data_struct *p);
static int write_with_double(int count, const char __user *buf, void * mem_addr, struct priv_data_struct *p);
static int write_with_bounce(int count, const char __user *buf, void * mem_addr, struct priv_data_struct *p);
static inline int write_device(int count, const char __user *buf, void * mem_addr, struct priv_data_struct *p);
......
......@@ -43,6 +43,9 @@ struct pci_dev* get_pcie_dev(void);
void pcie_writel(unsigned long data, void * addr);
unsigned long pcie_readl(void * addr);
void pcie_writel_bar2(unsigned long data, void * addr);
unsigned long pcie_readl_bar2(void * addr);
/******************************************************************************/
#endif // __DEVICE_PCIE_H
......@@ -67,12 +67,10 @@
/******************************************************************************/
void dma_ctrl_init(void * device_base_addr);
/* interrupt handler used by dma engines registered in pcie_device.c */
void ack_irq(int i);
irqreturn_t intr_handler_dma_0(int irq, void * dev_id);
irqreturn_t intr_handler_dma_1(int irq, void * dev_id);
irqreturn_t intr_handler_dma_2(int irq, void * dev_id);
irqreturn_t intr_handler_dma_3(int irq, void * dev_id);
irqreturn_t intr_handler_dma(int irq, void * dev_id);
/* setting registers to start dma transfer specific to used engine (Xilinx, custom) */
void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr);
......@@ -80,4 +78,13 @@ void transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, v
/******************************************************************************/
/* DMA Specific implementations */
irqreturn_t blue_dma_intr_handler(int irq, void * dev_id);
void blue_dma_transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr);
void blue_dma_transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr);
irqreturn_t dual_dma_intr_handler_dma(int irq, void * dev_id);
void dual_dma_transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr);
void dual_dma_transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr);
#endif // __DMA_CTRL_H
//
// Copyright (C) 2017 Jaco A. Hofmann, TU Darmstadt
//
// This file is part of Tapasco (TPC).
//
// Tapasco is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tapasco is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tapasco. If not, see <http://www.gnu.org/licenses/>.
//
/**
* @file dual_dma_ctrl.c
* @brief Implementation of custom dma engine specific code
Strips the layout of the dma-registers and setup stuff to start a dma transfer
in addition calls to acknowledge the interrupt in hw is given
* */
/******************************************************************************/
#include "common/dma_ctrl.h"
/******************************************************************************/
/******************************************************************************/
/* functions for irq-handling */
#define REG_ID 0x18
typedef enum {
DMA_USED_DUAL = 0,
DMA_USED_BLUE = 1
} dma_used_t;
typedef irqreturn_t (*dma_intr_handler)(int , void *);
typedef void (*dma_from_device)(void *, dma_addr_t, int, void *);
typedef void (*dma_to_device)(void *, dma_addr_t , int , void *);
typedef struct {
dma_intr_handler intr;
dma_from_device from_dev;
dma_to_device to_dev;
} fflink_dma_t;
static dma_used_t dma_used;
static const fflink_dma_t fflink_dma[] = {
[DMA_USED_DUAL] = {
dual_dma_intr_handler_dma,
dual_dma_transmit_from_device,
dual_dma_transmit_to_device
},
[DMA_USED_BLUE] = {
blue_dma_intr_handler,
blue_dma_transmit_from_device,
blue_dma_transmit_to_device
}
};
void dma_ctrl_init(void * device_base_addr)
{
if(pcie_readl(device_base_addr + REG_ID) == 0xE5A0023) {
dma_used = DMA_USED_BLUE;
fflink_warn("Detected BlueDMA\n");
} else {
dma_used = DMA_USED_DUAL;
fflink_warn("Detected DualDMA\n");
}
}
/**
* @brief Interrupt handler for dma engine 0
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
fflink_dma[dma_used].intr(irq, dev_id);
wake_up_queue(0);
return IRQ_HANDLED;
}
/******************************************************************************/
/**
* @brief Sets register of dma_engine to start a transfer from FPGA to Main memory
* @param device_buffer FPGA memory address
* @param host_handle Handle for platform independent memory address
* @param btt Bytes to transfer
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_dma[dma_used].from_dev(device_buffer, host_handle, btt, device_base_addr);
}
/**
* @brief Sets register of dma_engine to start a transfer from Main memory to FPGA
* @param device_buffer FPGA memory address
* @param host_handle Handle for platform independent memory address
* @param btt Bytes to transfer
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_dma[dma_used].to_dev(device_buffer, host_handle, btt, device_base_addr);
}
/******************************************************************************/
......@@ -48,73 +48,15 @@
/******************************************************************************/
/* functions for irq-handling */
/**
* @brief Acknowledge interrupt in hardware and wake up corresponding process
* @param i minor node corresponding to this irq
* @return none
* */
void ack_irq(int i)
{
fflink_info("Handle device number %d\n", i);
/* ack interrupt */
pcie_writel(CMD_ACK, get_dev_addr(i) + REG_CMD);
/* Set priv data for more minor nodes accordingly */
wake_up_queue(i);
}
/**
* @brief Interrupt handler for dma engine 0
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_0(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(0);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 1
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_1(int irq, void * dev_id)
irqreturn_t dual_dma_intr_handler_dma(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(1);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 2
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_2(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(2);
return IRQ_HANDLED;
}
/**
* @brief Interrupt handler for dma engine 3
* @param irq Interrupt number of calling line
* @param dev_id magic number for interrupt sharing (not needed)
* @return Tells OS, that irq is handled properly
* */
irqreturn_t intr_handler_dma_3(int irq, void * dev_id)
{
fflink_info("Interrupt called with irq %d\n", irq);
ack_irq(3);
pcie_writel(CMD_ACK, get_dev_addr(0) + REG_CMD);
return IRQ_HANDLED;
}
......@@ -128,7 +70,7 @@ irqreturn_t intr_handler_dma_3(int irq, void * dev_id)
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
void dual_dma_transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_info("dev_buf %lX dma_handle %lX \nsize %d dev_base %lX\n", (unsigned long) device_buffer, (unsigned long) host_handle, btt, (unsigned long) device_base_addr);
//if(mutex_lock_interruptible(&dma_regs_mutex))
......@@ -156,7 +98,7 @@ void transmit_from_device(void * device_buffer, dma_addr_t host_handle, int btt,
* @param device_base_addr Address of dma engine registers
* @return none
* */
void transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
void dual_dma_transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, void * device_base_addr)
{
fflink_info("dev_buf %lX dma_handle %lX \nsize %d dev_base %lX\n", (unsigned long) device_buffer, (unsigned long) host_handle, btt, (unsigned long) device_base_addr);
//if(mutex_lock_interruptible(&dma_regs_mutex))
......@@ -172,7 +114,7 @@ void transmit_to_device(void * device_buffer, dma_addr_t host_handle, int btt, v
wmb();
/* start cmd */
pcie_writel(CMD_WRITE, device_base_addr + REG_CMD);
//mutex_unlock(&dma_regs_mutex);
}
......
......@@ -45,6 +45,12 @@ static int __init fflink_init(void)
fflink_notice("Init char-dev(s), dev-entries and register pci-device\n");
err = pcie_register();
if(err) {
fflink_info("Could not register pcie device\n");
goto error_pcie_register;
}
err = char_dma_register();
if(err) {
fflink_info("Could not register dma char device(s)\n");
......@@ -56,13 +62,7 @@ static int __init fflink_init(void)
fflink_info("Could not register user char device(s)\n");
goto error_user_register;
}
err = pcie_register();
if(err) {
fflink_info("Could not register pcie device\n");
goto error_pcie_register;
}
fflink_warn("Successfully registered driver\n");
return 0;
......
......@@ -21,7 +21,7 @@
* @brief Implementation of all the pcie-device related functions - the code will lookup the dev_id on the pcie-bus
if a matching pcie-device is found, the pcie-device will probed and a basic configuration of the core is done
expects the device to provide a bar0 register space, which will be used for access to its registers afterwards
in addition up to 8 msi interrupts will be allocated for the char-devices of ffLink
in addition at least 8 msi interrupts will be allocated for the char-devices of ffLink
* */
/******************************************************************************/
......@@ -75,8 +75,8 @@ static int claim_device(struct pci_dev *pdev)
fflink_warn("Cannot remap Bar 0 address to kernel space\n");
goto error_pci_remap;
}
fflink_info("Remapped Bar 0 Address is: %llx\n", (unsigned long long int) pci_data.kvirt_addr_bar0);
fflink_info("Remapped Bar 0 Address is: %llx\n", (unsigned long long int) pci_data.kvirt_addr_bar2);
return 0;
error_pci_remap:
......@@ -94,28 +94,19 @@ error_pci_en:
* */
static int configure_device(struct pci_dev *pdev)
{
int err = 0;
//int err = 0;
u16 ctrl_reg = 0;
int mps_start = 0;
/* dma mask to set dma-able area
* currently pci specific code, but could be implemented with dma-api directly */
//err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(DMA_MAX_BIT));
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(DMA_MAX_BIT));
if(err) {
fflink_warn("%u-bit area is not completly dma-able\n", DMA_MAX_BIT);
goto error_pci_dma_mask;
fflink_warn("Trying to find optimal MPS and ReadRQ Settings\n");
for(mps_start = 256; mps_start >= 128; mps_start /= 2) {
if(pcie_set_mps(pdev, mps_start) == 0) break;
}
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(DMA_MAX_BIT));
if(err) {
fflink_warn("%u-bit area is not completly dma-able (consistent)\n", DMA_MAX_BIT);
goto error_pci_dma_mask;
for(mps_start = 4096; mps_start >= 128; mps_start /= 2) {
if(pcie_set_readrq(pdev, mps_start) == 0) break;
}
/* FIXME: Bytes hardcoded and could change with newer kernel versions
* set MPS to 256 Byte (0x20 for 256 or 0x60 for 512) */
pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &ctrl_reg);
fflink_info("Settings of PCI_EXP_DEVCTL: %X\n", ctrl_reg);
pcie_capability_write_word(pdev, PCI_EXP_DEVCTL, ctrl_reg | 0x20);
fflink_warn("Settings of MPS: %d and Maximum Read Request %d\n", pcie_get_mps(pdev), pcie_get_readrq(pdev));
/* set RCB to maximum */
pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &ctrl_reg);
......@@ -124,8 +115,8 @@ static int configure_device(struct pci_dev *pdev)
return 0;
error_pci_dma_mask:
return -EINVAL;
//error_pci_dma_mask:
// return -EINVAL;
}
/**
......@@ -141,47 +132,47 @@ static int register_intr_handler(struct pci_dev *pdev, int c)
* alternatively function will be called from free_irq as well with flag IRQF_SHARED */
switch(c) {
case 0:
err = request_irq(pdev->irq + c, intr_handler_dma_0, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_dma, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 1:
err = request_irq(pdev->irq + c, intr_handler_dma_1, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_dma, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 2:
err = request_irq(pdev->irq + c, intr_handler_dma_2, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_dma, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 3:
err = request_irq(pdev->irq + c, intr_handler_dma_3, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_dma, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 4:
err = request_irq(pdev->irq + c, intr_handler_user_0, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_user_0, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 5:
err = request_irq(pdev->irq + c, intr_handler_user_1, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_user_1, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 6:
err = request_irq(pdev->irq + c, intr_handler_user_2, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_user_2, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
case 7:
err = request_irq(pdev->irq + c, intr_handler_user_3, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pdev->irq + c, err);
err = request_irq(pci_irq_vector(pdev,c), intr_handler_user_3, IRQF_EARLY_RESUME, FFLINK_PCI_NAME, &pci_data);
fflink_notice("Interrupt Line %d assigned with return value %d\n", pci_irq_vector(pdev,c), err);
pci_data.irq_assigned++;
break;
default:
fflink_notice("No more interrupt handler for number (%d)\n", pdev->irq + c);
fflink_notice("No more interrupt handler for number (%d)\n", pci_irq_vector(pdev,c));
break;