blob: 60445406237c07534b9d4c3108d267e77310b6c7 [file] [log] [blame]
/*********************************************************************
*
* (C) Copyright IBM Corp. 2007,2010
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program 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 General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses>.
*
* Authors: Chris Ward <tjcw@uk.ibm.com>
* Volkmar Uhlig <vuhlig@us.ibm.com>
* Andrew Tauferner <ataufer@us.ibm.com>
*
* Description: Header file for col device
*
*
********************************************************************/
#ifndef __DRIVERS__NET__BLUEGENE__COL_H__
#define __DRIVERS__NET__BLUEGENE__COL_H__
#define KEEP_BG_COL_STATISTICS
#define EXTRA_TUNING
/* #define KEEP_RECV_TOTAL */
#define HAS_MISSED_INTERRUPT_TIMER
#define _BGP_COL_BASE (0x610000000ULL)
#define _BGP_COL_OFFSET (0x001000000ULL)
#define _BGP_COL_SIZE (0x400)
#define _BGP_TORUS_BASE (0x601140000ULL)
#define _BGP_TORUS_OFFSET (0x000010000ULL)
#define BGP_MAX_CHANNEL 2
#define BGP_COL_CHANNEL 0
#define BGP_COL_ADDR_BITS 24
#define COL_CHANNEL_PADDR(c) (_BGP_COL_BASE + ((c)*_BGP_COL_OFFSET))
#define COL_CHANNEL_DCROFF(c) (0x20 + ((c) * 8))
#define COL_DCR_BASE (0xc00)
#define COL_DCR_SIZE (0x80)
#define COL_IRQMASK_INJ (_TR_INJ_PIX_APAR0 | _TR_INJ_PIX_APAR1 |\
_TR_INJ_PIX_ALIGN0 | _TR_INJ_PIX_ALIGN1 |\
_TR_INJ_PIX_ADDR0 | _TR_INJ_PIX_ADDR1 |\
_TR_INJ_PIX_DPAR0 | _TR_INJ_PIX_DPAR1 |\
_TR_INJ_PIX_COLL | _TR_INJ_PIX_UE |\
_TR_INJ_PIX_PFO0 | _TR_INJ_PIX_PFO1 |\
_TR_INJ_PIX_HFO0 | _TR_INJ_PIX_HFO1)
#define COL_IRQMASK_REC (_TR_REC_PRX_APAR0 | _TR_REC_PRX_APAR1 |\
_TR_REC_PRX_ALIGN0 | _TR_REC_PRX_ALIGN1 |\
_TR_REC_PRX_ADDR0 | _TR_REC_PRX_ADDR1 |\
_TR_REC_PRX_COLL | _TR_REC_PRX_UE |\
_TR_REC_PRX_PFU0 | _TR_REC_PRX_PFU1 |\
_TR_REC_PRX_HFU0 | _TR_REC_PRX_HFU1 |\
_TR_REC_PRX_WM0 | _TR_REC_PRX_WM1 )
#define COL_IRQ_RCV_PENDING_MASK(idx) (1U << (1 - idx))
#define COL_IRQ_INJ_PENDING_MASK(idx) (1U << (2 - idx))
#define COL_IRQ_GROUP 5
#define COL_IRQ_BASE 20
#define COL_IRQ_NONCRIT_NUM 20
#define COL_NONCRIT_BASE 0
#define COL_FIFO_SIZE 8
union bgcol_header {
unsigned int raw;
struct {
unsigned int pclass : 4;
unsigned int p2p : 1;
unsigned int irq : 1;
unsigned vector : 24;
unsigned int csum_mode : 2;
} p2p;
struct {
unsigned int pclass : 4;
unsigned int p2p : 1;
unsigned int irq : 1;
unsigned int op : 3;
unsigned int opsize : 7;
unsigned int tag : 14;
unsigned int csum_mode : 2;
} bcast;
} __attribute__((packed));
union bgcol_status {
unsigned int raw;
struct {
unsigned int inj_pkt : 4;
unsigned int inj_qwords : 4;
unsigned int __res0 : 4;
unsigned int inj_hdr : 4;
unsigned int rcv_pkt : 4;
unsigned int rcv_qwords : 4;
unsigned int __res1 : 3;
unsigned int irq : 1;
unsigned int rcv_hdr : 4;
} x;
} __attribute__((packed));
static inline unsigned int bgcol_status_inj_pkt (unsigned int status) { return status >> 28 ; }
static inline unsigned int bgcol_status_inj_qwords(unsigned int status) { return (status >> 24) & 0x0f ; }
static inline unsigned int bgcol_status_inj_hdr (unsigned int status) { return (status >> 16) & 0x0f ; }
static inline unsigned int bgcol_status_rcv_pkt (unsigned int status) { return (status >> 12) & 0x0f ; }
static inline unsigned int bgcol_status_rcv_qwords(unsigned int status) { return (status >> 8 ) & 0x0f ; }
static inline unsigned int bgcol_status_irq (unsigned int status) { return (status >> 4 ) & 1 ; }
static inline unsigned int bgcol_status_rcv_hdr (unsigned int status) { return status & 0x0f ; }
/* some device defined */
#define _BGP_DCR_TR_RCTRL (_BGP_DCR_TR_CH0_RCTRL - _BGP_DCR_TR_CH0)
#define _BGP_DCR_TR_SCTRL (_BGP_DCR_TR_CH0_SCTRL - _BGP_DCR_TR_CH0)
#define _BGP_DCR_TR_RSTAT (_BGP_DCR_TR_CH0_RSTAT - _BGP_DCR_TR_CH0)
/* hardware specification: 4 bytes address, 256 bytes payload */
#define COL_ALEN 4
#define COL_PAYLOAD 256
#define FRAGMENT_LISTS 256
struct bgpnet_dev
{
int major,minor; /* device major, minor */
unsigned long long physaddr; /* physical address */
struct task_struct* current; /* process holding device */
int signum; /* signal to send holding process */
wait_queue_head_t read_wq;
int read_complete;
void *regs; /* mapped regs (only used with col) */
struct semaphore sem; /* interruptible semaphore */
struct cdev cdev; /* container device? */
};
struct bgcol_channel {
phys_addr_t paddr;
unsigned long mioaddr;
unsigned int dcrbase;
unsigned long irq_rcv_pending_mask;
unsigned long irq_inj_pending_mask;
struct timer_list inj_timer;
unsigned int injected;
unsigned int partial_injections;
unsigned int unaligned_hdr_injections;
unsigned int unaligned_data_injections;
unsigned int received;
unsigned int inject_fail;
unsigned int dropped;
unsigned int delivered;
unsigned int idx;
struct bg_col* col;
struct bgpnet_dev* chrdev;
};
enum {
k_ethkey_table_size=256
};
struct bg_col_per_eth {
unsigned char * payload ;
unsigned int expect ;
};
struct bg_col {
spinlock_t lock;
spinlock_t irq_lock;
struct bgcol_channel chn[BGP_MAX_CHANNEL];
unsigned int dcrbase;
unsigned int curr_conn;
unsigned int nodeid;
unsigned int inj_wm_mask;
unsigned int bgnet_channel ;
unsigned int max_packets_per_frame ;
unsigned int mtu ;
unsigned int eth_is_up ;
/* statistics */
unsigned fragment_timeout;
/* Interrupt management */
unsigned int handler_running ;
unsigned int skip_fp_save ;
/* Transmission items */
struct bglink_hdr_col lnkhdr_xmit __attribute__((aligned(8))); /* Link header being used for partially-sent skb */
spinlock_t irq_lock_xmit ;
struct sk_buff_head skb_list_xmit ; /* List of skb's to be sent */
struct sk_buff_head skb_list_free ; /* Keep a list of skb's to free at user level */
struct sk_buff * skb_current_xmit ; /* Partially-sent skb, if any */
void * current_xmit_data ; /* Data from current skb adjusted for alignment */
int current_xmit_len ; /* Length of current skb data */
union bgcol_header dest_xmit ;
unsigned int fragidx_xmit ;
/* Reception items */
struct bglink_hdr_col lnkhdr_rcv __attribute__((aligned(8))); /* Link header pulled out of reception FIFO */
struct sk_buff_head fragskb_list_rcv ; /* List of fully-received frames */
struct sk_buff_head fragskb_list_discard ; /* List of frames to discard */
struct sk_buff * skb_in_waiting ; /* An skb ready to catch the start of a 'new' frame */
struct sk_buff * skb_mini ; /* A 'miniature' skbuff just right for catching single-packet frames */
/* Core-to-core items */
struct sk_buff_head skb_list_for_filling ;
struct sk_buff_head skb_list_for_delivering ;
struct sk_buff_head skb_list_for_freeing ;
unsigned int deliver_without_workqueue ; /* Whether to activate the 'deliver on other core' code for an skbuff */
struct bgnet_dev *bgnet ;
/* Statistics */
int recv_total ;
int recv_guess_miss ;
int recv_no_skbuff ;
int recv_no_first_packet ;
/* 'big' tables */
struct bg_col_per_eth per_eth_table[k_ethkey_table_size] ;
struct sk_buff * skb_rcv_table[k_ethkey_table_size] ;
/* Tuning statistics */
#if defined(KEEP_BG_COL_STATISTICS)
unsigned int send_fifo_histogram0[16] ;
unsigned int send_fifo_histogram1[16] ;
unsigned int recv_fifo_histogram0[16] ;
unsigned int recv_fifo_histogram1[16] ;
#if defined(EXTRA_TUNING)
unsigned int send_fifo_histogram2[16] ;
unsigned int recv_fifo_histogram2[16] ;
#endif
#endif
unsigned int spurious_interrupts ;
/* Diagnostic controls */
struct ctl_table_header * sysctl_table_header ;
#if defined(HAS_MISSED_INTERRUPT_TIMER)
struct timer_list missed_interrupt_timer ;
#endif
};
/**********************************************************************
* driver
**********************************************************************/
#define COL_DEV_NAME "bgcol"
extern int bgcol_debug_tracemask ;
struct bg_col;
struct bg_col *bgcol_get_dev(void);
void bgcol_enable_interrupts(struct bg_col* col);
unsigned int bgcol_get_nodeid(struct bg_col* col);
void bgcol_link_hdr_init(struct bglink_hdr_col *lnkhdr);
int bgcol_xmit(struct bg_col *col, int chnidx, union bgcol_header dest,
struct bglink_hdr_col *lnkhdr, void *data, int len);
int __bgcol_xmit(struct bg_col *col, int chnidx, union bgcol_header dest,
struct bglink_hdr_col *lnkhdr, void *data, int len);
void bgcol_set_mtu(struct bg_col* col, unsigned int mtu) ;
void bgcol_enable_inj_wm_interrupt(struct bgcol_channel* chn);
void bgcol_disable_inj_wm_interrupt(struct bgcol_channel* chn);
void bgcol_enable_rcv_wm_interrupt(struct bgcol_channel* chn);
void bgcol_disable_rcv_wm_interrupt(struct bgcol_channel* chn);
void bgcol_duplex_slih(unsigned long dummy) ;
int col_start_xmit(struct sk_buff *skb, struct net_device *dev);
int __init bgcol_module_init(void) ;
enum {
bgcol_diagnostic_use_napi = 1
};
void bgcol_eth_up(struct bg_col* col) ;
void bgcol_eth_down(struct bg_col* col) ;
void bgcol_align_timebase(void) ;
/* extern int bgcol_diagnostic_use_napi ; */
#endif