162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This software is available to you under a choice of one of two 562306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 662306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 762306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 862306a36Sopenharmony_ci * OpenIB.org BSD license below: 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1162306a36Sopenharmony_ci * without modification, are permitted provided that the following 1262306a36Sopenharmony_ci * conditions are met: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1562306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1662306a36Sopenharmony_ci * disclaimer. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 1962306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2062306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2162306a36Sopenharmony_ci * provided with the distribution. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2462306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2562306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2662306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2762306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2862306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2962306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3062306a36Sopenharmony_ci * SOFTWARE. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* This file should not be included directly. Include common.h instead. */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#ifndef __T3_ADAPTER_H__ 3662306a36Sopenharmony_ci#define __T3_ADAPTER_H__ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <linux/pci.h> 3962306a36Sopenharmony_ci#include <linux/spinlock.h> 4062306a36Sopenharmony_ci#include <linux/interrupt.h> 4162306a36Sopenharmony_ci#include <linux/timer.h> 4262306a36Sopenharmony_ci#include <linux/cache.h> 4362306a36Sopenharmony_ci#include <linux/mutex.h> 4462306a36Sopenharmony_ci#include <linux/bitops.h> 4562306a36Sopenharmony_ci#include "t3cdev.h" 4662306a36Sopenharmony_ci#include <asm/io.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistruct adapter; 4962306a36Sopenharmony_cistruct sge_qset; 5062306a36Sopenharmony_cistruct port_info; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cienum mac_idx_types { 5362306a36Sopenharmony_ci LAN_MAC_IDX = 0, 5462306a36Sopenharmony_ci SAN_MAC_IDX, 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci MAX_MAC_IDX 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct iscsi_config { 6062306a36Sopenharmony_ci __u8 mac_addr[ETH_ALEN]; 6162306a36Sopenharmony_ci __u32 flags; 6262306a36Sopenharmony_ci int (*send)(struct port_info *pi, struct sk_buff **skb); 6362306a36Sopenharmony_ci int (*recv)(struct port_info *pi, struct sk_buff *skb); 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistruct port_info { 6762306a36Sopenharmony_ci struct adapter *adapter; 6862306a36Sopenharmony_ci struct sge_qset *qs; 6962306a36Sopenharmony_ci u8 port_id; 7062306a36Sopenharmony_ci u8 nqsets; 7162306a36Sopenharmony_ci u8 first_qset; 7262306a36Sopenharmony_ci struct cphy phy; 7362306a36Sopenharmony_ci struct cmac mac; 7462306a36Sopenharmony_ci struct link_config link_config; 7562306a36Sopenharmony_ci int activity; 7662306a36Sopenharmony_ci __be32 iscsi_ipv4addr; 7762306a36Sopenharmony_ci struct iscsi_config iscsic; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci int link_fault; /* link fault was detected */ 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cienum { /* adapter flags */ 8362306a36Sopenharmony_ci FULL_INIT_DONE = (1 << 0), 8462306a36Sopenharmony_ci USING_MSI = (1 << 1), 8562306a36Sopenharmony_ci USING_MSIX = (1 << 2), 8662306a36Sopenharmony_ci QUEUES_BOUND = (1 << 3), 8762306a36Sopenharmony_ci TP_PARITY_INIT = (1 << 4), 8862306a36Sopenharmony_ci NAPI_INIT = (1 << 5), 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct fl_pg_chunk { 9262306a36Sopenharmony_ci struct page *page; 9362306a36Sopenharmony_ci void *va; 9462306a36Sopenharmony_ci unsigned int offset; 9562306a36Sopenharmony_ci unsigned long *p_cnt; 9662306a36Sopenharmony_ci dma_addr_t mapping; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct rx_desc; 10062306a36Sopenharmony_cistruct rx_sw_desc; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct sge_fl { /* SGE per free-buffer list state */ 10362306a36Sopenharmony_ci unsigned int buf_size; /* size of each Rx buffer */ 10462306a36Sopenharmony_ci unsigned int credits; /* # of available Rx buffers */ 10562306a36Sopenharmony_ci unsigned int pend_cred; /* new buffers since last FL DB ring */ 10662306a36Sopenharmony_ci unsigned int size; /* capacity of free list */ 10762306a36Sopenharmony_ci unsigned int cidx; /* consumer index */ 10862306a36Sopenharmony_ci unsigned int pidx; /* producer index */ 10962306a36Sopenharmony_ci unsigned int gen; /* free list generation */ 11062306a36Sopenharmony_ci struct fl_pg_chunk pg_chunk;/* page chunk cache */ 11162306a36Sopenharmony_ci unsigned int use_pages; /* whether FL uses pages or sk_buffs */ 11262306a36Sopenharmony_ci unsigned int order; /* order of page allocations */ 11362306a36Sopenharmony_ci unsigned int alloc_size; /* size of allocated buffer */ 11462306a36Sopenharmony_ci struct rx_desc *desc; /* address of HW Rx descriptor ring */ 11562306a36Sopenharmony_ci struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ 11662306a36Sopenharmony_ci dma_addr_t phys_addr; /* physical address of HW ring start */ 11762306a36Sopenharmony_ci unsigned int cntxt_id; /* SGE context id for the free list */ 11862306a36Sopenharmony_ci unsigned long empty; /* # of times queue ran out of buffers */ 11962306a36Sopenharmony_ci unsigned long alloc_failed; /* # of times buffer allocation failed */ 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* 12362306a36Sopenharmony_ci * Bundle size for grouping offload RX packets for delivery to the stack. 12462306a36Sopenharmony_ci * Don't make this too big as we do prefetch on each packet in a bundle. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci# define RX_BUNDLE_SIZE 8 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct rsp_desc; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct sge_rspq { /* state for an SGE response queue */ 13162306a36Sopenharmony_ci unsigned int credits; /* # of pending response credits */ 13262306a36Sopenharmony_ci unsigned int size; /* capacity of response queue */ 13362306a36Sopenharmony_ci unsigned int cidx; /* consumer index */ 13462306a36Sopenharmony_ci unsigned int gen; /* current generation bit */ 13562306a36Sopenharmony_ci unsigned int polling; /* is the queue serviced through NAPI? */ 13662306a36Sopenharmony_ci unsigned int holdoff_tmr; /* interrupt holdoff timer in 100ns */ 13762306a36Sopenharmony_ci unsigned int next_holdoff; /* holdoff time for next interrupt */ 13862306a36Sopenharmony_ci unsigned int rx_recycle_buf; /* whether recycling occurred 13962306a36Sopenharmony_ci within current sop-eop */ 14062306a36Sopenharmony_ci struct rsp_desc *desc; /* address of HW response ring */ 14162306a36Sopenharmony_ci dma_addr_t phys_addr; /* physical address of the ring */ 14262306a36Sopenharmony_ci unsigned int cntxt_id; /* SGE context id for the response q */ 14362306a36Sopenharmony_ci spinlock_t lock; /* guards response processing */ 14462306a36Sopenharmony_ci struct sk_buff_head rx_queue; /* offload packet receive queue */ 14562306a36Sopenharmony_ci struct sk_buff *pg_skb; /* used to build frag list in napi handler */ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci unsigned long offload_pkts; 14862306a36Sopenharmony_ci unsigned long offload_bundles; 14962306a36Sopenharmony_ci unsigned long eth_pkts; /* # of ethernet packets */ 15062306a36Sopenharmony_ci unsigned long pure_rsps; /* # of pure (non-data) responses */ 15162306a36Sopenharmony_ci unsigned long imm_data; /* responses with immediate data */ 15262306a36Sopenharmony_ci unsigned long rx_drops; /* # of packets dropped due to no mem */ 15362306a36Sopenharmony_ci unsigned long async_notif; /* # of asynchronous notification events */ 15462306a36Sopenharmony_ci unsigned long empty; /* # of times queue ran out of credits */ 15562306a36Sopenharmony_ci unsigned long nomem; /* # of responses deferred due to no mem */ 15662306a36Sopenharmony_ci unsigned long unhandled_irqs; /* # of spurious intrs */ 15762306a36Sopenharmony_ci unsigned long starved; 15862306a36Sopenharmony_ci unsigned long restarted; 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistruct tx_desc; 16262306a36Sopenharmony_cistruct tx_sw_desc; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistruct sge_txq { /* state for an SGE Tx queue */ 16562306a36Sopenharmony_ci unsigned long flags; /* HW DMA fetch status */ 16662306a36Sopenharmony_ci unsigned int in_use; /* # of in-use Tx descriptors */ 16762306a36Sopenharmony_ci unsigned int size; /* # of descriptors */ 16862306a36Sopenharmony_ci unsigned int processed; /* total # of descs HW has processed */ 16962306a36Sopenharmony_ci unsigned int cleaned; /* total # of descs SW has reclaimed */ 17062306a36Sopenharmony_ci unsigned int stop_thres; /* SW TX queue suspend threshold */ 17162306a36Sopenharmony_ci unsigned int cidx; /* consumer index */ 17262306a36Sopenharmony_ci unsigned int pidx; /* producer index */ 17362306a36Sopenharmony_ci unsigned int gen; /* current value of generation bit */ 17462306a36Sopenharmony_ci unsigned int unacked; /* Tx descriptors used since last COMPL */ 17562306a36Sopenharmony_ci struct tx_desc *desc; /* address of HW Tx descriptor ring */ 17662306a36Sopenharmony_ci struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */ 17762306a36Sopenharmony_ci spinlock_t lock; /* guards enqueueing of new packets */ 17862306a36Sopenharmony_ci unsigned int token; /* WR token */ 17962306a36Sopenharmony_ci dma_addr_t phys_addr; /* physical address of the ring */ 18062306a36Sopenharmony_ci struct sk_buff_head sendq; /* List of backpressured offload packets */ 18162306a36Sopenharmony_ci struct work_struct qresume_task; /* restarts the queue */ 18262306a36Sopenharmony_ci unsigned int cntxt_id; /* SGE context id for the Tx q */ 18362306a36Sopenharmony_ci unsigned long stops; /* # of times q has been stopped */ 18462306a36Sopenharmony_ci unsigned long restarts; /* # of queue restarts */ 18562306a36Sopenharmony_ci}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cienum { /* per port SGE statistics */ 18862306a36Sopenharmony_ci SGE_PSTAT_TSO, /* # of TSO requests */ 18962306a36Sopenharmony_ci SGE_PSTAT_RX_CSUM_GOOD, /* # of successful RX csum offloads */ 19062306a36Sopenharmony_ci SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ 19162306a36Sopenharmony_ci SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ 19262306a36Sopenharmony_ci SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci SGE_PSTAT_MAX /* must be last */ 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistruct napi_gro_fraginfo; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistruct sge_qset { /* an SGE queue set */ 20062306a36Sopenharmony_ci struct adapter *adap; 20162306a36Sopenharmony_ci struct napi_struct napi; 20262306a36Sopenharmony_ci struct sge_rspq rspq; 20362306a36Sopenharmony_ci struct sge_fl fl[SGE_RXQ_PER_SET]; 20462306a36Sopenharmony_ci struct sge_txq txq[SGE_TXQ_PER_SET]; 20562306a36Sopenharmony_ci int nomem; 20662306a36Sopenharmony_ci void *lro_va; 20762306a36Sopenharmony_ci struct net_device *netdev; 20862306a36Sopenharmony_ci struct netdev_queue *tx_q; /* associated netdev TX queue */ 20962306a36Sopenharmony_ci unsigned long txq_stopped; /* which Tx queues are stopped */ 21062306a36Sopenharmony_ci struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ 21162306a36Sopenharmony_ci struct timer_list rx_reclaim_timer; /* reclaims RX buffers */ 21262306a36Sopenharmony_ci unsigned long port_stats[SGE_PSTAT_MAX]; 21362306a36Sopenharmony_ci} ____cacheline_aligned; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistruct sge { 21662306a36Sopenharmony_ci struct sge_qset qs[SGE_QSETS]; 21762306a36Sopenharmony_ci spinlock_t reg_lock; /* guards non-atomic SGE registers (eg context) */ 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistruct adapter { 22162306a36Sopenharmony_ci struct t3cdev tdev; 22262306a36Sopenharmony_ci struct list_head adapter_list; 22362306a36Sopenharmony_ci void __iomem *regs; 22462306a36Sopenharmony_ci struct pci_dev *pdev; 22562306a36Sopenharmony_ci unsigned long registered_device_map; 22662306a36Sopenharmony_ci unsigned long open_device_map; 22762306a36Sopenharmony_ci unsigned long flags; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci const char *name; 23062306a36Sopenharmony_ci int msg_enable; 23162306a36Sopenharmony_ci unsigned int mmio_len; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci struct adapter_params params; 23462306a36Sopenharmony_ci unsigned int slow_intr_mask; 23562306a36Sopenharmony_ci unsigned long irq_stats[IRQ_NUM_STATS]; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci int msix_nvectors; 23862306a36Sopenharmony_ci struct { 23962306a36Sopenharmony_ci unsigned short vec; 24062306a36Sopenharmony_ci char desc[22]; 24162306a36Sopenharmony_ci } msix_info[SGE_QSETS + 1]; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* T3 modules */ 24462306a36Sopenharmony_ci struct sge sge; 24562306a36Sopenharmony_ci struct mc7 pmrx; 24662306a36Sopenharmony_ci struct mc7 pmtx; 24762306a36Sopenharmony_ci struct mc7 cm; 24862306a36Sopenharmony_ci struct mc5 mc5; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci struct net_device *port[MAX_NPORTS]; 25162306a36Sopenharmony_ci unsigned int check_task_cnt; 25262306a36Sopenharmony_ci struct delayed_work adap_check_task; 25362306a36Sopenharmony_ci struct work_struct ext_intr_handler_task; 25462306a36Sopenharmony_ci struct work_struct fatal_error_handler_task; 25562306a36Sopenharmony_ci struct work_struct link_fault_handler_task; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci struct work_struct db_full_task; 25862306a36Sopenharmony_ci struct work_struct db_empty_task; 25962306a36Sopenharmony_ci struct work_struct db_drop_task; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci struct dentry *debugfs_root; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci struct mutex mdio_lock; 26462306a36Sopenharmony_ci spinlock_t stats_lock; 26562306a36Sopenharmony_ci spinlock_t work_lock; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci struct sk_buff *nofail_skb; 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic inline u32 t3_read_reg(struct adapter *adapter, u32 reg_addr) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci u32 val = readl(adapter->regs + reg_addr); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci CH_DBG(adapter, MMIO, "read register 0x%x value 0x%x\n", reg_addr, val); 27562306a36Sopenharmony_ci return val; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic inline void t3_write_reg(struct adapter *adapter, u32 reg_addr, u32 val) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci CH_DBG(adapter, MMIO, "setting register 0x%x to 0x%x\n", reg_addr, val); 28162306a36Sopenharmony_ci writel(val, adapter->regs + reg_addr); 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic inline struct port_info *adap2pinfo(struct adapter *adap, int idx) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci return netdev_priv(adap->port[idx]); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic inline int phy2portid(struct cphy *phy) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct adapter *adap = phy->adapter; 29262306a36Sopenharmony_ci struct port_info *port0 = adap2pinfo(adap, 0); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return &port0->phy == phy ? 0 : 1; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci#define OFFLOAD_DEVMAP_BIT 15 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci#define tdev2adap(d) container_of(d, struct adapter, tdev) 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic inline int offload_running(struct adapter *adapter) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ciint t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_civoid t3_os_ext_intr_handler(struct adapter *adapter); 30962306a36Sopenharmony_civoid t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, 31062306a36Sopenharmony_ci int speed, int duplex, int fc); 31162306a36Sopenharmony_civoid t3_os_phymod_changed(struct adapter *adap, int port_id); 31262306a36Sopenharmony_civoid t3_os_link_fault(struct adapter *adapter, int port_id, int state); 31362306a36Sopenharmony_civoid t3_os_link_fault_handler(struct adapter *adapter, int port_id); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_civoid t3_sge_start(struct adapter *adap); 31662306a36Sopenharmony_civoid t3_sge_stop_dma(struct adapter *adap); 31762306a36Sopenharmony_civoid t3_sge_stop(struct adapter *adap); 31862306a36Sopenharmony_civoid t3_start_sge_timers(struct adapter *adap); 31962306a36Sopenharmony_civoid t3_stop_sge_timers(struct adapter *adap); 32062306a36Sopenharmony_civoid t3_free_sge_resources(struct adapter *adap); 32162306a36Sopenharmony_civoid t3_sge_err_intr_handler(struct adapter *adapter); 32262306a36Sopenharmony_ciirq_handler_t t3_intr_handler(struct adapter *adap, int polling); 32362306a36Sopenharmony_cinetdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev); 32462306a36Sopenharmony_ciint t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb); 32562306a36Sopenharmony_civoid t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p); 32662306a36Sopenharmony_ciint t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, 32762306a36Sopenharmony_ci int irq_vec_idx, const struct qset_params *p, 32862306a36Sopenharmony_ci int ntxq, struct net_device *dev, 32962306a36Sopenharmony_ci struct netdev_queue *netdevq); 33062306a36Sopenharmony_ciextern struct workqueue_struct *cxgb3_wq; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ciint t3_get_edc_fw(struct cphy *phy, int edc_idx, int size); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci#endif /* __T3_ADAPTER_H__ */ 335