octeon_nic.h 7.9 KB
Newer Older
1 2 3 4 5 6
/**********************************************************************
 * Author: Cavium, Inc.
 *
 * Contact: support@cavium.com
 *          Please include "LiquidIO" in the subject.
 *
7
 * Copyright (c) 2003-2016 Cavium, Inc.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, Version 2, as
 * published by the Free Software Foundation.
 *
 * This file is distributed in the hope that it will be useful, but
 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
 * NONINFRINGEMENT.  See the GNU General Public License for more
 * details.
 **********************************************************************/

/*!  \file octeon_nic.h
 *   \brief Host NIC Driver: Routine to send network data &
 *   control packet to Octeon.
 */

#ifndef __OCTEON_NIC_H__
#define  __OCTEON_NIC_H__

/* Maximum number of 8-byte words can be sent in a NIC control message.
 */
#define  MAX_NCTRL_UDD  32

typedef void (*octnic_ctrl_pkt_cb_fn_t) (void *);

/* Structure of control information passed by the NIC module to the OSI
 * layer when sending control commands to Octeon device software.
 */
struct octnic_ctrl_pkt {
	/** Command to be passed to the Octeon device software. */
	union octnet_cmd ncmd;

	/** Send buffer  */
	void *data;
	u64 dmadata;

	/** Response buffer */
	void *rdata;
	u64 dmardata;

	/** Additional data that may be needed by some commands. */
	u64 udd[MAX_NCTRL_UDD];

52 53 54
	/** Input queue to use to send this command. */
	u64 iq_no;

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
	/** Time to wait for Octeon software to respond to this control command.
	 *  If wait_time is 0, OSI assumes no response is expected.
	 */
	size_t wait_time;

	/** The network device that issued the control command. */
	u64 netpndev;

	/** Callback function called when the command has been fetched */
	octnic_ctrl_pkt_cb_fn_t cb_fn;
};

#define MAX_UDD_SIZE(nctrl) (sizeof(nctrl->udd))

/** Structure of data information passed by the NIC module to the OSI
 * layer when forwarding data to Octeon device software.
 */
struct octnic_data_pkt {
	/** Pointer to information maintained by NIC module for this packet. The
	 *  OSI layer passes this as-is to the driver.
	 */
	void *buf;

	/** Type of buffer passed in "buf" above. */
	u32 reqtype;

	/** Total data bytes to be transferred in this command. */
	u32 datasize;

	/** Command to be passed to the Octeon device software. */
85
	union octeon_instr_64B cmd;
86 87 88 89 90 91 92 93 94 95 96

	/** Input queue to use to send this command. */
	u32 q_no;

};

/** Structure passed by NIC module to OSI layer to prepare a command to send
 * network data to Octeon.
 */
union octnic_cmd_setup {
	struct {
97
		u32 iq_no:8;
98 99 100
		u32 gather:1;
		u32 timestamp:1;
		u32 ip_csum:1;
101
		u32 transport_csum:1;
102
		u32 tnl_csum:1;
103
		u32 rsvd:19;
104

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
		union {
			u32 datasize;
			u32 gatherptrs;
		} u;
	} s;

	u64 u64;

};

static inline int octnet_iq_is_full(struct octeon_device *oct, u32 q_no)
{
	return ((u32)atomic_read(&oct->instr_queue[q_no]->instr_pending)
		>= (oct->instr_queue[q_no]->max_count - 2));
}

static inline void
122 123 124
octnet_prepare_pci_cmd_o2(struct octeon_device *oct,
			  union octeon_instr_64B *cmd,
			  union octnic_cmd_setup *setup, u32 tag)
125
{
126
	struct octeon_instr_ih2 *ih2;
127 128
	struct octeon_instr_irh *irh;
	union octnic_packet_params packet_params;
129
	int port;
130

131
	memset(cmd, 0, sizeof(union octeon_instr_64B));
132

133
	ih2 = (struct octeon_instr_ih2 *)&cmd->cmd2.ih2;
134 135

	/* assume that rflag is cleared so therefore front data will only have
136
	 * irh and ossp[0], ossp[1] for a total of 32 bytes
137
	 */
138
	ih2->fsz = LIO_PCICMD_O2;
139

140 141
	ih2->tagtype = ORDERED_TAG;
	ih2->grp = DEFAULT_POW_GRP;
142

143 144
	port = (int)oct->instr_queue[setup->s.iq_no]->txpciq.s.port;

145
	if (tag)
146
		ih2->tag = tag;
147
	else
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
		ih2->tag = LIO_DATA(port);

	ih2->raw = 1;
	ih2->qos = (port & 3) + 4;	/* map qos based on interface */

	if (!setup->s.gather) {
		ih2->dlengsz = setup->s.u.datasize;
	} else {
		ih2->gather = 1;
		ih2->dlengsz = setup->s.u.gatherptrs;
	}

	irh = (struct octeon_instr_irh *)&cmd->cmd2.irh;

	irh->opcode = OPCODE_NIC;
	irh->subcode = OPCODE_NIC_NW_DATA;

	packet_params.u32 = 0;

	packet_params.s.ip_csum = setup->s.ip_csum;
	packet_params.s.transport_csum = setup->s.transport_csum;
	packet_params.s.tnl_csum = setup->s.tnl_csum;
	packet_params.s.tsflag = setup->s.timestamp;

	irh->ossp = packet_params.u32;
}

