162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2006-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#ifndef _CXGB3_OFFLOAD_H 3362306a36Sopenharmony_ci#define _CXGB3_OFFLOAD_H 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/list.h> 3662306a36Sopenharmony_ci#include <linux/skbuff.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include "l2t.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include "t3cdev.h" 4162306a36Sopenharmony_ci#include "t3_cpl.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct adapter; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_civoid cxgb3_offload_init(void); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_civoid cxgb3_adapter_ofld(struct adapter *adapter); 4862306a36Sopenharmony_civoid cxgb3_adapter_unofld(struct adapter *adapter); 4962306a36Sopenharmony_ciint cxgb3_offload_activate(struct adapter *adapter); 5062306a36Sopenharmony_civoid cxgb3_offload_deactivate(struct adapter *adapter); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_civoid cxgb3_set_dummy_ops(struct t3cdev *dev); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistruct t3cdev *dev2t3cdev(struct net_device *dev); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Client registration. Users of T3 driver must register themselves. 5862306a36Sopenharmony_ci * The T3 driver will call the add function of every client for each T3 5962306a36Sopenharmony_ci * adapter activated, passing up the t3cdev ptr. Each client fills out an 6062306a36Sopenharmony_ci * array of callback functions to process CPL messages. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_civoid cxgb3_register_client(struct cxgb3_client *client); 6462306a36Sopenharmony_civoid cxgb3_unregister_client(struct cxgb3_client *client); 6562306a36Sopenharmony_civoid cxgb3_add_clients(struct t3cdev *tdev); 6662306a36Sopenharmony_civoid cxgb3_remove_clients(struct t3cdev *tdev); 6762306a36Sopenharmony_civoid cxgb3_event_notify(struct t3cdev *tdev, u32 event, u32 port); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_citypedef int (*cxgb3_cpl_handler_func)(struct t3cdev *dev, 7062306a36Sopenharmony_ci struct sk_buff *skb, void *ctx); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cienum { 7362306a36Sopenharmony_ci OFFLOAD_STATUS_UP, 7462306a36Sopenharmony_ci OFFLOAD_STATUS_DOWN, 7562306a36Sopenharmony_ci OFFLOAD_PORT_DOWN, 7662306a36Sopenharmony_ci OFFLOAD_PORT_UP, 7762306a36Sopenharmony_ci OFFLOAD_DB_FULL, 7862306a36Sopenharmony_ci OFFLOAD_DB_EMPTY, 7962306a36Sopenharmony_ci OFFLOAD_DB_DROP 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct cxgb3_client { 8362306a36Sopenharmony_ci char *name; 8462306a36Sopenharmony_ci void (*add) (struct t3cdev *); 8562306a36Sopenharmony_ci void (*remove) (struct t3cdev *); 8662306a36Sopenharmony_ci cxgb3_cpl_handler_func *handlers; 8762306a36Sopenharmony_ci int (*redirect)(void *ctx, struct dst_entry *old, 8862306a36Sopenharmony_ci struct dst_entry *new, struct l2t_entry *l2t); 8962306a36Sopenharmony_ci struct list_head client_list; 9062306a36Sopenharmony_ci void (*event_handler)(struct t3cdev *tdev, u32 event, u32 port); 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 9462306a36Sopenharmony_ci * TID allocation services. 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ciint cxgb3_alloc_atid(struct t3cdev *dev, struct cxgb3_client *client, 9762306a36Sopenharmony_ci void *ctx); 9862306a36Sopenharmony_ciint cxgb3_alloc_stid(struct t3cdev *dev, struct cxgb3_client *client, 9962306a36Sopenharmony_ci void *ctx); 10062306a36Sopenharmony_civoid *cxgb3_free_atid(struct t3cdev *dev, int atid); 10162306a36Sopenharmony_civoid cxgb3_free_stid(struct t3cdev *dev, int stid); 10262306a36Sopenharmony_civoid cxgb3_insert_tid(struct t3cdev *dev, struct cxgb3_client *client, 10362306a36Sopenharmony_ci void *ctx, unsigned int tid); 10462306a36Sopenharmony_civoid cxgb3_queue_tid_release(struct t3cdev *dev, unsigned int tid); 10562306a36Sopenharmony_civoid cxgb3_remove_tid(struct t3cdev *dev, void *ctx, unsigned int tid); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistruct t3c_tid_entry { 10862306a36Sopenharmony_ci struct cxgb3_client *client; 10962306a36Sopenharmony_ci void *ctx; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* CPL message priority levels */ 11362306a36Sopenharmony_cienum { 11462306a36Sopenharmony_ci CPL_PRIORITY_DATA = 0, /* data messages */ 11562306a36Sopenharmony_ci CPL_PRIORITY_SETUP = 1, /* connection setup messages */ 11662306a36Sopenharmony_ci CPL_PRIORITY_TEARDOWN = 0, /* connection teardown messages */ 11762306a36Sopenharmony_ci CPL_PRIORITY_LISTEN = 1, /* listen start/stop messages */ 11862306a36Sopenharmony_ci CPL_PRIORITY_ACK = 1, /* RX ACK messages */ 11962306a36Sopenharmony_ci CPL_PRIORITY_CONTROL = 1 /* offload control messages */ 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* Flags for return value of CPL message handlers */ 12362306a36Sopenharmony_cienum { 12462306a36Sopenharmony_ci CPL_RET_BUF_DONE = 1, /* buffer processing done, buffer may be freed */ 12562306a36Sopenharmony_ci CPL_RET_BAD_MSG = 2, /* bad CPL message (e.g., unknown opcode) */ 12662306a36Sopenharmony_ci CPL_RET_UNKNOWN_TID = 4 /* unexpected unknown TID */ 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_citypedef int (*cpl_handler_func)(struct t3cdev *dev, struct sk_buff *skb); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 13262306a36Sopenharmony_ci * Returns a pointer to the first byte of the CPL header in an sk_buff that 13362306a36Sopenharmony_ci * contains a CPL message. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_cistatic inline void *cplhdr(struct sk_buff *skb) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci return skb->data; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_civoid t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciunion listen_entry { 14362306a36Sopenharmony_ci struct t3c_tid_entry t3c_tid; 14462306a36Sopenharmony_ci union listen_entry *next; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ciunion active_open_entry { 14862306a36Sopenharmony_ci struct t3c_tid_entry t3c_tid; 14962306a36Sopenharmony_ci union active_open_entry *next; 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* 15362306a36Sopenharmony_ci * Holds the size, base address, free list start, etc of the TID, server TID, 15462306a36Sopenharmony_ci * and active-open TID tables for a offload device. 15562306a36Sopenharmony_ci * The tables themselves are allocated dynamically. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cistruct tid_info { 15862306a36Sopenharmony_ci struct t3c_tid_entry *tid_tab; 15962306a36Sopenharmony_ci unsigned int ntids; 16062306a36Sopenharmony_ci atomic_t tids_in_use; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci union listen_entry *stid_tab; 16362306a36Sopenharmony_ci unsigned int nstids; 16462306a36Sopenharmony_ci unsigned int stid_base; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci union active_open_entry *atid_tab; 16762306a36Sopenharmony_ci unsigned int natids; 16862306a36Sopenharmony_ci unsigned int atid_base; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* 17162306a36Sopenharmony_ci * The following members are accessed R/W so we put them in their own 17262306a36Sopenharmony_ci * cache lines. 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * XXX We could combine the atid fields above with the lock here since 17562306a36Sopenharmony_ci * atids are use once (unlike other tids). OTOH the above fields are 17662306a36Sopenharmony_ci * usually in cache due to tid_tab. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci spinlock_t atid_lock ____cacheline_aligned_in_smp; 17962306a36Sopenharmony_ci union active_open_entry *afree; 18062306a36Sopenharmony_ci unsigned int atids_in_use; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci spinlock_t stid_lock ____cacheline_aligned; 18362306a36Sopenharmony_ci union listen_entry *sfree; 18462306a36Sopenharmony_ci unsigned int stids_in_use; 18562306a36Sopenharmony_ci}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistruct t3c_data { 18862306a36Sopenharmony_ci struct list_head list_node; 18962306a36Sopenharmony_ci struct t3cdev *dev; 19062306a36Sopenharmony_ci unsigned int tx_max_chunk; /* max payload for TX_DATA */ 19162306a36Sopenharmony_ci unsigned int max_wrs; /* max in-flight WRs per connection */ 19262306a36Sopenharmony_ci unsigned int nmtus; 19362306a36Sopenharmony_ci const unsigned short *mtus; 19462306a36Sopenharmony_ci struct tid_info tid_maps; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci struct t3c_tid_entry *tid_release_list; 19762306a36Sopenharmony_ci spinlock_t tid_release_lock; 19862306a36Sopenharmony_ci struct work_struct tid_release_task; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci struct sk_buff *nofail_skb; 20162306a36Sopenharmony_ci unsigned int release_list_incomplete; 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci/* 20562306a36Sopenharmony_ci * t3cdev -> t3c_data accessor 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci#define T3C_DATA(dev) (*(struct t3c_data **)&(dev)->l4opt) 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#endif 210