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