static inline void
octnet_prepare_pci_cmd_o3(struct octeon_device *oct,
			  union octeon_instr_64B *cmd,
			  union octnic_cmd_setup *setup, u32 tag)
{
	struct octeon_instr_irh *irh;
	struct octeon_instr_ih3     *ih3;
	struct octeon_instr_pki_ih3 *pki_ih3;
	union octnic_packet_params packet_params;
	int port;
185

186 187 188 189 190 191 192 193 194 195
	memset(cmd, 0, sizeof(union octeon_instr_64B));

	ih3 = (struct octeon_instr_ih3 *)&cmd->cmd3.ih3;
	pki_ih3 = (struct octeon_instr_pki_ih3 *)&cmd->cmd3.pki_ih3;

	/* assume that rflag is cleared so therefore front data will only have
	 * irh and ossp[1] and ossp[2] for a total of 24 bytes
	 */
	ih3->pkind       = oct->instr_queue[setup->s.iq_no]->txpciq.s.pkind;
	/*PKI IH*/
196
	ih3->fsz = LIO_PCICMD_O3;
197 198

	if (!setup->s.gather) {
199
		ih3->dlengsz = setup->s.u.datasize;
200
	} else {
201 202
		ih3->gather = 1;
		ih3->dlengsz = setup->s.u.gatherptrs;
203 204
	}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	pki_ih3->w       = 1;
	pki_ih3->raw     = 1;
	pki_ih3->utag    = 1;
	pki_ih3->utt     = 1;
	pki_ih3->uqpg    = oct->instr_queue[setup->s.iq_no]->txpciq.s.use_qpg;

	port = (int)oct->instr_queue[setup->s.iq_no]->txpciq.s.port;

	if (tag)
		pki_ih3->tag = tag;
	else
		pki_ih3->tag     = LIO_DATA(port);

	pki_ih3->tagtype = ORDERED_TAG;
	pki_ih3->qpg     = oct->instr_queue[setup->s.iq_no]->txpciq.s.qpg;
	pki_ih3->pm      = 0x7; /*0x7 - meant for Parse nothing, uninterpreted*/
	pki_ih3->sl      = 8;   /* sl will be sizeof(pki_ih3)*/

	irh = (struct octeon_instr_irh *)&cmd->cmd3.irh;
224 225 226 227 228 229 230

	irh->opcode = OPCODE_NIC;
	irh->subcode = OPCODE_NIC_NW_DATA;

	packet_params.u32 = 0;

	packet_params.s.ip_csum = setup->s.ip_csum;
231
	packet_params.s.transport_csum = setup->s.transport_csum;
232 233 234 235 236 237
	packet_params.s.tnl_csum = setup->s.tnl_csum;
	packet_params.s.tsflag = setup->s.timestamp;

	irh->ossp = packet_params.u32;
}

238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/** Utility function to prepare a 64B NIC instruction based on a setup command
 * @param cmd - pointer to instruction to be filled in.
 * @param setup - pointer to the setup structure
 * @param q_no - which queue for back pressure
 *
 * Assumes the cmd instruction is pre-allocated, but no fields are filled in.
 */
static inline void
octnet_prepare_pci_cmd(struct octeon_device *oct, union octeon_instr_64B *cmd,
		       union octnic_cmd_setup *setup, u32 tag)
{
	if (OCTEON_CN6XXX(oct))
		octnet_prepare_pci_cmd_o2(oct, cmd, setup, tag);
	else
		octnet_prepare_pci_cmd_o3(oct, cmd, setup, tag);
}

255 256 257 258 259 260 261 262 263 264 265 266
/** Allocate and a soft command with space for a response immediately following
 * the commnad.
 * @param oct - octeon device pointer
 * @param cmd - pointer to the command structure, pre-filled for everything
 * except the response.
 * @param rdatasize - size in bytes of the response.
 *
 * @returns pointer to allocated buffer with command copied into it, and
 * response space immediately following.
 */
void *
octeon_alloc_soft_command_resp(struct octeon_device    *oct,
267 268
			       union octeon_instr_64B *cmd,
			       u32		       rdatasize);
269 270 271 272 273 274 275 276 277

/** Send a NIC data packet to the device
 * @param oct - octeon device pointer
 * @param ndata - control structure with queueing, and buffer information
 *
 * @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the
 * queue should be stopped, and IQ_SEND_OK if it sent okay.
 */
int octnet_send_nic_data_pkt(struct octeon_device *oct,
278
			     struct octnic_data_pkt *ndata);
279 280 281 282 283 284 285 286 287

/** Send a NIC control packet to the device
 * @param oct - octeon device pointer
 * @param nctrl - control structure with command, timout, and callback info
 * @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the
 * queue should be stopped, and IQ_SEND_OK if it sent okay.
 */
int
octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
288
			 struct octnic_ctrl_pkt *nctrl);
289 290

#endif