blob: 14dc8c8f47ef6edd2c2659da2fbe8cb300570355 [file] [log] [blame]
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001/******************************************************************************
2 * This software may be used and distributed according to the terms of
3 * the GNU General Public License (GPL), incorporated herein by reference.
4 * Drivers based on or derived from this code fall under the GPL and must
5 * retain the authorship, copyright and license notice. This file is not
6 * a complete program and may only be used when the entire operating
7 * system is licensed under the GPL.
8 * See the file COPYING in this distribution for more information.
9 *
Jon Mason926bd902010-07-15 08:47:26 +000010 * vxge-config.c: Driver for Exar Corp's X3100 Series 10GbE PCIe I/O
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +000011 * Virtualized Server Adapter.
Jon Mason926bd902010-07-15 08:47:26 +000012 * Copyright(c) 2002-2010 Exar Corp.
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +000013 ******************************************************************************/
14#include <linux/vmalloc.h>
15#include <linux/etherdevice.h>
16#include <linux/pci.h>
17#include <linux/pci_hotplug.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +000019
20#include "vxge-traffic.h"
21#include "vxge-config.h"
Jon Mason8424e002010-11-11 04:25:56 +000022#include "vxge-main.h"
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +000023
stephen hemminger42821a52010-10-21 07:50:53 +000024static enum vxge_hw_status
25__vxge_hw_fifo_create(
26 struct __vxge_hw_vpath_handle *vpath_handle,
27 struct vxge_hw_fifo_attr *attr);
28
29static enum vxge_hw_status
30__vxge_hw_fifo_abort(
31 struct __vxge_hw_fifo *fifoh);
32
33static enum vxge_hw_status
34__vxge_hw_fifo_reset(
35 struct __vxge_hw_fifo *ringh);
36
37static enum vxge_hw_status
38__vxge_hw_fifo_delete(
39 struct __vxge_hw_vpath_handle *vpath_handle);
40
41static struct __vxge_hw_blockpool_entry *
42__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *hldev,
43 u32 size);
44
45static void
46__vxge_hw_blockpool_block_free(struct __vxge_hw_device *hldev,
47 struct __vxge_hw_blockpool_entry *entry);
48
49static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
50 void *block_addr,
51 u32 length,
52 struct pci_dev *dma_h,
53 struct pci_dev *acc_handle);
54
55static enum vxge_hw_status
56__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
57 struct __vxge_hw_blockpool *blockpool,
58 u32 pool_size,
59 u32 pool_max);
60
61static void
62__vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool);
63
64static void *
65__vxge_hw_blockpool_malloc(struct __vxge_hw_device *hldev,
66 u32 size,
67 struct vxge_hw_mempool_dma *dma_object);
68
69static void
70__vxge_hw_blockpool_free(struct __vxge_hw_device *hldev,
71 void *memblock,
72 u32 size,
73 struct vxge_hw_mempool_dma *dma_object);
74
75
76static struct __vxge_hw_channel*
77__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
78 enum __vxge_hw_channel_type type, u32 length,
79 u32 per_dtr_space, void *userdata);
80
81static void
82__vxge_hw_channel_free(
83 struct __vxge_hw_channel *channel);
84
85static enum vxge_hw_status
86__vxge_hw_channel_initialize(
87 struct __vxge_hw_channel *channel);
88
89static enum vxge_hw_status
90__vxge_hw_channel_reset(
91 struct __vxge_hw_channel *channel);
92
93static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp);
94
95static enum vxge_hw_status
96__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config);
97
98static enum vxge_hw_status
99__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config);
100
101static void
stephen hemminger42821a52010-10-21 07:50:53 +0000102__vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev);
103
104static enum vxge_hw_status
stephen hemminger42821a52010-10-21 07:50:53 +0000105__vxge_hw_device_initialize(struct __vxge_hw_device *hldev);
106
107static void
108__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev);
109
110static enum vxge_hw_status
111__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev);
112
113static enum vxge_hw_status
114__vxge_hw_device_register_poll(
115 void __iomem *reg,
116 u64 mask, u32 max_millis);
117
118static inline enum vxge_hw_status
119__vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr,
120 u64 mask, u32 max_millis)
121{
122 __vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr);
123 wmb();
124
125 __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr);
126 wmb();
127
128 return __vxge_hw_device_register_poll(addr, mask, max_millis);
129}
130
131static struct vxge_hw_mempool*
132__vxge_hw_mempool_create(struct __vxge_hw_device *devh, u32 memblock_size,
133 u32 item_size, u32 private_size, u32 items_initial,
134 u32 items_max, struct vxge_hw_mempool_cbs *mp_callback,
135 void *userdata);
136static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool);
137
138static enum vxge_hw_status
139__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
140 struct vxge_hw_vpath_stats_hw_info *hw_stats);
141
142static enum vxge_hw_status
143vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vpath_handle);
144
145static enum vxge_hw_status
146__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg);
147
stephen hemminger42821a52010-10-21 07:50:53 +0000148static enum vxge_hw_status
149__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath);
150
151
152static enum vxge_hw_status
153__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *devh, u32 vp_id);
154
stephen hemminger42821a52010-10-21 07:50:53 +0000155static enum vxge_hw_status
156__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh, u32 vp_id);
157
158static void
159__vxge_hw_vp_terminate(struct __vxge_hw_device *devh, u32 vp_id);
160
161static enum vxge_hw_status
162__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
163 u32 operation, u32 offset, u64 *stat);
164
165static enum vxge_hw_status
166__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath,
167 struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats);
168
169static enum vxge_hw_status
170__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
171 struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats);
172
Jon Mason4d2a5b42010-11-11 04:25:54 +0000173static void
174vxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg)
175{
176 u64 val64;
177
178 val64 = readq(&vp_reg->rxmac_vcfg0);
179 val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
180 writeq(val64, &vp_reg->rxmac_vcfg0);
181 val64 = readq(&vp_reg->rxmac_vcfg0);
182
183 return;
184}
185
186/*
187 * vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle
188 */
189int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id)
190{
191 struct vxge_hw_vpath_reg __iomem *vp_reg;
192 struct __vxge_hw_virtualpath *vpath;
193 u64 val64, rxd_count, rxd_spat;
194 int count = 0, total_count = 0;
195
196 vpath = &hldev->virtual_paths[vp_id];
197 vp_reg = vpath->vp_reg;
198
199 vxge_hw_vpath_set_zero_rx_frm_len(vp_reg);
200
201 /* Check that the ring controller for this vpath has enough free RxDs
202 * to send frames to the host. This is done by reading the
203 * PRC_RXD_DOORBELL_VPn register and comparing the read value to the
204 * RXD_SPAT value for the vpath.
205 */
206 val64 = readq(&vp_reg->prc_cfg6);
207 rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1;
208 /* Use a factor of 2 when comparing rxd_count against rxd_spat for some
209 * leg room.
210 */
211 rxd_spat *= 2;
212
213 do {
214 mdelay(1);
215
216 rxd_count = readq(&vp_reg->prc_rxd_doorbell);
217
218 /* Check that the ring controller for this vpath does
219 * not have any frame in its pipeline.
220 */
221 val64 = readq(&vp_reg->frm_in_progress_cnt);
222 if ((rxd_count <= rxd_spat) || (val64 > 0))
223 count = 0;
224 else
225 count++;
226 total_count++;
227 } while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) &&
228 (total_count < VXGE_HW_MAX_POLLING_COUNT));
229
230 if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
231 printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n",
232 __func__);
233
234 return total_count;
235}
236
237/* vxge_hw_device_wait_receive_idle - This function waits until all frames
238 * stored in the frame buffer for each vpath assigned to the given
239 * function (hldev) have been sent to the host.
240 */
241void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev)
242{
243 int i, total_count = 0;
244
245 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
246 if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
247 continue;
248
249 total_count += vxge_hw_vpath_wait_receive_idle(hldev, i);
250 if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
251 break;
252 }
253}
254
Jon Mason8424e002010-11-11 04:25:56 +0000255static enum vxge_hw_status
256vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action,
257 u32 fw_memo, u32 offset, u64 *data0, u64 *data1,
258 u64 *steer_ctrl)
259{
260 struct vxge_hw_vpath_reg __iomem *vp_reg;
261 enum vxge_hw_status status;
262 u64 val64;
263 u32 retry = 0, max_retry = 100;
264
265 vp_reg = vpath->vp_reg;
266
267 if (vpath->vp_open) {
268 max_retry = 3;
269 spin_lock(&vpath->lock);
270 }
271
272 writeq(*data0, &vp_reg->rts_access_steer_data0);
273 writeq(*data1, &vp_reg->rts_access_steer_data1);
274 wmb();
275
276 val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
277 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(fw_memo) |
278 VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset) |
279 VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
280 *steer_ctrl;
281
282 status = __vxge_hw_pio_mem_write64(val64,
283 &vp_reg->rts_access_steer_ctrl,
284 VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
285 VXGE_HW_DEF_DEVICE_POLL_MILLIS);
286
287 /* The __vxge_hw_device_register_poll can udelay for a significant
288 * amount of time, blocking other proccess from the CPU. If it delays
289 * for ~5secs, a NMI error can occur. A way around this is to give up
290 * the processor via msleep, but this is not allowed is under lock.
291 * So, only allow it to sleep for ~4secs if open. Otherwise, delay for
292 * 1sec and sleep for 10ms until the firmware operation has completed
293 * or timed-out.
294 */
295 while ((status != VXGE_HW_OK) && retry++ < max_retry) {
296 if (!vpath->vp_open)
297 msleep(20);
298 status = __vxge_hw_device_register_poll(
299 &vp_reg->rts_access_steer_ctrl,
300 VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
301 VXGE_HW_DEF_DEVICE_POLL_MILLIS);
302 }
303
304 if (status != VXGE_HW_OK)
305 goto out;
306
307 val64 = readq(&vp_reg->rts_access_steer_ctrl);
308 if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
309 *data0 = readq(&vp_reg->rts_access_steer_data0);
310 *data1 = readq(&vp_reg->rts_access_steer_data1);
311 *steer_ctrl = val64;
312 } else
313 status = VXGE_HW_FAIL;
314
315out:
316 if (vpath->vp_open)
317 spin_unlock(&vpath->lock);
318 return status;
319}
320
Jon Masone8ac1752010-11-11 04:25:57 +0000321enum vxge_hw_status
322vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
323 u32 *minor, u32 *build)
324{
325 u64 data0 = 0, data1 = 0, steer_ctrl = 0;
326 struct __vxge_hw_virtualpath *vpath;
327 enum vxge_hw_status status;
328
329 vpath = &hldev->virtual_paths[hldev->first_vp_id];
330
331 status = vxge_hw_vpath_fw_api(vpath,
332 VXGE_HW_FW_UPGRADE_ACTION,
333 VXGE_HW_FW_UPGRADE_MEMO,
334 VXGE_HW_FW_UPGRADE_OFFSET_READ,
335 &data0, &data1, &steer_ctrl);
336 if (status != VXGE_HW_OK)
337 return status;
338
339 *major = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
340 *minor = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
341 *build = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
342
343 return status;
344}
345
346enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev)
347{
348 u64 data0 = 0, data1 = 0, steer_ctrl = 0;
349 struct __vxge_hw_virtualpath *vpath;
350 enum vxge_hw_status status;
351 u32 ret;
352
353 vpath = &hldev->virtual_paths[hldev->first_vp_id];
354
355 status = vxge_hw_vpath_fw_api(vpath,
356 VXGE_HW_FW_UPGRADE_ACTION,
357 VXGE_HW_FW_UPGRADE_MEMO,
358 VXGE_HW_FW_UPGRADE_OFFSET_COMMIT,
359 &data0, &data1, &steer_ctrl);
360 if (status != VXGE_HW_OK) {
361 vxge_debug_init(VXGE_ERR, "%s: FW upgrade failed", __func__);
362 goto exit;
363 }
364
365 ret = VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(steer_ctrl) & 0x7F;
366 if (ret != 1) {
367 vxge_debug_init(VXGE_ERR, "%s: FW commit failed with error %d",
368 __func__, ret);
369 status = VXGE_HW_FAIL;
370 }
371
372exit:
373 return status;
374}
375
376enum vxge_hw_status
377vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *fwdata, int size)
378{
379 u64 data0 = 0, data1 = 0, steer_ctrl = 0;
380 struct __vxge_hw_virtualpath *vpath;
381 enum vxge_hw_status status;
382 int ret_code, sec_code;
383
384 vpath = &hldev->virtual_paths[hldev->first_vp_id];
385
386 /* send upgrade start command */
387 status = vxge_hw_vpath_fw_api(vpath,
388 VXGE_HW_FW_UPGRADE_ACTION,
389 VXGE_HW_FW_UPGRADE_MEMO,
390 VXGE_HW_FW_UPGRADE_OFFSET_START,
391 &data0, &data1, &steer_ctrl);
392 if (status != VXGE_HW_OK) {
393 vxge_debug_init(VXGE_ERR, " %s: Upgrade start cmd failed",
394 __func__);
395 return status;
396 }
397
398 /* Transfer fw image to adapter 16 bytes at a time */
399 for (; size > 0; size -= VXGE_HW_FW_UPGRADE_BLK_SIZE) {
400 steer_ctrl = 0;
401
402 /* The next 128bits of fwdata to be loaded onto the adapter */
403 data0 = *((u64 *)fwdata);
404 data1 = *((u64 *)fwdata + 1);
405
406 status = vxge_hw_vpath_fw_api(vpath,
407 VXGE_HW_FW_UPGRADE_ACTION,
408 VXGE_HW_FW_UPGRADE_MEMO,
409 VXGE_HW_FW_UPGRADE_OFFSET_SEND,
410 &data0, &data1, &steer_ctrl);
411 if (status != VXGE_HW_OK) {
412 vxge_debug_init(VXGE_ERR, "%s: Upgrade send failed",
413 __func__);
414 goto out;
415 }
416
417 ret_code = VXGE_HW_UPGRADE_GET_RET_ERR_CODE(data0);
418 switch (ret_code) {
419 case VXGE_HW_FW_UPGRADE_OK:
420 /* All OK, send next 16 bytes. */
421 break;
422 case VXGE_FW_UPGRADE_BYTES2SKIP:
423 /* skip bytes in the stream */
424 fwdata += (data0 >> 8) & 0xFFFFFFFF;
425 break;
426 case VXGE_HW_FW_UPGRADE_DONE:
427 goto out;
428 case VXGE_HW_FW_UPGRADE_ERR:
429 sec_code = VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(data0);
430 switch (sec_code) {
431 case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1:
432 case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7:
433 printk(KERN_ERR
434 "corrupted data from .ncf file\n");
435 break;
436 case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3:
437 case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4:
438 case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5:
439 case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6:
440 case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8:
441 printk(KERN_ERR "invalid .ncf file\n");
442 break;
443 case VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW:
444 printk(KERN_ERR "buffer overflow\n");
445 break;
446 case VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH:
447 printk(KERN_ERR "failed to flash the image\n");
448 break;
449 case VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN:
450 printk(KERN_ERR
451 "generic error. Unknown error type\n");
452 break;
453 default:
454 printk(KERN_ERR "Unknown error of type %d\n",
455 sec_code);
456 break;
457 }
458 status = VXGE_HW_FAIL;
459 goto out;
460 default:
461 printk(KERN_ERR "Unknown FW error: %d\n", ret_code);
462 status = VXGE_HW_FAIL;
463 goto out;
464 }
465 /* point to next 16 bytes */
466 fwdata += VXGE_HW_FW_UPGRADE_BLK_SIZE;
467 }
468out:
469 return status;
470}
471
472enum vxge_hw_status
473vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
474 struct eprom_image *img)
475{
476 u64 data0 = 0, data1 = 0, steer_ctrl = 0;
477 struct __vxge_hw_virtualpath *vpath;
478 enum vxge_hw_status status;
479 int i;
480
481 vpath = &hldev->virtual_paths[hldev->first_vp_id];
482
483 for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) {
484 data0 = VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(i);
485 data1 = steer_ctrl = 0;
486
487 status = vxge_hw_vpath_fw_api(vpath,
488 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
489 VXGE_HW_FW_API_GET_EPROM_REV,
490 0, &data0, &data1, &steer_ctrl);
491 if (status != VXGE_HW_OK)
492 break;
493
494 img[i].is_valid = VXGE_HW_GET_EPROM_IMAGE_VALID(data0);
495 img[i].index = VXGE_HW_GET_EPROM_IMAGE_INDEX(data0);
496 img[i].type = VXGE_HW_GET_EPROM_IMAGE_TYPE(data0);
497 img[i].version = VXGE_HW_GET_EPROM_IMAGE_REV(data0);
498 }
499
500 return status;
501}
502
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000503/*
504 * __vxge_hw_channel_allocate - Allocate memory for channel
505 * This function allocates required memory for the channel and various arrays
506 * in the channel
507 */
508struct __vxge_hw_channel*
509__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
510 enum __vxge_hw_channel_type type,
511 u32 length, u32 per_dtr_space, void *userdata)
512{
513 struct __vxge_hw_channel *channel;
514 struct __vxge_hw_device *hldev;
515 int size = 0;
516 u32 vp_id;
517
518 hldev = vph->vpath->hldev;
519 vp_id = vph->vpath->vp_id;
520
521 switch (type) {
522 case VXGE_HW_CHANNEL_TYPE_FIFO:
523 size = sizeof(struct __vxge_hw_fifo);
524 break;
525 case VXGE_HW_CHANNEL_TYPE_RING:
526 size = sizeof(struct __vxge_hw_ring);
527 break;
528 default:
529 break;
530 }
531
532 channel = kzalloc(size, GFP_KERNEL);
533 if (channel == NULL)
534 goto exit0;
535 INIT_LIST_HEAD(&channel->item);
536
537 channel->common_reg = hldev->common_reg;
538 channel->first_vp_id = hldev->first_vp_id;
539 channel->type = type;
540 channel->devh = hldev;
541 channel->vph = vph;
542 channel->userdata = userdata;
543 channel->per_dtr_space = per_dtr_space;
544 channel->length = length;
545 channel->vp_id = vp_id;
546
547 channel->work_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
548 if (channel->work_arr == NULL)
549 goto exit1;
550
551 channel->free_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
552 if (channel->free_arr == NULL)
553 goto exit1;
554 channel->free_ptr = length;
555
556 channel->reserve_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
557 if (channel->reserve_arr == NULL)
558 goto exit1;
559 channel->reserve_ptr = length;
560 channel->reserve_top = 0;
561
562 channel->orig_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
563 if (channel->orig_arr == NULL)
564 goto exit1;
565
566 return channel;
567exit1:
568 __vxge_hw_channel_free(channel);
569
570exit0:
571 return NULL;
572}
573
574/*
575 * __vxge_hw_channel_free - Free memory allocated for channel
576 * This function deallocates memory from the channel and various arrays
577 * in the channel
578 */
579void __vxge_hw_channel_free(struct __vxge_hw_channel *channel)
580{
581 kfree(channel->work_arr);
582 kfree(channel->free_arr);
583 kfree(channel->reserve_arr);
584 kfree(channel->orig_arr);
585 kfree(channel);
586}
587
588/*
589 * __vxge_hw_channel_initialize - Initialize a channel
590 * This function initializes a channel by properly setting the
591 * various references
592 */
593enum vxge_hw_status
594__vxge_hw_channel_initialize(struct __vxge_hw_channel *channel)
595{
596 u32 i;
597 struct __vxge_hw_virtualpath *vpath;
598
599 vpath = channel->vph->vpath;
600
601 if ((channel->reserve_arr != NULL) && (channel->orig_arr != NULL)) {
602 for (i = 0; i < channel->length; i++)
603 channel->orig_arr[i] = channel->reserve_arr[i];
604 }
605
606 switch (channel->type) {
607 case VXGE_HW_CHANNEL_TYPE_FIFO:
608 vpath->fifoh = (struct __vxge_hw_fifo *)channel;
609 channel->stats = &((struct __vxge_hw_fifo *)
610 channel)->stats->common_stats;
611 break;
612 case VXGE_HW_CHANNEL_TYPE_RING:
613 vpath->ringh = (struct __vxge_hw_ring *)channel;
614 channel->stats = &((struct __vxge_hw_ring *)
615 channel)->stats->common_stats;
616 break;
617 default:
618 break;
619 }
620
621 return VXGE_HW_OK;
622}
623
624/*
625 * __vxge_hw_channel_reset - Resets a channel
626 * This function resets a channel by properly setting the various references
627 */
628enum vxge_hw_status
629__vxge_hw_channel_reset(struct __vxge_hw_channel *channel)
630{
631 u32 i;
632
633 for (i = 0; i < channel->length; i++) {
634 if (channel->reserve_arr != NULL)
635 channel->reserve_arr[i] = channel->orig_arr[i];
636 if (channel->free_arr != NULL)
637 channel->free_arr[i] = NULL;
638 if (channel->work_arr != NULL)
639 channel->work_arr[i] = NULL;
640 }
641 channel->free_ptr = channel->length;
642 channel->reserve_ptr = channel->length;
643 channel->reserve_top = 0;
644 channel->post_index = 0;
645 channel->compl_index = 0;
646
647 return VXGE_HW_OK;
648}
649
650/*
651 * __vxge_hw_device_pci_e_init
652 * Initialize certain PCI/PCI-X configuration registers
653 * with recommended values. Save config space for future hw resets.
654 */
655void
656__vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev)
657{
658 u16 cmd = 0;
659
660 /* Set the PErr Repconse bit and SERR in PCI command register. */
661 pci_read_config_word(hldev->pdev, PCI_COMMAND, &cmd);
662 cmd |= 0x140;
663 pci_write_config_word(hldev->pdev, PCI_COMMAND, cmd);
664
665 pci_save_state(hldev->pdev);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000666}
667
668/*
669 * __vxge_hw_device_register_poll
670 * Will poll certain register for specified amount of time.
671 * Will poll until masked bit is not cleared.
672 */
stephen hemminger42821a52010-10-21 07:50:53 +0000673static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000674__vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
675{
676 u64 val64;
677 u32 i = 0;
678 enum vxge_hw_status ret = VXGE_HW_FAIL;
679
680 udelay(10);
681
682 do {
683 val64 = readq(reg);
684 if (!(val64 & mask))
685 return VXGE_HW_OK;
686 udelay(100);
687 } while (++i <= 9);
688
689 i = 0;
690 do {
691 val64 = readq(reg);
692 if (!(val64 & mask))
693 return VXGE_HW_OK;
694 mdelay(1);
695 } while (++i <= max_millis);
696
697 return ret;
698}
699
Jon Mason4d2a5b42010-11-11 04:25:54 +0000700/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000701 * in progress
702 * This routine checks the vpath reset in progress register is turned zero
703 */
stephen hemminger42821a52010-10-21 07:50:53 +0000704static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000705__vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog)
706{
707 enum vxge_hw_status status;
708 status = __vxge_hw_device_register_poll(vpath_rst_in_prog,
709 VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(0x1ffff),
710 VXGE_HW_DEF_DEVICE_POLL_MILLIS);
711 return status;
712}
713
714/*
715 * __vxge_hw_device_toc_get
716 * This routine sets the swapper and reads the toc pointer and returns the
717 * memory mapped address of the toc
718 */
stephen hemminger42821a52010-10-21 07:50:53 +0000719static struct vxge_hw_toc_reg __iomem *
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000720__vxge_hw_device_toc_get(void __iomem *bar0)
721{
722 u64 val64;
723 struct vxge_hw_toc_reg __iomem *toc = NULL;
724 enum vxge_hw_status status;
725
726 struct vxge_hw_legacy_reg __iomem *legacy_reg =
727 (struct vxge_hw_legacy_reg __iomem *)bar0;
728
729 status = __vxge_hw_legacy_swapper_set(legacy_reg);
730 if (status != VXGE_HW_OK)
731 goto exit;
732
733 val64 = readq(&legacy_reg->toc_first_pointer);
734 toc = (struct vxge_hw_toc_reg __iomem *)(bar0+val64);
735exit:
736 return toc;
737}
738
739/*
740 * __vxge_hw_device_reg_addr_get
741 * This routine sets the swapper and reads the toc pointer and initializes the
742 * register location pointers in the device object. It waits until the ric is
743 * completed initializing registers.
744 */
745enum vxge_hw_status
746__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
747{
748 u64 val64;
749 u32 i;
750 enum vxge_hw_status status = VXGE_HW_OK;
751
752 hldev->legacy_reg = (struct vxge_hw_legacy_reg __iomem *)hldev->bar0;
753
754 hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0);
755 if (hldev->toc_reg == NULL) {
756 status = VXGE_HW_FAIL;
757 goto exit;
758 }
759
760 val64 = readq(&hldev->toc_reg->toc_common_pointer);
761 hldev->common_reg =
762 (struct vxge_hw_common_reg __iomem *)(hldev->bar0 + val64);
763
764 val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
765 hldev->mrpcim_reg =
766 (struct vxge_hw_mrpcim_reg __iomem *)(hldev->bar0 + val64);
767
768 for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
769 val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
770 hldev->srpcim_reg[i] =
771 (struct vxge_hw_srpcim_reg __iomem *)
772 (hldev->bar0 + val64);
773 }
774
775 for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
776 val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
777 hldev->vpmgmt_reg[i] =
778 (struct vxge_hw_vpmgmt_reg __iomem *)(hldev->bar0 + val64);
779 }
780
781 for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
782 val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
783 hldev->vpath_reg[i] =
784 (struct vxge_hw_vpath_reg __iomem *)
785 (hldev->bar0 + val64);
786 }
787
788 val64 = readq(&hldev->toc_reg->toc_kdfc);
789
790 switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
791 case 0:
792 hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
793 VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
794 break;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000795 default:
796 break;
797 }
798
799 status = __vxge_hw_device_vpath_reset_in_prog_check(
800 (u64 __iomem *)&hldev->common_reg->vpath_rst_in_prog);
801exit:
802 return status;
803}
804
805/*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000806 * __vxge_hw_device_access_rights_get: Get Access Rights of the driver
807 * This routine returns the Access Rights of the driver
808 */
809static u32
810__vxge_hw_device_access_rights_get(u32 host_type, u32 func_id)
811{
812 u32 access_rights = VXGE_HW_DEVICE_ACCESS_RIGHT_VPATH;
813
814 switch (host_type) {
815 case VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION:
Sreenivasa Honnur1dc47a92010-03-28 22:12:33 +0000816 if (func_id == 0) {
817 access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
818 VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
819 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000820 break;
821 case VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION:
822 access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
823 VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
824 break;
825 case VXGE_HW_NO_MR_SR_VH0_FUNCTION0:
826 access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
827 VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
828 break;
829 case VXGE_HW_NO_MR_SR_VH0_VIRTUAL_FUNCTION:
830 case VXGE_HW_SR_VH_VIRTUAL_FUNCTION:
831 case VXGE_HW_MR_SR_VH0_INVALID_CONFIG:
832 break;
833 case VXGE_HW_SR_VH_FUNCTION0:
834 case VXGE_HW_VH_NORMAL_FUNCTION:
835 access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
836 break;
837 }
838
839 return access_rights;
840}
841/*
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +0000842 * __vxge_hw_device_is_privilaged
843 * This routine checks if the device function is privilaged or not
844 */
845
846enum vxge_hw_status
847__vxge_hw_device_is_privilaged(u32 host_type, u32 func_id)
848{
849 if (__vxge_hw_device_access_rights_get(host_type,
850 func_id) &
851 VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)
852 return VXGE_HW_OK;
853 else
854 return VXGE_HW_ERR_PRIVILAGED_OPEARATION;
855}
856
857/*
Jon Mason8424e002010-11-11 04:25:56 +0000858 * __vxge_hw_vpath_func_id_get - Get the function id of the vpath.
859 * Returns the function number of the vpath.
860 */
861static u32
862__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg)
863{
864 u64 val64;
865
866 val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1);
867
868 return
869 (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64);
870}
871
872/*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000873 * __vxge_hw_device_host_info_get
874 * This routine returns the host type assignments
875 */
Jon Mason8424e002010-11-11 04:25:56 +0000876static void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000877{
878 u64 val64;
879 u32 i;
880
881 val64 = readq(&hldev->common_reg->host_type_assignments);
882
883 hldev->host_type =
884 (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
885
886 hldev->vpath_assignments = readq(&hldev->common_reg->vpath_assignments);
887
888 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000889 if (!(hldev->vpath_assignments & vxge_mBIT(i)))
890 continue;
891
892 hldev->func_id =
Jon Mason8424e002010-11-11 04:25:56 +0000893 __vxge_hw_vpath_func_id_get(hldev->vpmgmt_reg[i]);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000894
895 hldev->access_rights = __vxge_hw_device_access_rights_get(
896 hldev->host_type, hldev->func_id);
897
Jon Mason8424e002010-11-11 04:25:56 +0000898 hldev->virtual_paths[i].vp_open = VXGE_HW_VP_NOT_OPEN;
899 hldev->virtual_paths[i].vp_reg = hldev->vpath_reg[i];
900
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000901 hldev->first_vp_id = i;
902 break;
903 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000904}
905
906/*
907 * __vxge_hw_verify_pci_e_info - Validate the pci-e link parameters such as
908 * link width and signalling rate.
909 */
910static enum vxge_hw_status
911__vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
912{
913 int exp_cap;
914 u16 lnk;
915
916 /* Get the negotiated link width and speed from PCI config space */
917 exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
918 pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
919
920 if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
921 return VXGE_HW_ERR_INVALID_PCI_INFO;
922
923 switch ((lnk & PCI_EXP_LNKSTA_NLW) >> 4) {
924 case PCIE_LNK_WIDTH_RESRV:
925 case PCIE_LNK_X1:
926 case PCIE_LNK_X2:
927 case PCIE_LNK_X4:
928 case PCIE_LNK_X8:
929 break;
930 default:
931 return VXGE_HW_ERR_INVALID_PCI_INFO;
932 }
933
934 return VXGE_HW_OK;
935}
936
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000937/*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000938 * __vxge_hw_device_initialize
939 * Initialize Titan-V hardware.
940 */
941enum vxge_hw_status __vxge_hw_device_initialize(struct __vxge_hw_device *hldev)
942{
943 enum vxge_hw_status status = VXGE_HW_OK;
944
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +0000945 if (VXGE_HW_OK == __vxge_hw_device_is_privilaged(hldev->host_type,
946 hldev->func_id)) {
Sivakumar Subramani5dbc9012009-06-16 18:48:55 +0000947 /* Validate the pci-e link width and speed */
948 status = __vxge_hw_verify_pci_e_info(hldev);
949 if (status != VXGE_HW_OK)
950 goto exit;
951 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000952
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +0000953exit:
954 return status;
955}
956
Jon Mason8424e002010-11-11 04:25:56 +0000957/*
958 * __vxge_hw_vpath_fw_ver_get - Get the fw version
959 * Returns FW Version
960 */
961static enum vxge_hw_status
962__vxge_hw_vpath_fw_ver_get(struct __vxge_hw_virtualpath *vpath,
963 struct vxge_hw_device_hw_info *hw_info)
964{
965 struct vxge_hw_device_version *fw_version = &hw_info->fw_version;
966 struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
967 struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
968 struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
969 u64 data0, data1 = 0, steer_ctrl = 0;
970 enum vxge_hw_status status;
971
972 status = vxge_hw_vpath_fw_api(vpath,
973 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
974 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
975 0, &data0, &data1, &steer_ctrl);
976 if (status != VXGE_HW_OK)
977 goto exit;
978
979 fw_date->day =
980 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(data0);
981 fw_date->month =
982 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(data0);
983 fw_date->year =
984 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(data0);
985
986 snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
987 fw_date->month, fw_date->day, fw_date->year);
988
989 fw_version->major =
990 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
991 fw_version->minor =
992 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
993 fw_version->build =
994 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
995
996 snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
997 fw_version->major, fw_version->minor, fw_version->build);
998
999 flash_date->day =
1000 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data1);
1001 flash_date->month =
1002 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data1);
1003 flash_date->year =
1004 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data1);
1005
1006 snprintf(flash_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
1007 flash_date->month, flash_date->day, flash_date->year);
1008
1009 flash_version->major =
1010 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data1);
1011 flash_version->minor =
1012 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data1);
1013 flash_version->build =
1014 (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data1);
1015
1016 snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
1017 flash_version->major, flash_version->minor,
1018 flash_version->build);
1019
1020exit:
1021 return status;
1022}
1023
1024/*
1025 * __vxge_hw_vpath_card_info_get - Get the serial numbers,
1026 * part number and product description.
1027 */
1028static enum vxge_hw_status
1029__vxge_hw_vpath_card_info_get(struct __vxge_hw_virtualpath *vpath,
1030 struct vxge_hw_device_hw_info *hw_info)
1031{
1032 enum vxge_hw_status status;
1033 u64 data0, data1 = 0, steer_ctrl = 0;
1034 u8 *serial_number = hw_info->serial_number;
1035 u8 *part_number = hw_info->part_number;
1036 u8 *product_desc = hw_info->product_desc;
1037 u32 i, j = 0;
1038
1039 data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER;
1040
1041 status = vxge_hw_vpath_fw_api(vpath,
1042 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
1043 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
1044 0, &data0, &data1, &steer_ctrl);
1045 if (status != VXGE_HW_OK)
1046 return status;
1047
1048 ((u64 *)serial_number)[0] = be64_to_cpu(data0);
1049 ((u64 *)serial_number)[1] = be64_to_cpu(data1);
1050
1051 data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER;
1052 data1 = steer_ctrl = 0;
1053
1054 status = vxge_hw_vpath_fw_api(vpath,
1055 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
1056 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
1057 0, &data0, &data1, &steer_ctrl);
1058 if (status != VXGE_HW_OK)
1059 return status;
1060
1061 ((u64 *)part_number)[0] = be64_to_cpu(data0);
1062 ((u64 *)part_number)[1] = be64_to_cpu(data1);
1063
1064 for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0;
1065 i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) {
1066 data0 = i;
1067 data1 = steer_ctrl = 0;
1068
1069 status = vxge_hw_vpath_fw_api(vpath,
1070 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
1071 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
1072 0, &data0, &data1, &steer_ctrl);
1073 if (status != VXGE_HW_OK)
1074 return status;
1075
1076 ((u64 *)product_desc)[j++] = be64_to_cpu(data0);
1077 ((u64 *)product_desc)[j++] = be64_to_cpu(data1);
1078 }
1079
1080 return status;
1081}
1082
1083/*
1084 * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode
1085 * Returns pci function mode
1086 */
Jon Masonc3150ea2010-11-11 04:25:59 +00001087static enum vxge_hw_status
1088__vxge_hw_vpath_pci_func_mode_get(struct __vxge_hw_virtualpath *vpath,
1089 struct vxge_hw_device_hw_info *hw_info)
Jon Mason8424e002010-11-11 04:25:56 +00001090{
1091 u64 data0, data1 = 0, steer_ctrl = 0;
1092 enum vxge_hw_status status;
1093
Jon Masonca3e3b8fa2010-11-11 04:26:01 +00001094 data0 = 0;
Jon Mason8424e002010-11-11 04:25:56 +00001095
1096 status = vxge_hw_vpath_fw_api(vpath,
Jon Masonca3e3b8fa2010-11-11 04:26:01 +00001097 VXGE_HW_FW_API_GET_FUNC_MODE,
Jon Mason8424e002010-11-11 04:25:56 +00001098 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
1099 0, &data0, &data1, &steer_ctrl);
Jon Masonc3150ea2010-11-11 04:25:59 +00001100 if (status != VXGE_HW_OK)
1101 return status;
Jon Mason8424e002010-11-11 04:25:56 +00001102
Jon Masonca3e3b8fa2010-11-11 04:26:01 +00001103 hw_info->function_mode = VXGE_HW_GET_FUNC_MODE_VAL(data0);
Jon Masonc3150ea2010-11-11 04:25:59 +00001104 return status;
Jon Mason8424e002010-11-11 04:25:56 +00001105}
1106
1107/*
1108 * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath
1109 * from MAC address table.
1110 */
1111static enum vxge_hw_status
1112__vxge_hw_vpath_addr_get(struct __vxge_hw_virtualpath *vpath,
1113 u8 *macaddr, u8 *macaddr_mask)
1114{
1115 u64 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
1116 data0 = 0, data1 = 0, steer_ctrl = 0;
1117 enum vxge_hw_status status;
1118 int i;
1119
1120 do {
1121 status = vxge_hw_vpath_fw_api(vpath, action,
1122 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
1123 0, &data0, &data1, &steer_ctrl);
1124 if (status != VXGE_HW_OK)
1125 goto exit;
1126
1127 data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data0);
1128 data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(
1129 data1);
1130
1131 for (i = ETH_ALEN; i > 0; i--) {
1132 macaddr[i - 1] = (u8) (data0 & 0xFF);
1133 data0 >>= 8;
1134
1135 macaddr_mask[i - 1] = (u8) (data1 & 0xFF);
1136 data1 >>= 8;
1137 }
1138
1139 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY;
1140 data0 = 0, data1 = 0, steer_ctrl = 0;
1141
1142 } while (!is_valid_ether_addr(macaddr));
1143exit:
1144 return status;
1145}
1146
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001147/**
1148 * vxge_hw_device_hw_info_get - Get the hw information
1149 * Returns the vpath mask that has the bits set for each vpath allocated
1150 * for the driver, FW version information and the first mac addresse for
1151 * each vpath
1152 */
1153enum vxge_hw_status __devinit
1154vxge_hw_device_hw_info_get(void __iomem *bar0,
1155 struct vxge_hw_device_hw_info *hw_info)
1156{
1157 u32 i;
1158 u64 val64;
1159 struct vxge_hw_toc_reg __iomem *toc;
1160 struct vxge_hw_mrpcim_reg __iomem *mrpcim_reg;
1161 struct vxge_hw_common_reg __iomem *common_reg;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001162 struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
1163 enum vxge_hw_status status;
Jon Mason8424e002010-11-11 04:25:56 +00001164 struct __vxge_hw_virtualpath vpath;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001165
1166 memset(hw_info, 0, sizeof(struct vxge_hw_device_hw_info));
1167
1168 toc = __vxge_hw_device_toc_get(bar0);
1169 if (toc == NULL) {
1170 status = VXGE_HW_ERR_CRITICAL;
1171 goto exit;
1172 }
1173
1174 val64 = readq(&toc->toc_common_pointer);
1175 common_reg = (struct vxge_hw_common_reg __iomem *)(bar0 + val64);
1176
1177 status = __vxge_hw_device_vpath_reset_in_prog_check(
1178 (u64 __iomem *)&common_reg->vpath_rst_in_prog);
1179 if (status != VXGE_HW_OK)
1180 goto exit;
1181
1182 hw_info->vpath_mask = readq(&common_reg->vpath_assignments);
1183
1184 val64 = readq(&common_reg->host_type_assignments);
1185
1186 hw_info->host_type =
1187 (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
1188
1189 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
1190
1191 if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
1192 continue;
1193
1194 val64 = readq(&toc->toc_vpmgmt_pointer[i]);
1195
1196 vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
1197 (bar0 + val64);
1198
Jon Mason8424e002010-11-11 04:25:56 +00001199 hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001200 if (__vxge_hw_device_access_rights_get(hw_info->host_type,
1201 hw_info->func_id) &
1202 VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM) {
1203
1204 val64 = readq(&toc->toc_mrpcim_pointer);
1205
1206 mrpcim_reg = (struct vxge_hw_mrpcim_reg __iomem *)
1207 (bar0 + val64);
1208
1209 writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
1210 wmb();
1211 }
1212
1213 val64 = readq(&toc->toc_vpath_pointer[i]);
1214
Jon Mason8424e002010-11-11 04:25:56 +00001215 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
1216 (bar0 + val64);
1217 vpath.vp_open = 0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001218
Jon Masonc3150ea2010-11-11 04:25:59 +00001219 status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
1220 if (status != VXGE_HW_OK)
1221 goto exit;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001222
Jon Mason8424e002010-11-11 04:25:56 +00001223 status = __vxge_hw_vpath_fw_ver_get(&vpath, hw_info);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001224 if (status != VXGE_HW_OK)
1225 goto exit;
1226
Jon Mason8424e002010-11-11 04:25:56 +00001227 status = __vxge_hw_vpath_card_info_get(&vpath, hw_info);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001228 if (status != VXGE_HW_OK)
1229 goto exit;
1230
1231 break;
1232 }
1233
1234 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001235 if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
1236 continue;
1237
1238 val64 = readq(&toc->toc_vpath_pointer[i]);
Jon Mason8424e002010-11-11 04:25:56 +00001239 vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
1240 (bar0 + val64);
1241 vpath.vp_open = 0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001242
Jon Mason8424e002010-11-11 04:25:56 +00001243 status = __vxge_hw_vpath_addr_get(&vpath,
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001244 hw_info->mac_addrs[i],
1245 hw_info->mac_addr_masks[i]);
1246 if (status != VXGE_HW_OK)
1247 goto exit;
1248 }
1249exit:
1250 return status;
1251}
1252
1253/*
1254 * vxge_hw_device_initialize - Initialize Titan device.
1255 * Initialize Titan device. Note that all the arguments of this public API
1256 * are 'IN', including @hldev. Driver cooperates with
1257 * OS to find new Titan device, locate its PCI and memory spaces.
1258 *
1259 * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
1260 * to enable the latter to perform Titan hardware initialization.
1261 */
1262enum vxge_hw_status __devinit
1263vxge_hw_device_initialize(
1264 struct __vxge_hw_device **devh,
1265 struct vxge_hw_device_attr *attr,
1266 struct vxge_hw_device_config *device_config)
1267{
1268 u32 i;
1269 u32 nblocks = 0;
1270 struct __vxge_hw_device *hldev = NULL;
1271 enum vxge_hw_status status = VXGE_HW_OK;
1272
1273 status = __vxge_hw_device_config_check(device_config);
1274 if (status != VXGE_HW_OK)
1275 goto exit;
1276
1277 hldev = (struct __vxge_hw_device *)
1278 vmalloc(sizeof(struct __vxge_hw_device));
1279 if (hldev == NULL) {
1280 status = VXGE_HW_ERR_OUT_OF_MEMORY;
1281 goto exit;
1282 }
1283
1284 memset(hldev, 0, sizeof(struct __vxge_hw_device));
1285 hldev->magic = VXGE_HW_DEVICE_MAGIC;
1286
1287 vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL);
1288
1289 /* apply config */
1290 memcpy(&hldev->config, device_config,
1291 sizeof(struct vxge_hw_device_config));
1292
1293 hldev->bar0 = attr->bar0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001294 hldev->pdev = attr->pdev;
1295
1296 hldev->uld_callbacks.link_up = attr->uld_callbacks.link_up;
1297 hldev->uld_callbacks.link_down = attr->uld_callbacks.link_down;
1298 hldev->uld_callbacks.crit_err = attr->uld_callbacks.crit_err;
1299
1300 __vxge_hw_device_pci_e_init(hldev);
1301
1302 status = __vxge_hw_device_reg_addr_get(hldev);
Sreenivasa Honnuraaffbd92010-04-08 01:44:39 -07001303 if (status != VXGE_HW_OK) {
1304 vfree(hldev);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001305 goto exit;
Sreenivasa Honnuraaffbd92010-04-08 01:44:39 -07001306 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001307
1308 __vxge_hw_device_host_info_get(hldev);
1309
1310 /* Incrementing for stats blocks */
1311 nblocks++;
1312
1313 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001314 if (!(hldev->vpath_assignments & vxge_mBIT(i)))
1315 continue;
1316
1317 if (device_config->vp_config[i].ring.enable ==
1318 VXGE_HW_RING_ENABLE)
1319 nblocks += device_config->vp_config[i].ring.ring_blocks;
1320
1321 if (device_config->vp_config[i].fifo.enable ==
1322 VXGE_HW_FIFO_ENABLE)
1323 nblocks += device_config->vp_config[i].fifo.fifo_blocks;
1324 nblocks++;
1325 }
1326
1327 if (__vxge_hw_blockpool_create(hldev,
1328 &hldev->block_pool,
1329 device_config->dma_blockpool_initial + nblocks,
1330 device_config->dma_blockpool_max + nblocks) != VXGE_HW_OK) {
1331
1332 vxge_hw_device_terminate(hldev);
1333 status = VXGE_HW_ERR_OUT_OF_MEMORY;
1334 goto exit;
1335 }
1336
1337 status = __vxge_hw_device_initialize(hldev);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001338 if (status != VXGE_HW_OK) {
1339 vxge_hw_device_terminate(hldev);
1340 goto exit;
1341 }
1342
1343 *devh = hldev;
1344exit:
1345 return status;
1346}
1347
1348/*
1349 * vxge_hw_device_terminate - Terminate Titan device.
1350 * Terminate HW device.
1351 */
1352void
1353vxge_hw_device_terminate(struct __vxge_hw_device *hldev)
1354{
1355 vxge_assert(hldev->magic == VXGE_HW_DEVICE_MAGIC);
1356
1357 hldev->magic = VXGE_HW_DEVICE_DEAD;
1358 __vxge_hw_blockpool_destroy(&hldev->block_pool);
1359 vfree(hldev);
1360}
1361
1362/*
1363 * vxge_hw_device_stats_get - Get the device hw statistics.
1364 * Returns the vpath h/w stats for the device.
1365 */
1366enum vxge_hw_status
1367vxge_hw_device_stats_get(struct __vxge_hw_device *hldev,
1368 struct vxge_hw_device_stats_hw_info *hw_stats)
1369{
1370 u32 i;
1371 enum vxge_hw_status status = VXGE_HW_OK;
1372
1373 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001374 if (!(hldev->vpaths_deployed & vxge_mBIT(i)) ||
1375 (hldev->virtual_paths[i].vp_open ==
1376 VXGE_HW_VP_NOT_OPEN))
1377 continue;
1378
1379 memcpy(hldev->virtual_paths[i].hw_stats_sav,
1380 hldev->virtual_paths[i].hw_stats,
1381 sizeof(struct vxge_hw_vpath_stats_hw_info));
1382
1383 status = __vxge_hw_vpath_stats_get(
1384 &hldev->virtual_paths[i],
1385 hldev->virtual_paths[i].hw_stats);
1386 }
1387
1388 memcpy(hw_stats, &hldev->stats.hw_dev_info_stats,
1389 sizeof(struct vxge_hw_device_stats_hw_info));
1390
1391 return status;
1392}
1393
1394/*
1395 * vxge_hw_driver_stats_get - Get the device sw statistics.
1396 * Returns the vpath s/w stats for the device.
1397 */
1398enum vxge_hw_status vxge_hw_driver_stats_get(
1399 struct __vxge_hw_device *hldev,
1400 struct vxge_hw_device_stats_sw_info *sw_stats)
1401{
1402 enum vxge_hw_status status = VXGE_HW_OK;
1403
1404 memcpy(sw_stats, &hldev->stats.sw_dev_info_stats,
1405 sizeof(struct vxge_hw_device_stats_sw_info));
1406
1407 return status;
1408}
1409
1410/*
1411 * vxge_hw_mrpcim_stats_access - Access the statistics from the given location
1412 * and offset and perform an operation
1413 * Get the statistics from the given location and offset.
1414 */
1415enum vxge_hw_status
1416vxge_hw_mrpcim_stats_access(struct __vxge_hw_device *hldev,
1417 u32 operation, u32 location, u32 offset, u64 *stat)
1418{
1419 u64 val64;
1420 enum vxge_hw_status status = VXGE_HW_OK;
1421
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +00001422 status = __vxge_hw_device_is_privilaged(hldev->host_type,
1423 hldev->func_id);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001424 if (status != VXGE_HW_OK)
1425 goto exit;
1426
1427 val64 = VXGE_HW_XMAC_STATS_SYS_CMD_OP(operation) |
1428 VXGE_HW_XMAC_STATS_SYS_CMD_STROBE |
1429 VXGE_HW_XMAC_STATS_SYS_CMD_LOC_SEL(location) |
1430 VXGE_HW_XMAC_STATS_SYS_CMD_OFFSET_SEL(offset);
1431
1432 status = __vxge_hw_pio_mem_write64(val64,
1433 &hldev->mrpcim_reg->xmac_stats_sys_cmd,
1434 VXGE_HW_XMAC_STATS_SYS_CMD_STROBE,
1435 hldev->config.device_poll_millis);
1436
1437 if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
1438 *stat = readq(&hldev->mrpcim_reg->xmac_stats_sys_data);
1439 else
1440 *stat = 0;
1441exit:
1442 return status;
1443}
1444
1445/*
1446 * vxge_hw_device_xmac_aggr_stats_get - Get the Statistics on aggregate port
1447 * Get the Statistics on aggregate port
1448 */
stephen hemminger42821a52010-10-21 07:50:53 +00001449static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001450vxge_hw_device_xmac_aggr_stats_get(struct __vxge_hw_device *hldev, u32 port,
1451 struct vxge_hw_xmac_aggr_stats *aggr_stats)
1452{
1453 u64 *val64;
1454 int i;
1455 u32 offset = VXGE_HW_STATS_AGGRn_OFFSET;
1456 enum vxge_hw_status status = VXGE_HW_OK;
1457
1458 val64 = (u64 *)aggr_stats;
1459
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +00001460 status = __vxge_hw_device_is_privilaged(hldev->host_type,
1461 hldev->func_id);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001462 if (status != VXGE_HW_OK)
1463 goto exit;
1464
1465 for (i = 0; i < sizeof(struct vxge_hw_xmac_aggr_stats) / 8; i++) {
1466 status = vxge_hw_mrpcim_stats_access(hldev,
1467 VXGE_HW_STATS_OP_READ,
1468 VXGE_HW_STATS_LOC_AGGR,
1469 ((offset + (104 * port)) >> 3), val64);
1470 if (status != VXGE_HW_OK)
1471 goto exit;
1472
1473 offset += 8;
1474 val64++;
1475 }
1476exit:
1477 return status;
1478}
1479
1480/*
1481 * vxge_hw_device_xmac_port_stats_get - Get the Statistics on a port
1482 * Get the Statistics on port
1483 */
stephen hemminger42821a52010-10-21 07:50:53 +00001484static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001485vxge_hw_device_xmac_port_stats_get(struct __vxge_hw_device *hldev, u32 port,
1486 struct vxge_hw_xmac_port_stats *port_stats)
1487{
1488 u64 *val64;
1489 enum vxge_hw_status status = VXGE_HW_OK;
1490 int i;
1491 u32 offset = 0x0;
1492 val64 = (u64 *) port_stats;
1493
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +00001494 status = __vxge_hw_device_is_privilaged(hldev->host_type,
1495 hldev->func_id);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001496 if (status != VXGE_HW_OK)
1497 goto exit;
1498
1499 for (i = 0; i < sizeof(struct vxge_hw_xmac_port_stats) / 8; i++) {
1500 status = vxge_hw_mrpcim_stats_access(hldev,
1501 VXGE_HW_STATS_OP_READ,
1502 VXGE_HW_STATS_LOC_AGGR,
1503 ((offset + (608 * port)) >> 3), val64);
1504 if (status != VXGE_HW_OK)
1505 goto exit;
1506
1507 offset += 8;
1508 val64++;
1509 }
1510
1511exit:
1512 return status;
1513}
1514
1515/*
1516 * vxge_hw_device_xmac_stats_get - Get the XMAC Statistics
1517 * Get the XMAC Statistics
1518 */
1519enum vxge_hw_status
1520vxge_hw_device_xmac_stats_get(struct __vxge_hw_device *hldev,
1521 struct vxge_hw_xmac_stats *xmac_stats)
1522{
1523 enum vxge_hw_status status = VXGE_HW_OK;
1524 u32 i;
1525
1526 status = vxge_hw_device_xmac_aggr_stats_get(hldev,
1527 0, &xmac_stats->aggr_stats[0]);
1528
1529 if (status != VXGE_HW_OK)
1530 goto exit;
1531
1532 status = vxge_hw_device_xmac_aggr_stats_get(hldev,
1533 1, &xmac_stats->aggr_stats[1]);
1534 if (status != VXGE_HW_OK)
1535 goto exit;
1536
1537 for (i = 0; i <= VXGE_HW_MAC_MAX_MAC_PORT_ID; i++) {
1538
1539 status = vxge_hw_device_xmac_port_stats_get(hldev,
1540 i, &xmac_stats->port_stats[i]);
1541 if (status != VXGE_HW_OK)
1542 goto exit;
1543 }
1544
1545 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
1546
1547 if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
1548 continue;
1549
1550 status = __vxge_hw_vpath_xmac_tx_stats_get(
1551 &hldev->virtual_paths[i],
1552 &xmac_stats->vpath_tx_stats[i]);
1553 if (status != VXGE_HW_OK)
1554 goto exit;
1555
1556 status = __vxge_hw_vpath_xmac_rx_stats_get(
1557 &hldev->virtual_paths[i],
1558 &xmac_stats->vpath_rx_stats[i]);
1559 if (status != VXGE_HW_OK)
1560 goto exit;
1561 }
1562exit:
1563 return status;
1564}
1565
1566/*
1567 * vxge_hw_device_debug_set - Set the debug module, level and timestamp
1568 * This routine is used to dynamically change the debug output
1569 */
1570void vxge_hw_device_debug_set(struct __vxge_hw_device *hldev,
1571 enum vxge_debug_level level, u32 mask)
1572{
1573 if (hldev == NULL)
1574 return;
1575
1576#if defined(VXGE_DEBUG_TRACE_MASK) || \
1577 defined(VXGE_DEBUG_ERR_MASK)
1578 hldev->debug_module_mask = mask;
1579 hldev->debug_level = level;
1580#endif
1581
1582#if defined(VXGE_DEBUG_ERR_MASK)
1583 hldev->level_err = level & VXGE_ERR;
1584#endif
1585
1586#if defined(VXGE_DEBUG_TRACE_MASK)
1587 hldev->level_trace = level & VXGE_TRACE;
1588#endif
1589}
1590
1591/*
1592 * vxge_hw_device_error_level_get - Get the error level
1593 * This routine returns the current error level set
1594 */
1595u32 vxge_hw_device_error_level_get(struct __vxge_hw_device *hldev)
1596{
1597#if defined(VXGE_DEBUG_ERR_MASK)
1598 if (hldev == NULL)
1599 return VXGE_ERR;
1600 else
1601 return hldev->level_err;
1602#else
1603 return 0;
1604#endif
1605}
1606
1607/*
1608 * vxge_hw_device_trace_level_get - Get the trace level
1609 * This routine returns the current trace level set
1610 */
1611u32 vxge_hw_device_trace_level_get(struct __vxge_hw_device *hldev)
1612{
1613#if defined(VXGE_DEBUG_TRACE_MASK)
1614 if (hldev == NULL)
1615 return VXGE_TRACE;
1616 else
1617 return hldev->level_trace;
1618#else
1619 return 0;
1620#endif
1621}
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001622
1623/*
1624 * vxge_hw_getpause_data -Pause frame frame generation and reception.
1625 * Returns the Pause frame generation and reception capability of the NIC.
1626 */
1627enum vxge_hw_status vxge_hw_device_getpause_data(struct __vxge_hw_device *hldev,
1628 u32 port, u32 *tx, u32 *rx)
1629{
1630 u64 val64;
1631 enum vxge_hw_status status = VXGE_HW_OK;
1632
1633 if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
1634 status = VXGE_HW_ERR_INVALID_DEVICE;
1635 goto exit;
1636 }
1637
1638 if (port > VXGE_HW_MAC_MAX_MAC_PORT_ID) {
1639 status = VXGE_HW_ERR_INVALID_PORT;
1640 goto exit;
1641 }
1642
1643 if (!(hldev->access_rights & VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
1644 status = VXGE_HW_ERR_PRIVILAGED_OPEARATION;
1645 goto exit;
1646 }
1647
1648 val64 = readq(&hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
1649 if (val64 & VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN)
1650 *tx = 1;
1651 if (val64 & VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN)
1652 *rx = 1;
1653exit:
1654 return status;
1655}
1656
1657/*
1658 * vxge_hw_device_setpause_data - set/reset pause frame generation.
1659 * It can be used to set or reset Pause frame generation or reception
1660 * support of the NIC.
1661 */
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001662enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev,
1663 u32 port, u32 tx, u32 rx)
1664{
1665 u64 val64;
1666 enum vxge_hw_status status = VXGE_HW_OK;
1667
1668 if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
1669 status = VXGE_HW_ERR_INVALID_DEVICE;
1670 goto exit;
1671 }
1672
1673 if (port > VXGE_HW_MAC_MAX_MAC_PORT_ID) {
1674 status = VXGE_HW_ERR_INVALID_PORT;
1675 goto exit;
1676 }
1677
Sreenivasa Honnur92cdd7c2009-10-05 01:51:38 +00001678 status = __vxge_hw_device_is_privilaged(hldev->host_type,
1679 hldev->func_id);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001680 if (status != VXGE_HW_OK)
1681 goto exit;
1682
1683 val64 = readq(&hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
1684 if (tx)
1685 val64 |= VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN;
1686 else
1687 val64 &= ~VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN;
1688 if (rx)
1689 val64 |= VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN;
1690 else
1691 val64 &= ~VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN;
1692
1693 writeq(val64, &hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
1694exit:
1695 return status;
1696}
1697
1698u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
1699{
1700 int link_width, exp_cap;
1701 u16 lnk;
1702
1703 exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
1704 pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
1705 link_width = (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
1706 return link_width;
1707}
1708
1709/*
1710 * __vxge_hw_ring_block_memblock_idx - Return the memblock index
1711 * This function returns the index of memory block
1712 */
1713static inline u32
1714__vxge_hw_ring_block_memblock_idx(u8 *block)
1715{
1716 return (u32)*((u64 *)(block + VXGE_HW_RING_MEMBLOCK_IDX_OFFSET));
1717}
1718
1719/*
1720 * __vxge_hw_ring_block_memblock_idx_set - Sets the memblock index
1721 * This function sets index to a memory block
1722 */
1723static inline void
1724__vxge_hw_ring_block_memblock_idx_set(u8 *block, u32 memblock_idx)
1725{
1726 *((u64 *)(block + VXGE_HW_RING_MEMBLOCK_IDX_OFFSET)) = memblock_idx;
1727}
1728
1729/*
1730 * __vxge_hw_ring_block_next_pointer_set - Sets the next block pointer
1731 * in RxD block
1732 * Sets the next block pointer in RxD block
1733 */
1734static inline void
1735__vxge_hw_ring_block_next_pointer_set(u8 *block, dma_addr_t dma_next)
1736{
1737 *((u64 *)(block + VXGE_HW_RING_NEXT_BLOCK_POINTER_OFFSET)) = dma_next;
1738}
1739
1740/*
1741 * __vxge_hw_ring_first_block_address_get - Returns the dma address of the
1742 * first block
1743 * Returns the dma address of the first RxD block
1744 */
stephen hemminger42821a52010-10-21 07:50:53 +00001745static u64 __vxge_hw_ring_first_block_address_get(struct __vxge_hw_ring *ring)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001746{
1747 struct vxge_hw_mempool_dma *dma_object;
1748
1749 dma_object = ring->mempool->memblocks_dma_arr;
1750 vxge_assert(dma_object != NULL);
1751
1752 return dma_object->addr;
1753}
1754
1755/*
1756 * __vxge_hw_ring_item_dma_addr - Return the dma address of an item
1757 * This function returns the dma address of a given item
1758 */
1759static dma_addr_t __vxge_hw_ring_item_dma_addr(struct vxge_hw_mempool *mempoolh,
1760 void *item)
1761{
1762 u32 memblock_idx;
1763 void *memblock;
1764 struct vxge_hw_mempool_dma *memblock_dma_object;
1765 ptrdiff_t dma_item_offset;
1766
1767 /* get owner memblock index */
1768 memblock_idx = __vxge_hw_ring_block_memblock_idx(item);
1769
1770 /* get owner memblock by memblock index */
1771 memblock = mempoolh->memblocks_arr[memblock_idx];
1772
1773 /* get memblock DMA object by memblock index */
1774 memblock_dma_object = mempoolh->memblocks_dma_arr + memblock_idx;
1775
1776 /* calculate offset in the memblock of this item */
1777 dma_item_offset = (u8 *)item - (u8 *)memblock;
1778
1779 return memblock_dma_object->addr + dma_item_offset;
1780}
1781
1782/*
1783 * __vxge_hw_ring_rxdblock_link - Link the RxD blocks
1784 * This function returns the dma address of a given item
1785 */
1786static void __vxge_hw_ring_rxdblock_link(struct vxge_hw_mempool *mempoolh,
1787 struct __vxge_hw_ring *ring, u32 from,
1788 u32 to)
1789{
1790 u8 *to_item , *from_item;
1791 dma_addr_t to_dma;
1792
1793 /* get "from" RxD block */
1794 from_item = mempoolh->items_arr[from];
1795 vxge_assert(from_item);
1796
1797 /* get "to" RxD block */
1798 to_item = mempoolh->items_arr[to];
1799 vxge_assert(to_item);
1800
1801 /* return address of the beginning of previous RxD block */
1802 to_dma = __vxge_hw_ring_item_dma_addr(mempoolh, to_item);
1803
1804 /* set next pointer for this RxD block to point on
1805 * previous item's DMA start address */
1806 __vxge_hw_ring_block_next_pointer_set(from_item, to_dma);
1807}
1808
1809/*
1810 * __vxge_hw_ring_mempool_item_alloc - Allocate List blocks for RxD
1811 * block callback
1812 * This function is callback passed to __vxge_hw_mempool_create to create memory
1813 * pool for RxD block
1814 */
1815static void
1816__vxge_hw_ring_mempool_item_alloc(struct vxge_hw_mempool *mempoolh,
1817 u32 memblock_index,
1818 struct vxge_hw_mempool_dma *dma_object,
1819 u32 index, u32 is_last)
1820{
1821 u32 i;
1822 void *item = mempoolh->items_arr[index];
1823 struct __vxge_hw_ring *ring =
1824 (struct __vxge_hw_ring *)mempoolh->userdata;
1825
1826 /* format rxds array */
1827 for (i = 0; i < ring->rxds_per_block; i++) {
1828 void *rxdblock_priv;
1829 void *uld_priv;
1830 struct vxge_hw_ring_rxd_1 *rxdp;
1831
1832 u32 reserve_index = ring->channel.reserve_ptr -
1833 (index * ring->rxds_per_block + i + 1);
1834 u32 memblock_item_idx;
1835
1836 ring->channel.reserve_arr[reserve_index] = ((u8 *)item) +
1837 i * ring->rxd_size;
1838
1839 /* Note: memblock_item_idx is index of the item within
1840 * the memblock. For instance, in case of three RxD-blocks
1841 * per memblock this value can be 0, 1 or 2. */
1842 rxdblock_priv = __vxge_hw_mempool_item_priv(mempoolh,
1843 memblock_index, item,
1844 &memblock_item_idx);
1845
1846 rxdp = (struct vxge_hw_ring_rxd_1 *)
1847 ring->channel.reserve_arr[reserve_index];
1848
1849 uld_priv = ((u8 *)rxdblock_priv + ring->rxd_priv_size * i);
1850
1851 /* pre-format Host_Control */
1852 rxdp->host_control = (u64)(size_t)uld_priv;
1853 }
1854
1855 __vxge_hw_ring_block_memblock_idx_set(item, memblock_index);
1856
1857 if (is_last) {
1858 /* link last one with first one */
1859 __vxge_hw_ring_rxdblock_link(mempoolh, ring, index, 0);
1860 }
1861
1862 if (index > 0) {
1863 /* link this RxD block with previous one */
1864 __vxge_hw_ring_rxdblock_link(mempoolh, ring, index - 1, index);
1865 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001866}
1867
1868/*
Sreenivasa Honnur33632762010-03-28 22:08:30 +00001869 * __vxge_hw_ring_replenish - Initial replenish of RxDs
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001870 * This function replenishes the RxDs from reserve array to work array
1871 */
1872enum vxge_hw_status
Sreenivasa Honnur33632762010-03-28 22:08:30 +00001873vxge_hw_ring_replenish(struct __vxge_hw_ring *ring)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001874{
1875 void *rxd;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001876 struct __vxge_hw_channel *channel;
1877 enum vxge_hw_status status = VXGE_HW_OK;
1878
1879 channel = &ring->channel;
1880
1881 while (vxge_hw_channel_dtr_count(channel) > 0) {
1882
1883 status = vxge_hw_ring_rxd_reserve(ring, &rxd);
1884
1885 vxge_assert(status == VXGE_HW_OK);
1886
1887 if (ring->rxd_init) {
1888 status = ring->rxd_init(rxd, channel->userdata);
1889 if (status != VXGE_HW_OK) {
1890 vxge_hw_ring_rxd_free(ring, rxd);
1891 goto exit;
1892 }
1893 }
1894
1895 vxge_hw_ring_rxd_post(ring, rxd);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001896 }
1897 status = VXGE_HW_OK;
1898exit:
1899 return status;
1900}
1901
1902/*
1903 * __vxge_hw_ring_create - Create a Ring
1904 * This function creates Ring and initializes it.
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001905 */
stephen hemminger42821a52010-10-21 07:50:53 +00001906static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00001907__vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
1908 struct vxge_hw_ring_attr *attr)
1909{
1910 enum vxge_hw_status status = VXGE_HW_OK;
1911 struct __vxge_hw_ring *ring;
1912 u32 ring_length;
1913 struct vxge_hw_ring_config *config;
1914 struct __vxge_hw_device *hldev;
1915 u32 vp_id;
1916 struct vxge_hw_mempool_cbs ring_mp_callback;
1917
1918 if ((vp == NULL) || (attr == NULL)) {
1919 status = VXGE_HW_FAIL;
1920 goto exit;
1921 }
1922
1923 hldev = vp->vpath->hldev;
1924 vp_id = vp->vpath->vp_id;
1925
1926 config = &hldev->config.vp_config[vp_id].ring;
1927
1928 ring_length = config->ring_blocks *
1929 vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
1930
1931 ring = (struct __vxge_hw_ring *)__vxge_hw_channel_allocate(vp,
1932 VXGE_HW_CHANNEL_TYPE_RING,
1933 ring_length,
1934 attr->per_rxd_space,
1935 attr->userdata);
1936
1937 if (ring == NULL) {
1938 status = VXGE_HW_ERR_OUT_OF_MEMORY;
1939 goto exit;
1940 }
1941
1942 vp->vpath->ringh = ring;
1943 ring->vp_id = vp_id;
1944 ring->vp_reg = vp->vpath->vp_reg;
1945 ring->common_reg = hldev->common_reg;
1946 ring->stats = &vp->vpath->sw_stats->ring_stats;
1947 ring->config = config;
1948 ring->callback = attr->callback;
1949 ring->rxd_init = attr->rxd_init;
1950 ring->rxd_term = attr->rxd_term;
1951 ring->buffer_mode = config->buffer_mode;
1952 ring->rxds_limit = config->rxds_limit;
1953
1954 ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
1955 ring->rxd_priv_size =
1956 sizeof(struct __vxge_hw_ring_rxd_priv) + attr->per_rxd_space;
1957 ring->per_rxd_space = attr->per_rxd_space;
1958
1959 ring->rxd_priv_size =
1960 ((ring->rxd_priv_size + VXGE_CACHE_LINE_SIZE - 1) /
1961 VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
1962
1963 /* how many RxDs can fit into one block. Depends on configured
1964 * buffer_mode. */
1965 ring->rxds_per_block =
1966 vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
1967
1968 /* calculate actual RxD block private size */
1969 ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
1970 ring_mp_callback.item_func_alloc = __vxge_hw_ring_mempool_item_alloc;
1971 ring->mempool = __vxge_hw_mempool_create(hldev,
1972 VXGE_HW_BLOCK_SIZE,
1973 VXGE_HW_BLOCK_SIZE,
1974 ring->rxdblock_priv_size,
1975 ring->config->ring_blocks,
1976 ring->config->ring_blocks,
1977 &ring_mp_callback,
1978 ring);
1979
1980 if (ring->mempool == NULL) {
1981 __vxge_hw_ring_delete(vp);
1982 return VXGE_HW_ERR_OUT_OF_MEMORY;
1983 }
1984
1985 status = __vxge_hw_channel_initialize(&ring->channel);
1986 if (status != VXGE_HW_OK) {
1987 __vxge_hw_ring_delete(vp);
1988 goto exit;
1989 }
1990
1991 /* Note:
1992 * Specifying rxd_init callback means two things:
1993 * 1) rxds need to be initialized by driver at channel-open time;
1994 * 2) rxds need to be posted at channel-open time
1995 * (that's what the initial_replenish() below does)
1996 * Currently we don't have a case when the 1) is done without the 2).
1997 */
1998 if (ring->rxd_init) {
Sreenivasa Honnur33632762010-03-28 22:08:30 +00001999 status = vxge_hw_ring_replenish(ring);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002000 if (status != VXGE_HW_OK) {
2001 __vxge_hw_ring_delete(vp);
2002 goto exit;
2003 }
2004 }
2005
2006 /* initial replenish will increment the counter in its post() routine,
2007 * we have to reset it */
2008 ring->stats->common_stats.usage_cnt = 0;
2009exit:
2010 return status;
2011}
2012
2013/*
2014 * __vxge_hw_ring_abort - Returns the RxD
2015 * This function terminates the RxDs of ring
2016 */
stephen hemminger42821a52010-10-21 07:50:53 +00002017static enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002018{
2019 void *rxdh;
2020 struct __vxge_hw_channel *channel;
2021
2022 channel = &ring->channel;
2023
2024 for (;;) {
2025 vxge_hw_channel_dtr_try_complete(channel, &rxdh);
2026
2027 if (rxdh == NULL)
2028 break;
2029
2030 vxge_hw_channel_dtr_complete(channel);
2031
2032 if (ring->rxd_term)
2033 ring->rxd_term(rxdh, VXGE_HW_RXD_STATE_POSTED,
2034 channel->userdata);
2035
2036 vxge_hw_channel_dtr_free(channel, rxdh);
2037 }
2038
2039 return VXGE_HW_OK;
2040}
2041
2042/*
2043 * __vxge_hw_ring_reset - Resets the ring
2044 * This function resets the ring during vpath reset operation
2045 */
stephen hemminger42821a52010-10-21 07:50:53 +00002046static enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002047{
2048 enum vxge_hw_status status = VXGE_HW_OK;
2049 struct __vxge_hw_channel *channel;
2050
2051 channel = &ring->channel;
2052
2053 __vxge_hw_ring_abort(ring);
2054
2055 status = __vxge_hw_channel_reset(channel);
2056
2057 if (status != VXGE_HW_OK)
2058 goto exit;
2059
2060 if (ring->rxd_init) {
Sreenivasa Honnur33632762010-03-28 22:08:30 +00002061 status = vxge_hw_ring_replenish(ring);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002062 if (status != VXGE_HW_OK)
2063 goto exit;
2064 }
2065exit:
2066 return status;
2067}
2068
2069/*
2070 * __vxge_hw_ring_delete - Removes the ring
2071 * This function freeup the memory pool and removes the ring
2072 */
stephen hemminger42821a52010-10-21 07:50:53 +00002073static enum vxge_hw_status __vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002074{
2075 struct __vxge_hw_ring *ring = vp->vpath->ringh;
2076
2077 __vxge_hw_ring_abort(ring);
2078
2079 if (ring->mempool)
2080 __vxge_hw_mempool_destroy(ring->mempool);
2081
2082 vp->vpath->ringh = NULL;
2083 __vxge_hw_channel_free(&ring->channel);
2084
2085 return VXGE_HW_OK;
2086}
2087
2088/*
2089 * __vxge_hw_mempool_grow
2090 * Will resize mempool up to %num_allocate value.
2091 */
stephen hemminger42821a52010-10-21 07:50:53 +00002092static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002093__vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate,
2094 u32 *num_allocated)
2095{
2096 u32 i, first_time = mempool->memblocks_allocated == 0 ? 1 : 0;
2097 u32 n_items = mempool->items_per_memblock;
2098 u32 start_block_idx = mempool->memblocks_allocated;
2099 u32 end_block_idx = mempool->memblocks_allocated + num_allocate;
2100 enum vxge_hw_status status = VXGE_HW_OK;
2101
2102 *num_allocated = 0;
2103
2104 if (end_block_idx > mempool->memblocks_max) {
2105 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2106 goto exit;
2107 }
2108
2109 for (i = start_block_idx; i < end_block_idx; i++) {
2110 u32 j;
2111 u32 is_last = ((end_block_idx - 1) == i);
2112 struct vxge_hw_mempool_dma *dma_object =
2113 mempool->memblocks_dma_arr + i;
2114 void *the_memblock;
2115
2116 /* allocate memblock's private part. Each DMA memblock
2117 * has a space allocated for item's private usage upon
2118 * mempool's user request. Each time mempool grows, it will
2119 * allocate new memblock and its private part at once.
2120 * This helps to minimize memory usage a lot. */
2121 mempool->memblocks_priv_arr[i] =
2122 vmalloc(mempool->items_priv_size * n_items);
2123 if (mempool->memblocks_priv_arr[i] == NULL) {
2124 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2125 goto exit;
2126 }
2127
2128 memset(mempool->memblocks_priv_arr[i], 0,
2129 mempool->items_priv_size * n_items);
2130
2131 /* allocate DMA-capable memblock */
2132 mempool->memblocks_arr[i] =
2133 __vxge_hw_blockpool_malloc(mempool->devh,
2134 mempool->memblock_size, dma_object);
2135 if (mempool->memblocks_arr[i] == NULL) {
2136 vfree(mempool->memblocks_priv_arr[i]);
2137 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2138 goto exit;
2139 }
2140
2141 (*num_allocated)++;
2142 mempool->memblocks_allocated++;
2143
2144 memset(mempool->memblocks_arr[i], 0, mempool->memblock_size);
2145
2146 the_memblock = mempool->memblocks_arr[i];
2147
2148 /* fill the items hash array */
2149 for (j = 0; j < n_items; j++) {
2150 u32 index = i * n_items + j;
2151
2152 if (first_time && index >= mempool->items_initial)
2153 break;
2154
2155 mempool->items_arr[index] =
2156 ((char *)the_memblock + j*mempool->item_size);
2157
2158 /* let caller to do more job on each item */
2159 if (mempool->item_func_alloc != NULL)
2160 mempool->item_func_alloc(mempool, i,
2161 dma_object, index, is_last);
2162
2163 mempool->items_current = index + 1;
2164 }
2165
2166 if (first_time && mempool->items_current ==
2167 mempool->items_initial)
2168 break;
2169 }
2170exit:
2171 return status;
2172}
2173
2174/*
2175 * vxge_hw_mempool_create
2176 * This function will create memory pool object. Pool may grow but will
2177 * never shrink. Pool consists of number of dynamically allocated blocks
2178 * with size enough to hold %items_initial number of items. Memory is
2179 * DMA-able but client must map/unmap before interoperating with the device.
2180 */
stephen hemminger42821a52010-10-21 07:50:53 +00002181static struct vxge_hw_mempool*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002182__vxge_hw_mempool_create(
2183 struct __vxge_hw_device *devh,
2184 u32 memblock_size,
2185 u32 item_size,
2186 u32 items_priv_size,
2187 u32 items_initial,
2188 u32 items_max,
2189 struct vxge_hw_mempool_cbs *mp_callback,
2190 void *userdata)
2191{
2192 enum vxge_hw_status status = VXGE_HW_OK;
2193 u32 memblocks_to_allocate;
2194 struct vxge_hw_mempool *mempool = NULL;
2195 u32 allocated;
2196
2197 if (memblock_size < item_size) {
2198 status = VXGE_HW_FAIL;
2199 goto exit;
2200 }
2201
2202 mempool = (struct vxge_hw_mempool *)
2203 vmalloc(sizeof(struct vxge_hw_mempool));
2204 if (mempool == NULL) {
2205 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2206 goto exit;
2207 }
2208 memset(mempool, 0, sizeof(struct vxge_hw_mempool));
2209
2210 mempool->devh = devh;
2211 mempool->memblock_size = memblock_size;
2212 mempool->items_max = items_max;
2213 mempool->items_initial = items_initial;
2214 mempool->item_size = item_size;
2215 mempool->items_priv_size = items_priv_size;
2216 mempool->item_func_alloc = mp_callback->item_func_alloc;
2217 mempool->userdata = userdata;
2218
2219 mempool->memblocks_allocated = 0;
2220
2221 mempool->items_per_memblock = memblock_size / item_size;
2222
2223 mempool->memblocks_max = (items_max + mempool->items_per_memblock - 1) /
2224 mempool->items_per_memblock;
2225
2226 /* allocate array of memblocks */
2227 mempool->memblocks_arr =
2228 (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
2229 if (mempool->memblocks_arr == NULL) {
2230 __vxge_hw_mempool_destroy(mempool);
2231 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2232 mempool = NULL;
2233 goto exit;
2234 }
2235 memset(mempool->memblocks_arr, 0,
2236 sizeof(void *) * mempool->memblocks_max);
2237
2238 /* allocate array of private parts of items per memblocks */
2239 mempool->memblocks_priv_arr =
2240 (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
2241 if (mempool->memblocks_priv_arr == NULL) {
2242 __vxge_hw_mempool_destroy(mempool);
2243 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2244 mempool = NULL;
2245 goto exit;
2246 }
2247 memset(mempool->memblocks_priv_arr, 0,
2248 sizeof(void *) * mempool->memblocks_max);
2249
2250 /* allocate array of memblocks DMA objects */
2251 mempool->memblocks_dma_arr = (struct vxge_hw_mempool_dma *)
2252 vmalloc(sizeof(struct vxge_hw_mempool_dma) *
2253 mempool->memblocks_max);
2254
2255 if (mempool->memblocks_dma_arr == NULL) {
2256 __vxge_hw_mempool_destroy(mempool);
2257 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2258 mempool = NULL;
2259 goto exit;
2260 }
2261 memset(mempool->memblocks_dma_arr, 0,
2262 sizeof(struct vxge_hw_mempool_dma) *
2263 mempool->memblocks_max);
2264
2265 /* allocate hash array of items */
2266 mempool->items_arr =
2267 (void **) vmalloc(sizeof(void *) * mempool->items_max);
2268 if (mempool->items_arr == NULL) {
2269 __vxge_hw_mempool_destroy(mempool);
2270 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2271 mempool = NULL;
2272 goto exit;
2273 }
2274 memset(mempool->items_arr, 0, sizeof(void *) * mempool->items_max);
2275
2276 /* calculate initial number of memblocks */
2277 memblocks_to_allocate = (mempool->items_initial +
2278 mempool->items_per_memblock - 1) /
2279 mempool->items_per_memblock;
2280
2281 /* pre-allocate the mempool */
2282 status = __vxge_hw_mempool_grow(mempool, memblocks_to_allocate,
2283 &allocated);
2284 if (status != VXGE_HW_OK) {
2285 __vxge_hw_mempool_destroy(mempool);
2286 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2287 mempool = NULL;
2288 goto exit;
2289 }
2290
2291exit:
2292 return mempool;
2293}
2294
2295/*
2296 * vxge_hw_mempool_destroy
2297 */
stephen hemminger42821a52010-10-21 07:50:53 +00002298static void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002299{
2300 u32 i, j;
2301 struct __vxge_hw_device *devh = mempool->devh;
2302
2303 for (i = 0; i < mempool->memblocks_allocated; i++) {
2304 struct vxge_hw_mempool_dma *dma_object;
2305
2306 vxge_assert(mempool->memblocks_arr[i]);
2307 vxge_assert(mempool->memblocks_dma_arr + i);
2308
2309 dma_object = mempool->memblocks_dma_arr + i;
2310
2311 for (j = 0; j < mempool->items_per_memblock; j++) {
2312 u32 index = i * mempool->items_per_memblock + j;
2313
2314 /* to skip last partially filled(if any) memblock */
2315 if (index >= mempool->items_current)
2316 break;
2317 }
2318
2319 vfree(mempool->memblocks_priv_arr[i]);
2320
2321 __vxge_hw_blockpool_free(devh, mempool->memblocks_arr[i],
2322 mempool->memblock_size, dma_object);
2323 }
2324
Figo.zhang50d36a92009-06-10 04:21:55 +00002325 vfree(mempool->items_arr);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002326
Figo.zhang50d36a92009-06-10 04:21:55 +00002327 vfree(mempool->memblocks_dma_arr);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002328
Figo.zhang50d36a92009-06-10 04:21:55 +00002329 vfree(mempool->memblocks_priv_arr);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002330
Figo.zhang50d36a92009-06-10 04:21:55 +00002331 vfree(mempool->memblocks_arr);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002332
2333 vfree(mempool);
2334}
2335
2336/*
2337 * __vxge_hw_device_fifo_config_check - Check fifo configuration.
2338 * Check the fifo configuration
2339 */
2340enum vxge_hw_status
2341__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config)
2342{
2343 if ((fifo_config->fifo_blocks < VXGE_HW_MIN_FIFO_BLOCKS) ||
2344 (fifo_config->fifo_blocks > VXGE_HW_MAX_FIFO_BLOCKS))
2345 return VXGE_HW_BADCFG_FIFO_BLOCKS;
2346
2347 return VXGE_HW_OK;
2348}
2349
2350/*
2351 * __vxge_hw_device_vpath_config_check - Check vpath configuration.
2352 * Check the vpath configuration
2353 */
stephen hemminger42821a52010-10-21 07:50:53 +00002354static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002355__vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config)
2356{
2357 enum vxge_hw_status status;
2358
2359 if ((vp_config->min_bandwidth < VXGE_HW_VPATH_BANDWIDTH_MIN) ||
2360 (vp_config->min_bandwidth >
2361 VXGE_HW_VPATH_BANDWIDTH_MAX))
2362 return VXGE_HW_BADCFG_VPATH_MIN_BANDWIDTH;
2363
2364 status = __vxge_hw_device_fifo_config_check(&vp_config->fifo);
2365 if (status != VXGE_HW_OK)
2366 return status;
2367
2368 if ((vp_config->mtu != VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) &&
2369 ((vp_config->mtu < VXGE_HW_VPATH_MIN_INITIAL_MTU) ||
2370 (vp_config->mtu > VXGE_HW_VPATH_MAX_INITIAL_MTU)))
2371 return VXGE_HW_BADCFG_VPATH_MTU;
2372
2373 if ((vp_config->rpa_strip_vlan_tag !=
2374 VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) &&
2375 (vp_config->rpa_strip_vlan_tag !=
2376 VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE) &&
2377 (vp_config->rpa_strip_vlan_tag !=
2378 VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_DISABLE))
2379 return VXGE_HW_BADCFG_VPATH_RPA_STRIP_VLAN_TAG;
2380
2381 return VXGE_HW_OK;
2382}
2383
2384/*
2385 * __vxge_hw_device_config_check - Check device configuration.
2386 * Check the device configuration
2387 */
2388enum vxge_hw_status
2389__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
2390{
2391 u32 i;
2392 enum vxge_hw_status status;
2393
2394 if ((new_config->intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
2395 (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
2396 (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
2397 (new_config->intr_mode != VXGE_HW_INTR_MODE_DEF))
2398 return VXGE_HW_BADCFG_INTR_MODE;
2399
2400 if ((new_config->rts_mac_en != VXGE_HW_RTS_MAC_DISABLE) &&
2401 (new_config->rts_mac_en != VXGE_HW_RTS_MAC_ENABLE))
2402 return VXGE_HW_BADCFG_RTS_MAC_EN;
2403
2404 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
2405 status = __vxge_hw_device_vpath_config_check(
2406 &new_config->vp_config[i]);
2407 if (status != VXGE_HW_OK)
2408 return status;
2409 }
2410
2411 return VXGE_HW_OK;
2412}
2413
2414/*
2415 * vxge_hw_device_config_default_get - Initialize device config with defaults.
2416 * Initialize Titan device config with default values.
2417 */
2418enum vxge_hw_status __devinit
2419vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config)
2420{
2421 u32 i;
2422
2423 device_config->dma_blockpool_initial =
2424 VXGE_HW_INITIAL_DMA_BLOCK_POOL_SIZE;
2425 device_config->dma_blockpool_max = VXGE_HW_MAX_DMA_BLOCK_POOL_SIZE;
2426 device_config->intr_mode = VXGE_HW_INTR_MODE_DEF;
2427 device_config->rth_en = VXGE_HW_RTH_DEFAULT;
2428 device_config->rth_it_type = VXGE_HW_RTH_IT_TYPE_DEFAULT;
2429 device_config->device_poll_millis = VXGE_HW_DEF_DEVICE_POLL_MILLIS;
2430 device_config->rts_mac_en = VXGE_HW_RTS_MAC_DEFAULT;
2431
2432 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
2433
2434 device_config->vp_config[i].vp_id = i;
2435
2436 device_config->vp_config[i].min_bandwidth =
2437 VXGE_HW_VPATH_BANDWIDTH_DEFAULT;
2438
2439 device_config->vp_config[i].ring.enable = VXGE_HW_RING_DEFAULT;
2440
2441 device_config->vp_config[i].ring.ring_blocks =
2442 VXGE_HW_DEF_RING_BLOCKS;
2443
2444 device_config->vp_config[i].ring.buffer_mode =
2445 VXGE_HW_RING_RXD_BUFFER_MODE_DEFAULT;
2446
2447 device_config->vp_config[i].ring.scatter_mode =
2448 VXGE_HW_RING_SCATTER_MODE_USE_FLASH_DEFAULT;
2449
2450 device_config->vp_config[i].ring.rxds_limit =
2451 VXGE_HW_DEF_RING_RXDS_LIMIT;
2452
2453 device_config->vp_config[i].fifo.enable = VXGE_HW_FIFO_ENABLE;
2454
2455 device_config->vp_config[i].fifo.fifo_blocks =
2456 VXGE_HW_MIN_FIFO_BLOCKS;
2457
2458 device_config->vp_config[i].fifo.max_frags =
2459 VXGE_HW_MAX_FIFO_FRAGS;
2460
2461 device_config->vp_config[i].fifo.memblock_size =
2462 VXGE_HW_DEF_FIFO_MEMBLOCK_SIZE;
2463
2464 device_config->vp_config[i].fifo.alignment_size =
2465 VXGE_HW_DEF_FIFO_ALIGNMENT_SIZE;
2466
2467 device_config->vp_config[i].fifo.intr =
2468 VXGE_HW_FIFO_QUEUE_INTR_DEFAULT;
2469
2470 device_config->vp_config[i].fifo.no_snoop_bits =
2471 VXGE_HW_FIFO_NO_SNOOP_DEFAULT;
2472 device_config->vp_config[i].tti.intr_enable =
2473 VXGE_HW_TIM_INTR_DEFAULT;
2474
2475 device_config->vp_config[i].tti.btimer_val =
2476 VXGE_HW_USE_FLASH_DEFAULT;
2477
2478 device_config->vp_config[i].tti.timer_ac_en =
2479 VXGE_HW_USE_FLASH_DEFAULT;
2480
2481 device_config->vp_config[i].tti.timer_ci_en =
2482 VXGE_HW_USE_FLASH_DEFAULT;
2483
2484 device_config->vp_config[i].tti.timer_ri_en =
2485 VXGE_HW_USE_FLASH_DEFAULT;
2486
2487 device_config->vp_config[i].tti.rtimer_val =
2488 VXGE_HW_USE_FLASH_DEFAULT;
2489
2490 device_config->vp_config[i].tti.util_sel =
2491 VXGE_HW_USE_FLASH_DEFAULT;
2492
2493 device_config->vp_config[i].tti.ltimer_val =
2494 VXGE_HW_USE_FLASH_DEFAULT;
2495
2496 device_config->vp_config[i].tti.urange_a =
2497 VXGE_HW_USE_FLASH_DEFAULT;
2498
2499 device_config->vp_config[i].tti.uec_a =
2500 VXGE_HW_USE_FLASH_DEFAULT;
2501
2502 device_config->vp_config[i].tti.urange_b =
2503 VXGE_HW_USE_FLASH_DEFAULT;
2504
2505 device_config->vp_config[i].tti.uec_b =
2506 VXGE_HW_USE_FLASH_DEFAULT;
2507
2508 device_config->vp_config[i].tti.urange_c =
2509 VXGE_HW_USE_FLASH_DEFAULT;
2510
2511 device_config->vp_config[i].tti.uec_c =
2512 VXGE_HW_USE_FLASH_DEFAULT;
2513
2514 device_config->vp_config[i].tti.uec_d =
2515 VXGE_HW_USE_FLASH_DEFAULT;
2516
2517 device_config->vp_config[i].rti.intr_enable =
2518 VXGE_HW_TIM_INTR_DEFAULT;
2519
2520 device_config->vp_config[i].rti.btimer_val =
2521 VXGE_HW_USE_FLASH_DEFAULT;
2522
2523 device_config->vp_config[i].rti.timer_ac_en =
2524 VXGE_HW_USE_FLASH_DEFAULT;
2525
2526 device_config->vp_config[i].rti.timer_ci_en =
2527 VXGE_HW_USE_FLASH_DEFAULT;
2528
2529 device_config->vp_config[i].rti.timer_ri_en =
2530 VXGE_HW_USE_FLASH_DEFAULT;
2531
2532 device_config->vp_config[i].rti.rtimer_val =
2533 VXGE_HW_USE_FLASH_DEFAULT;
2534
2535 device_config->vp_config[i].rti.util_sel =
2536 VXGE_HW_USE_FLASH_DEFAULT;
2537
2538 device_config->vp_config[i].rti.ltimer_val =
2539 VXGE_HW_USE_FLASH_DEFAULT;
2540
2541 device_config->vp_config[i].rti.urange_a =
2542 VXGE_HW_USE_FLASH_DEFAULT;
2543
2544 device_config->vp_config[i].rti.uec_a =
2545 VXGE_HW_USE_FLASH_DEFAULT;
2546
2547 device_config->vp_config[i].rti.urange_b =
2548 VXGE_HW_USE_FLASH_DEFAULT;
2549
2550 device_config->vp_config[i].rti.uec_b =
2551 VXGE_HW_USE_FLASH_DEFAULT;
2552
2553 device_config->vp_config[i].rti.urange_c =
2554 VXGE_HW_USE_FLASH_DEFAULT;
2555
2556 device_config->vp_config[i].rti.uec_c =
2557 VXGE_HW_USE_FLASH_DEFAULT;
2558
2559 device_config->vp_config[i].rti.uec_d =
2560 VXGE_HW_USE_FLASH_DEFAULT;
2561
2562 device_config->vp_config[i].mtu =
2563 VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU;
2564
2565 device_config->vp_config[i].rpa_strip_vlan_tag =
2566 VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT;
2567 }
2568
2569 return VXGE_HW_OK;
2570}
2571
2572/*
2573 * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion.
2574 * Set the swapper bits appropriately for the lagacy section.
2575 */
stephen hemminger42821a52010-10-21 07:50:53 +00002576static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002577__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg)
2578{
2579 u64 val64;
2580 enum vxge_hw_status status = VXGE_HW_OK;
2581
2582 val64 = readq(&legacy_reg->toc_swapper_fb);
2583
2584 wmb();
2585
2586 switch (val64) {
2587
2588 case VXGE_HW_SWAPPER_INITIAL_VALUE:
2589 return status;
2590
2591 case VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED:
2592 writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
2593 &legacy_reg->pifm_rd_swap_en);
2594 writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
2595 &legacy_reg->pifm_rd_flip_en);
2596 writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
2597 &legacy_reg->pifm_wr_swap_en);
2598 writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
2599 &legacy_reg->pifm_wr_flip_en);
2600 break;
2601
2602 case VXGE_HW_SWAPPER_BYTE_SWAPPED:
2603 writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
2604 &legacy_reg->pifm_rd_swap_en);
2605 writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
2606 &legacy_reg->pifm_wr_swap_en);
2607 break;
2608
2609 case VXGE_HW_SWAPPER_BIT_FLIPPED:
2610 writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
2611 &legacy_reg->pifm_rd_flip_en);
2612 writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
2613 &legacy_reg->pifm_wr_flip_en);
2614 break;
2615 }
2616
2617 wmb();
2618
2619 val64 = readq(&legacy_reg->toc_swapper_fb);
2620
2621 if (val64 != VXGE_HW_SWAPPER_INITIAL_VALUE)
2622 status = VXGE_HW_ERR_SWAPPER_CTRL;
2623
2624 return status;
2625}
2626
2627/*
2628 * __vxge_hw_vpath_swapper_set - Set the swapper bits for the vpath.
2629 * Set the swapper bits appropriately for the vpath.
2630 */
stephen hemminger42821a52010-10-21 07:50:53 +00002631static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002632__vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg)
2633{
2634#ifndef __BIG_ENDIAN
2635 u64 val64;
2636
2637 val64 = readq(&vpath_reg->vpath_general_cfg1);
2638 wmb();
2639 val64 |= VXGE_HW_VPATH_GENERAL_CFG1_CTL_BYTE_SWAPEN;
2640 writeq(val64, &vpath_reg->vpath_general_cfg1);
2641 wmb();
2642#endif
2643 return VXGE_HW_OK;
2644}
2645
2646/*
2647 * __vxge_hw_kdfc_swapper_set - Set the swapper bits for the kdfc.
2648 * Set the swapper bits appropriately for the vpath.
2649 */
stephen hemminger42821a52010-10-21 07:50:53 +00002650static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002651__vxge_hw_kdfc_swapper_set(
2652 struct vxge_hw_legacy_reg __iomem *legacy_reg,
2653 struct vxge_hw_vpath_reg __iomem *vpath_reg)
2654{
2655 u64 val64;
2656
2657 val64 = readq(&legacy_reg->pifm_wr_swap_en);
2658
2659 if (val64 == VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE) {
2660 val64 = readq(&vpath_reg->kdfcctl_cfg0);
2661 wmb();
2662
2663 val64 |= VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO0 |
2664 VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO1 |
2665 VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO2;
2666
2667 writeq(val64, &vpath_reg->kdfcctl_cfg0);
2668 wmb();
2669 }
2670
2671 return VXGE_HW_OK;
2672}
2673
2674/*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002675 * vxge_hw_mgmt_reg_read - Read Titan register.
2676 */
2677enum vxge_hw_status
2678vxge_hw_mgmt_reg_read(struct __vxge_hw_device *hldev,
2679 enum vxge_hw_mgmt_reg_type type,
2680 u32 index, u32 offset, u64 *value)
2681{
2682 enum vxge_hw_status status = VXGE_HW_OK;
2683
2684 if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
2685 status = VXGE_HW_ERR_INVALID_DEVICE;
2686 goto exit;
2687 }
2688
2689 switch (type) {
2690 case vxge_hw_mgmt_reg_type_legacy:
2691 if (offset > sizeof(struct vxge_hw_legacy_reg) - 8) {
2692 status = VXGE_HW_ERR_INVALID_OFFSET;
2693 break;
2694 }
2695 *value = readq((void __iomem *)hldev->legacy_reg + offset);
2696 break;
2697 case vxge_hw_mgmt_reg_type_toc:
2698 if (offset > sizeof(struct vxge_hw_toc_reg) - 8) {
2699 status = VXGE_HW_ERR_INVALID_OFFSET;
2700 break;
2701 }
2702 *value = readq((void __iomem *)hldev->toc_reg + offset);
2703 break;
2704 case vxge_hw_mgmt_reg_type_common:
2705 if (offset > sizeof(struct vxge_hw_common_reg) - 8) {
2706 status = VXGE_HW_ERR_INVALID_OFFSET;
2707 break;
2708 }
2709 *value = readq((void __iomem *)hldev->common_reg + offset);
2710 break;
2711 case vxge_hw_mgmt_reg_type_mrpcim:
2712 if (!(hldev->access_rights &
2713 VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
2714 status = VXGE_HW_ERR_PRIVILAGED_OPEARATION;
2715 break;
2716 }
2717 if (offset > sizeof(struct vxge_hw_mrpcim_reg) - 8) {
2718 status = VXGE_HW_ERR_INVALID_OFFSET;
2719 break;
2720 }
2721 *value = readq((void __iomem *)hldev->mrpcim_reg + offset);
2722 break;
2723 case vxge_hw_mgmt_reg_type_srpcim:
2724 if (!(hldev->access_rights &
2725 VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM)) {
2726 status = VXGE_HW_ERR_PRIVILAGED_OPEARATION;
2727 break;
2728 }
2729 if (index > VXGE_HW_TITAN_SRPCIM_REG_SPACES - 1) {
2730 status = VXGE_HW_ERR_INVALID_INDEX;
2731 break;
2732 }
2733 if (offset > sizeof(struct vxge_hw_srpcim_reg) - 8) {
2734 status = VXGE_HW_ERR_INVALID_OFFSET;
2735 break;
2736 }
2737 *value = readq((void __iomem *)hldev->srpcim_reg[index] +
2738 offset);
2739 break;
2740 case vxge_hw_mgmt_reg_type_vpmgmt:
2741 if ((index > VXGE_HW_TITAN_VPMGMT_REG_SPACES - 1) ||
2742 (!(hldev->vpath_assignments & vxge_mBIT(index)))) {
2743 status = VXGE_HW_ERR_INVALID_INDEX;
2744 break;
2745 }
2746 if (offset > sizeof(struct vxge_hw_vpmgmt_reg) - 8) {
2747 status = VXGE_HW_ERR_INVALID_OFFSET;
2748 break;
2749 }
2750 *value = readq((void __iomem *)hldev->vpmgmt_reg[index] +
2751 offset);
2752 break;
2753 case vxge_hw_mgmt_reg_type_vpath:
2754 if ((index > VXGE_HW_TITAN_VPATH_REG_SPACES - 1) ||
2755 (!(hldev->vpath_assignments & vxge_mBIT(index)))) {
2756 status = VXGE_HW_ERR_INVALID_INDEX;
2757 break;
2758 }
2759 if (index > VXGE_HW_TITAN_VPATH_REG_SPACES - 1) {
2760 status = VXGE_HW_ERR_INVALID_INDEX;
2761 break;
2762 }
2763 if (offset > sizeof(struct vxge_hw_vpath_reg) - 8) {
2764 status = VXGE_HW_ERR_INVALID_OFFSET;
2765 break;
2766 }
2767 *value = readq((void __iomem *)hldev->vpath_reg[index] +
2768 offset);
2769 break;
2770 default:
2771 status = VXGE_HW_ERR_INVALID_TYPE;
2772 break;
2773 }
2774
2775exit:
2776 return status;
2777}
2778
2779/*
Sreenivasa Honnurfa41fd12009-10-05 01:56:35 +00002780 * vxge_hw_vpath_strip_fcs_check - Check for FCS strip.
2781 */
2782enum vxge_hw_status
2783vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask)
2784{
2785 struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
2786 enum vxge_hw_status status = VXGE_HW_OK;
2787 int i = 0, j = 0;
2788
2789 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
2790 if (!((vpath_mask) & vxge_mBIT(i)))
2791 continue;
2792 vpmgmt_reg = hldev->vpmgmt_reg[i];
2793 for (j = 0; j < VXGE_HW_MAC_MAX_MAC_PORT_ID; j++) {
2794 if (readq(&vpmgmt_reg->rxmac_cfg0_port_vpmgmt_clone[j])
2795 & VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_STRIP_FCS)
2796 return VXGE_HW_FAIL;
2797 }
2798 }
2799 return status;
2800}
2801/*
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002802 * vxge_hw_mgmt_reg_Write - Write Titan register.
2803 */
2804enum vxge_hw_status
2805vxge_hw_mgmt_reg_write(struct __vxge_hw_device *hldev,
2806 enum vxge_hw_mgmt_reg_type type,
2807 u32 index, u32 offset, u64 value)
2808{
2809 enum vxge_hw_status status = VXGE_HW_OK;
2810
2811 if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
2812 status = VXGE_HW_ERR_INVALID_DEVICE;
2813 goto exit;
2814 }
2815
2816 switch (type) {
2817 case vxge_hw_mgmt_reg_type_legacy:
2818 if (offset > sizeof(struct vxge_hw_legacy_reg) - 8) {
2819 status = VXGE_HW_ERR_INVALID_OFFSET;
2820 break;
2821 }
2822 writeq(value, (void __iomem *)hldev->legacy_reg + offset);
2823 break;
2824 case vxge_hw_mgmt_reg_type_toc:
2825 if (offset > sizeof(struct vxge_hw_toc_reg) - 8) {
2826 status = VXGE_HW_ERR_INVALID_OFFSET;
2827 break;
2828 }
2829 writeq(value, (void __iomem *)hldev->toc_reg + offset);
2830 break;
2831 case vxge_hw_mgmt_reg_type_common:
2832 if (offset > sizeof(struct vxge_hw_common_reg) - 8) {
2833 status = VXGE_HW_ERR_INVALID_OFFSET;
2834 break;
2835 }
2836 writeq(value, (void __iomem *)hldev->common_reg + offset);
2837 break;
2838 case vxge_hw_mgmt_reg_type_mrpcim:
2839 if (!(hldev->access_rights &
2840 VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
2841 status = VXGE_HW_ERR_PRIVILAGED_OPEARATION;
2842 break;
2843 }
2844 if (offset > sizeof(struct vxge_hw_mrpcim_reg) - 8) {
2845 status = VXGE_HW_ERR_INVALID_OFFSET;
2846 break;
2847 }
2848 writeq(value, (void __iomem *)hldev->mrpcim_reg + offset);
2849 break;
2850 case vxge_hw_mgmt_reg_type_srpcim:
2851 if (!(hldev->access_rights &
2852 VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM)) {
2853 status = VXGE_HW_ERR_PRIVILAGED_OPEARATION;
2854 break;
2855 }
2856 if (index > VXGE_HW_TITAN_SRPCIM_REG_SPACES - 1) {
2857 status = VXGE_HW_ERR_INVALID_INDEX;
2858 break;
2859 }
2860 if (offset > sizeof(struct vxge_hw_srpcim_reg) - 8) {
2861 status = VXGE_HW_ERR_INVALID_OFFSET;
2862 break;
2863 }
2864 writeq(value, (void __iomem *)hldev->srpcim_reg[index] +
2865 offset);
2866
2867 break;
2868 case vxge_hw_mgmt_reg_type_vpmgmt:
2869 if ((index > VXGE_HW_TITAN_VPMGMT_REG_SPACES - 1) ||
2870 (!(hldev->vpath_assignments & vxge_mBIT(index)))) {
2871 status = VXGE_HW_ERR_INVALID_INDEX;
2872 break;
2873 }
2874 if (offset > sizeof(struct vxge_hw_vpmgmt_reg) - 8) {
2875 status = VXGE_HW_ERR_INVALID_OFFSET;
2876 break;
2877 }
2878 writeq(value, (void __iomem *)hldev->vpmgmt_reg[index] +
2879 offset);
2880 break;
2881 case vxge_hw_mgmt_reg_type_vpath:
2882 if ((index > VXGE_HW_TITAN_VPATH_REG_SPACES-1) ||
2883 (!(hldev->vpath_assignments & vxge_mBIT(index)))) {
2884 status = VXGE_HW_ERR_INVALID_INDEX;
2885 break;
2886 }
2887 if (offset > sizeof(struct vxge_hw_vpath_reg) - 8) {
2888 status = VXGE_HW_ERR_INVALID_OFFSET;
2889 break;
2890 }
2891 writeq(value, (void __iomem *)hldev->vpath_reg[index] +
2892 offset);
2893 break;
2894 default:
2895 status = VXGE_HW_ERR_INVALID_TYPE;
2896 break;
2897 }
2898exit:
2899 return status;
2900}
2901
2902/*
2903 * __vxge_hw_fifo_mempool_item_alloc - Allocate List blocks for TxD
2904 * list callback
2905 * This function is callback passed to __vxge_hw_mempool_create to create memory
2906 * pool for TxD list
2907 */
2908static void
2909__vxge_hw_fifo_mempool_item_alloc(
2910 struct vxge_hw_mempool *mempoolh,
2911 u32 memblock_index, struct vxge_hw_mempool_dma *dma_object,
2912 u32 index, u32 is_last)
2913{
2914 u32 memblock_item_idx;
2915 struct __vxge_hw_fifo_txdl_priv *txdl_priv;
2916 struct vxge_hw_fifo_txd *txdp =
2917 (struct vxge_hw_fifo_txd *)mempoolh->items_arr[index];
2918 struct __vxge_hw_fifo *fifo =
2919 (struct __vxge_hw_fifo *)mempoolh->userdata;
2920 void *memblock = mempoolh->memblocks_arr[memblock_index];
2921
2922 vxge_assert(txdp);
2923
2924 txdp->host_control = (u64) (size_t)
2925 __vxge_hw_mempool_item_priv(mempoolh, memblock_index, txdp,
2926 &memblock_item_idx);
2927
2928 txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdp);
2929
2930 vxge_assert(txdl_priv);
2931
2932 fifo->channel.reserve_arr[fifo->channel.reserve_ptr - 1 - index] = txdp;
2933
2934 /* pre-format HW's TxDL's private */
2935 txdl_priv->dma_offset = (char *)txdp - (char *)memblock;
2936 txdl_priv->dma_addr = dma_object->addr + txdl_priv->dma_offset;
2937 txdl_priv->dma_handle = dma_object->handle;
2938 txdl_priv->memblock = memblock;
2939 txdl_priv->first_txdp = txdp;
2940 txdl_priv->next_txdl_priv = NULL;
2941 txdl_priv->alloc_frags = 0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00002942}
2943
2944/*
2945 * __vxge_hw_fifo_create - Create a FIFO
2946 * This function creates FIFO and initializes it.
2947 */
2948enum vxge_hw_status
2949__vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp,
2950 struct vxge_hw_fifo_attr *attr)
2951{
2952 enum vxge_hw_status status = VXGE_HW_OK;
2953 struct __vxge_hw_fifo *fifo;
2954 struct vxge_hw_fifo_config *config;
2955 u32 txdl_size, txdl_per_memblock;
2956 struct vxge_hw_mempool_cbs fifo_mp_callback;
2957 struct __vxge_hw_virtualpath *vpath;
2958
2959 if ((vp == NULL) || (attr == NULL)) {
2960 status = VXGE_HW_ERR_INVALID_HANDLE;
2961 goto exit;
2962 }
2963 vpath = vp->vpath;
2964 config = &vpath->hldev->config.vp_config[vpath->vp_id].fifo;
2965
2966 txdl_size = config->max_frags * sizeof(struct vxge_hw_fifo_txd);
2967
2968 txdl_per_memblock = config->memblock_size / txdl_size;
2969
2970 fifo = (struct __vxge_hw_fifo *)__vxge_hw_channel_allocate(vp,
2971 VXGE_HW_CHANNEL_TYPE_FIFO,
2972 config->fifo_blocks * txdl_per_memblock,
2973 attr->per_txdl_space, attr->userdata);
2974
2975 if (fifo == NULL) {
2976 status = VXGE_HW_ERR_OUT_OF_MEMORY;
2977 goto exit;
2978 }
2979
2980 vpath->fifoh = fifo;
2981 fifo->nofl_db = vpath->nofl_db;
2982
2983 fifo->vp_id = vpath->vp_id;
2984 fifo->vp_reg = vpath->vp_reg;
2985 fifo->stats = &vpath->sw_stats->fifo_stats;
2986
2987 fifo->config = config;
2988
2989 /* apply "interrupts per txdl" attribute */
2990 fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_UTILZ;
2991
2992 if (fifo->config->intr)
2993 fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST;
2994
2995 fifo->no_snoop_bits = config->no_snoop_bits;
2996
2997 /*
2998 * FIFO memory management strategy:
2999 *
3000 * TxDL split into three independent parts:
3001 * - set of TxD's
3002 * - TxD HW private part
3003 * - driver private part
3004 *
3005 * Adaptative memory allocation used. i.e. Memory allocated on
3006 * demand with the size which will fit into one memory block.
3007 * One memory block may contain more than one TxDL.
3008 *
3009 * During "reserve" operations more memory can be allocated on demand
3010 * for example due to FIFO full condition.
3011 *
3012 * Pool of memory memblocks never shrinks except in __vxge_hw_fifo_close
3013 * routine which will essentially stop the channel and free resources.
3014 */
3015
3016 /* TxDL common private size == TxDL private + driver private */
3017 fifo->priv_size =
3018 sizeof(struct __vxge_hw_fifo_txdl_priv) + attr->per_txdl_space;
3019 fifo->priv_size = ((fifo->priv_size + VXGE_CACHE_LINE_SIZE - 1) /
3020 VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
3021
3022 fifo->per_txdl_space = attr->per_txdl_space;
3023
3024 /* recompute txdl size to be cacheline aligned */
3025 fifo->txdl_size = txdl_size;
3026 fifo->txdl_per_memblock = txdl_per_memblock;
3027
3028 fifo->txdl_term = attr->txdl_term;
3029 fifo->callback = attr->callback;
3030
3031 if (fifo->txdl_per_memblock == 0) {
3032 __vxge_hw_fifo_delete(vp);
3033 status = VXGE_HW_ERR_INVALID_BLOCK_SIZE;
3034 goto exit;
3035 }
3036
3037 fifo_mp_callback.item_func_alloc = __vxge_hw_fifo_mempool_item_alloc;
3038
3039 fifo->mempool =
3040 __vxge_hw_mempool_create(vpath->hldev,
3041 fifo->config->memblock_size,
3042 fifo->txdl_size,
3043 fifo->priv_size,
3044 (fifo->config->fifo_blocks * fifo->txdl_per_memblock),
3045 (fifo->config->fifo_blocks * fifo->txdl_per_memblock),
3046 &fifo_mp_callback,
3047 fifo);
3048
3049 if (fifo->mempool == NULL) {
3050 __vxge_hw_fifo_delete(vp);
3051 status = VXGE_HW_ERR_OUT_OF_MEMORY;
3052 goto exit;
3053 }
3054
3055 status = __vxge_hw_channel_initialize(&fifo->channel);
3056 if (status != VXGE_HW_OK) {
3057 __vxge_hw_fifo_delete(vp);
3058 goto exit;
3059 }
3060
3061 vxge_assert(fifo->channel.reserve_ptr);
3062exit:
3063 return status;
3064}
3065
3066/*
3067 * __vxge_hw_fifo_abort - Returns the TxD
3068 * This function terminates the TxDs of fifo
3069 */
stephen hemminger42821a52010-10-21 07:50:53 +00003070static enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003071{
3072 void *txdlh;
3073
3074 for (;;) {
3075 vxge_hw_channel_dtr_try_complete(&fifo->channel, &txdlh);
3076
3077 if (txdlh == NULL)
3078 break;
3079
3080 vxge_hw_channel_dtr_complete(&fifo->channel);
3081
3082 if (fifo->txdl_term) {
3083 fifo->txdl_term(txdlh,
3084 VXGE_HW_TXDL_STATE_POSTED,
3085 fifo->channel.userdata);
3086 }
3087
3088 vxge_hw_channel_dtr_free(&fifo->channel, txdlh);
3089 }
3090
3091 return VXGE_HW_OK;
3092}
3093
3094/*
3095 * __vxge_hw_fifo_reset - Resets the fifo
3096 * This function resets the fifo during vpath reset operation
3097 */
stephen hemminger42821a52010-10-21 07:50:53 +00003098static enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003099{
3100 enum vxge_hw_status status = VXGE_HW_OK;
3101
3102 __vxge_hw_fifo_abort(fifo);
3103 status = __vxge_hw_channel_reset(&fifo->channel);
3104
3105 return status;
3106}
3107
3108/*
3109 * __vxge_hw_fifo_delete - Removes the FIFO
3110 * This function freeup the memory pool and removes the FIFO
3111 */
3112enum vxge_hw_status __vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp)
3113{
3114 struct __vxge_hw_fifo *fifo = vp->vpath->fifoh;
3115
3116 __vxge_hw_fifo_abort(fifo);
3117
3118 if (fifo->mempool)
3119 __vxge_hw_mempool_destroy(fifo->mempool);
3120
3121 vp->vpath->fifoh = NULL;
3122
3123 __vxge_hw_channel_free(&fifo->channel);
3124
3125 return VXGE_HW_OK;
3126}
3127
3128/*
3129 * __vxge_hw_vpath_pci_read - Read the content of given address
3130 * in pci config space.
3131 * Read from the vpath pci config space.
3132 */
stephen hemminger42821a52010-10-21 07:50:53 +00003133static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003134__vxge_hw_vpath_pci_read(struct __vxge_hw_virtualpath *vpath,
3135 u32 phy_func_0, u32 offset, u32 *val)
3136{
3137 u64 val64;
3138 enum vxge_hw_status status = VXGE_HW_OK;
3139 struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
3140
3141 val64 = VXGE_HW_PCI_CONFIG_ACCESS_CFG1_ADDRESS(offset);
3142
3143 if (phy_func_0)
3144 val64 |= VXGE_HW_PCI_CONFIG_ACCESS_CFG1_SEL_FUNC0;
3145
3146 writeq(val64, &vp_reg->pci_config_access_cfg1);
3147 wmb();
3148 writeq(VXGE_HW_PCI_CONFIG_ACCESS_CFG2_REQ,
3149 &vp_reg->pci_config_access_cfg2);
3150 wmb();
3151
3152 status = __vxge_hw_device_register_poll(
3153 &vp_reg->pci_config_access_cfg2,
3154 VXGE_HW_INTR_MASK_ALL, VXGE_HW_DEF_DEVICE_POLL_MILLIS);
3155
3156 if (status != VXGE_HW_OK)
3157 goto exit;
3158
3159 val64 = readq(&vp_reg->pci_config_access_status);
3160
3161 if (val64 & VXGE_HW_PCI_CONFIG_ACCESS_STATUS_ACCESS_ERR) {
3162 status = VXGE_HW_FAIL;
3163 *val = 0;
3164 } else
3165 *val = (u32)vxge_bVALn(val64, 32, 32);
3166exit:
3167 return status;
3168}
3169
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003170/**
3171 * vxge_hw_device_flick_link_led - Flick (blink) link LED.
3172 * @hldev: HW device.
3173 * @on_off: TRUE if flickering to be on, FALSE to be off
3174 *
3175 * Flicker the link LED.
3176 */
3177enum vxge_hw_status
Jon Mason8424e002010-11-11 04:25:56 +00003178vxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev, u64 on_off)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003179{
Jon Mason8424e002010-11-11 04:25:56 +00003180 struct __vxge_hw_virtualpath *vpath;
3181 u64 data0, data1 = 0, steer_ctrl = 0;
3182 enum vxge_hw_status status;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003183
3184 if (hldev == NULL) {
3185 status = VXGE_HW_ERR_INVALID_DEVICE;
3186 goto exit;
3187 }
3188
Jon Mason8424e002010-11-11 04:25:56 +00003189 vpath = &hldev->virtual_paths[hldev->first_vp_id];
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003190
Jon Mason8424e002010-11-11 04:25:56 +00003191 data0 = on_off;
3192 status = vxge_hw_vpath_fw_api(vpath,
3193 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL,
3194 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
3195 0, &data0, &data1, &steer_ctrl);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003196exit:
3197 return status;
3198}
3199
3200/*
3201 * __vxge_hw_vpath_rts_table_get - Get the entries from RTS access tables
3202 */
3203enum vxge_hw_status
Jon Mason8424e002010-11-11 04:25:56 +00003204__vxge_hw_vpath_rts_table_get(struct __vxge_hw_vpath_handle *vp,
3205 u32 action, u32 rts_table, u32 offset,
3206 u64 *data0, u64 *data1)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003207{
Jon Mason8424e002010-11-11 04:25:56 +00003208 enum vxge_hw_status status;
3209 u64 steer_ctrl = 0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003210
3211 if (vp == NULL) {
3212 status = VXGE_HW_ERR_INVALID_HANDLE;
3213 goto exit;
3214 }
3215
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003216 if ((rts_table ==
Jon Mason8424e002010-11-11 04:25:56 +00003217 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) ||
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003218 (rts_table ==
Jon Mason8424e002010-11-11 04:25:56 +00003219 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) ||
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003220 (rts_table ==
Jon Mason8424e002010-11-11 04:25:56 +00003221 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) ||
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003222 (rts_table ==
Jon Mason8424e002010-11-11 04:25:56 +00003223 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) {
3224 steer_ctrl = VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003225 }
3226
Jon Mason8424e002010-11-11 04:25:56 +00003227 status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
3228 data0, data1, &steer_ctrl);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003229 if (status != VXGE_HW_OK)
3230 goto exit;
3231
Jon Mason8424e002010-11-11 04:25:56 +00003232 if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) ||
3233 (rts_table !=
3234 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
3235 *data1 = 0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003236exit:
3237 return status;
3238}
3239
3240/*
3241 * __vxge_hw_vpath_rts_table_set - Set the entries of RTS access tables
3242 */
3243enum vxge_hw_status
Jon Mason8424e002010-11-11 04:25:56 +00003244__vxge_hw_vpath_rts_table_set(struct __vxge_hw_vpath_handle *vp, u32 action,
3245 u32 rts_table, u32 offset, u64 steer_data0,
3246 u64 steer_data1)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003247{
Jon Mason8424e002010-11-11 04:25:56 +00003248 u64 data0, data1 = 0, steer_ctrl = 0;
3249 enum vxge_hw_status status;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003250
3251 if (vp == NULL) {
3252 status = VXGE_HW_ERR_INVALID_HANDLE;
3253 goto exit;
3254 }
3255
Jon Mason8424e002010-11-11 04:25:56 +00003256 data0 = steer_data0;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003257
3258 if ((rts_table == VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) ||
3259 (rts_table ==
Jon Mason8424e002010-11-11 04:25:56 +00003260 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
3261 data1 = steer_data1;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003262
Jon Mason8424e002010-11-11 04:25:56 +00003263 status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
3264 &data0, &data1, &steer_ctrl);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003265exit:
3266 return status;
3267}
3268
3269/*
3270 * vxge_hw_vpath_rts_rth_set - Set/configure RTS hashing.
3271 */
3272enum vxge_hw_status vxge_hw_vpath_rts_rth_set(
3273 struct __vxge_hw_vpath_handle *vp,
3274 enum vxge_hw_rth_algoritms algorithm,
3275 struct vxge_hw_rth_hash_types *hash_type,
3276 u16 bucket_size)
3277{
3278 u64 data0, data1;
3279 enum vxge_hw_status status = VXGE_HW_OK;
3280
3281 if (vp == NULL) {
3282 status = VXGE_HW_ERR_INVALID_HANDLE;
3283 goto exit;
3284 }
3285
3286 status = __vxge_hw_vpath_rts_table_get(vp,
3287 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
3288 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
3289 0, &data0, &data1);
Jon Mason47f01db2010-11-11 04:25:53 +00003290 if (status != VXGE_HW_OK)
3291 goto exit;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003292
3293 data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) |
3294 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3));
3295
3296 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_EN |
3297 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(bucket_size) |
3298 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(algorithm);
3299
3300 if (hash_type->hash_type_tcpipv4_en)
3301 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV4_EN;
3302
3303 if (hash_type->hash_type_ipv4_en)
3304 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV4_EN;
3305
3306 if (hash_type->hash_type_tcpipv6_en)
3307 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EN;
3308
3309 if (hash_type->hash_type_ipv6_en)
3310 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EN;
3311
3312 if (hash_type->hash_type_tcpipv6ex_en)
3313 data0 |=
3314 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EX_EN;
3315
3316 if (hash_type->hash_type_ipv6ex_en)
3317 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EX_EN;
3318
3319 if (VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_ACTIVE_TABLE(data0))
3320 data0 &= ~VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ACTIVE_TABLE;
3321 else
3322 data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ACTIVE_TABLE;
3323
3324 status = __vxge_hw_vpath_rts_table_set(vp,
3325 VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY,
3326 VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
3327 0, data0, 0);
3328exit:
3329 return status;
3330}
3331
3332static void
3333vxge_hw_rts_rth_data0_data1_get(u32 j, u64 *data0, u64 *data1,
3334 u16 flag, u8 *itable)
3335{
3336 switch (flag) {
3337 case 1:
3338 *data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_NUM(j)|
3339 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_ENTRY_EN |
3340 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_DATA(
3341 itable[j]);
3342 case 2:
3343 *data0 |=
3344 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_NUM(j)|
3345 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_ENTRY_EN |
3346 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_DATA(
3347 itable[j]);
3348 case 3:
3349 *data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_NUM(j)|
3350 VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_ENTRY_EN |
3351 VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_DATA(
3352 itable[j]);
3353 case 4:
3354 *data1 |=
3355 VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_NUM(j)|
3356 VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_ENTRY_EN |
3357 VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_DATA(
3358 itable[j]);
3359 default:
3360 return;
3361 }
3362}
3363/*
3364 * vxge_hw_vpath_rts_rth_itable_set - Set/configure indirection table (IT).
3365 */
3366enum vxge_hw_status vxge_hw_vpath_rts_rth_itable_set(
3367 struct __vxge_hw_vpath_handle **vpath_handles,
3368 u32 vpath_count,
3369 u8 *mtable,
3370 u8 *itable,
3371 u32 itable_size)
3372{
3373 u32 i, j, action, rts_table;
3374 u64 data0;
3375 u64 data1;
3376 u32 max_entries;
3377 enum vxge_hw_status status = VXGE_HW_OK;
3378 struct __vxge_hw_vpath_handle *vp = vpath_handles[0];
3379
3380 if (vp == NULL) {
3381 status = VXGE_HW_ERR_INVALID_HANDLE;
3382 goto exit;
3383 }
3384
3385 max_entries = (((u32)1) << itable_size);
3386
3387 if (vp->vpath->hldev->config.rth_it_type
3388 == VXGE_HW_RTH_IT_TYPE_SOLO_IT) {
3389 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY;
3390 rts_table =
3391 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT;
3392
3393 for (j = 0; j < max_entries; j++) {
3394
3395 data1 = 0;
3396
3397 data0 =
3398 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_BUCKET_DATA(
3399 itable[j]);
3400
3401 status = __vxge_hw_vpath_rts_table_set(vpath_handles[0],
3402 action, rts_table, j, data0, data1);
3403
3404 if (status != VXGE_HW_OK)
3405 goto exit;
3406 }
3407
3408 for (j = 0; j < max_entries; j++) {
3409
3410 data1 = 0;
3411
3412 data0 =
3413 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_ENTRY_EN |
3414 VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_BUCKET_DATA(
3415 itable[j]);
3416
3417 status = __vxge_hw_vpath_rts_table_set(
3418 vpath_handles[mtable[itable[j]]], action,
3419 rts_table, j, data0, data1);
3420
3421 if (status != VXGE_HW_OK)
3422 goto exit;
3423 }
3424 } else {
3425 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY;
3426 rts_table =
3427 VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT;
3428 for (i = 0; i < vpath_count; i++) {
3429
3430 for (j = 0; j < max_entries;) {
3431
3432 data0 = 0;
3433 data1 = 0;
3434
3435 while (j < max_entries) {
3436 if (mtable[itable[j]] != i) {
3437 j++;
3438 continue;
3439 }
3440 vxge_hw_rts_rth_data0_data1_get(j,
3441 &data0, &data1, 1, itable);
3442 j++;
3443 break;
3444 }
3445
3446 while (j < max_entries) {
3447 if (mtable[itable[j]] != i) {
3448 j++;
3449 continue;
3450 }
3451 vxge_hw_rts_rth_data0_data1_get(j,
3452 &data0, &data1, 2, itable);
3453 j++;
3454 break;
3455 }
3456
3457 while (j < max_entries) {
3458 if (mtable[itable[j]] != i) {
3459 j++;
3460 continue;
3461 }
3462 vxge_hw_rts_rth_data0_data1_get(j,
3463 &data0, &data1, 3, itable);
3464 j++;
3465 break;
3466 }
3467
3468 while (j < max_entries) {
3469 if (mtable[itable[j]] != i) {
3470 j++;
3471 continue;
3472 }
3473 vxge_hw_rts_rth_data0_data1_get(j,
3474 &data0, &data1, 4, itable);
3475 j++;
3476 break;
3477 }
3478
3479 if (data0 != 0) {
3480 status = __vxge_hw_vpath_rts_table_set(
3481 vpath_handles[i],
3482 action, rts_table,
3483 0, data0, data1);
3484
3485 if (status != VXGE_HW_OK)
3486 goto exit;
3487 }
3488 }
3489 }
3490 }
3491exit:
3492 return status;
3493}
3494
3495/**
3496 * vxge_hw_vpath_check_leak - Check for memory leak
3497 * @ringh: Handle to the ring object used for receive
3498 *
3499 * If PRC_RXD_DOORBELL_VPn.NEW_QW_CNT is larger or equal to
3500 * PRC_CFG6_VPn.RXD_SPAT then a leak has occurred.
3501 * Returns: VXGE_HW_FAIL, if leak has occurred.
3502 *
3503 */
3504enum vxge_hw_status
3505vxge_hw_vpath_check_leak(struct __vxge_hw_ring *ring)
3506{
3507 enum vxge_hw_status status = VXGE_HW_OK;
3508 u64 rxd_new_count, rxd_spat;
3509
3510 if (ring == NULL)
3511 return status;
3512
3513 rxd_new_count = readl(&ring->vp_reg->prc_rxd_doorbell);
3514 rxd_spat = readq(&ring->vp_reg->prc_cfg6);
3515 rxd_spat = VXGE_HW_PRC_CFG6_RXD_SPAT(rxd_spat);
3516
3517 if (rxd_new_count >= rxd_spat)
3518 status = VXGE_HW_FAIL;
3519
3520 return status;
3521}
3522
3523/*
3524 * __vxge_hw_vpath_mgmt_read
3525 * This routine reads the vpath_mgmt registers
3526 */
3527static enum vxge_hw_status
3528__vxge_hw_vpath_mgmt_read(
3529 struct __vxge_hw_device *hldev,
3530 struct __vxge_hw_virtualpath *vpath)
3531{
3532 u32 i, mtu = 0, max_pyld = 0;
3533 u64 val64;
3534 enum vxge_hw_status status = VXGE_HW_OK;
3535
3536 for (i = 0; i < VXGE_HW_MAC_MAX_MAC_PORT_ID; i++) {
3537
3538 val64 = readq(&vpath->vpmgmt_reg->
3539 rxmac_cfg0_port_vpmgmt_clone[i]);
3540 max_pyld =
3541 (u32)
3542 VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_GET_MAX_PYLD_LEN
3543 (val64);
3544 if (mtu < max_pyld)
3545 mtu = max_pyld;
3546 }
3547
3548 vpath->max_mtu = mtu + VXGE_HW_MAC_HEADER_MAX_SIZE;
3549
3550 val64 = readq(&vpath->vpmgmt_reg->xmac_vsport_choices_vp);
3551
3552 for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
3553 if (val64 & vxge_mBIT(i))
3554 vpath->vsport_number = i;
3555 }
3556
3557 val64 = readq(&vpath->vpmgmt_reg->xgmac_gen_status_vpmgmt_clone);
3558
3559 if (val64 & VXGE_HW_XGMAC_GEN_STATUS_VPMGMT_CLONE_XMACJ_NTWK_OK)
3560 VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_UP);
3561 else
3562 VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_DOWN);
3563
3564 return status;
3565}
3566
3567/*
3568 * __vxge_hw_vpath_reset_check - Check if resetting the vpath completed
3569 * This routine checks the vpath_rst_in_prog register to see if
3570 * adapter completed the reset process for the vpath
3571 */
stephen hemminger42821a52010-10-21 07:50:53 +00003572static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003573__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath)
3574{
3575 enum vxge_hw_status status;
3576
3577 status = __vxge_hw_device_register_poll(
3578 &vpath->hldev->common_reg->vpath_rst_in_prog,
3579 VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(
3580 1 << (16 - vpath->vp_id)),
3581 vpath->hldev->config.device_poll_millis);
3582
3583 return status;
3584}
3585
3586/*
3587 * __vxge_hw_vpath_reset
3588 * This routine resets the vpath on the device
3589 */
stephen hemminger42821a52010-10-21 07:50:53 +00003590static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003591__vxge_hw_vpath_reset(struct __vxge_hw_device *hldev, u32 vp_id)
3592{
3593 u64 val64;
3594 enum vxge_hw_status status = VXGE_HW_OK;
3595
3596 val64 = VXGE_HW_CMN_RSTHDLR_CFG0_SW_RESET_VPATH(1 << (16 - vp_id));
3597
3598 __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
3599 &hldev->common_reg->cmn_rsthdlr_cfg0);
3600
3601 return status;
3602}
3603
3604/*
3605 * __vxge_hw_vpath_sw_reset
3606 * This routine resets the vpath structures
3607 */
stephen hemminger42821a52010-10-21 07:50:53 +00003608static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003609__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *hldev, u32 vp_id)
3610{
3611 enum vxge_hw_status status = VXGE_HW_OK;
3612 struct __vxge_hw_virtualpath *vpath;
3613
3614 vpath = (struct __vxge_hw_virtualpath *)&hldev->virtual_paths[vp_id];
3615
3616 if (vpath->ringh) {
3617 status = __vxge_hw_ring_reset(vpath->ringh);
3618 if (status != VXGE_HW_OK)
3619 goto exit;
3620 }
3621
3622 if (vpath->fifoh)
3623 status = __vxge_hw_fifo_reset(vpath->fifoh);
3624exit:
3625 return status;
3626}
3627
3628/*
3629 * __vxge_hw_vpath_prc_configure
3630 * This routine configures the prc registers of virtual path using the config
3631 * passed
3632 */
stephen hemminger42821a52010-10-21 07:50:53 +00003633static void
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003634__vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev, u32 vp_id)
3635{
3636 u64 val64;
3637 struct __vxge_hw_virtualpath *vpath;
3638 struct vxge_hw_vp_config *vp_config;
3639 struct vxge_hw_vpath_reg __iomem *vp_reg;
3640
3641 vpath = &hldev->virtual_paths[vp_id];
3642 vp_reg = vpath->vp_reg;
3643 vp_config = vpath->vp_config;
3644
3645 if (vp_config->ring.enable == VXGE_HW_RING_DISABLE)
3646 return;
3647
3648 val64 = readq(&vp_reg->prc_cfg1);
3649 val64 |= VXGE_HW_PRC_CFG1_RTI_TINT_DISABLE;
3650 writeq(val64, &vp_reg->prc_cfg1);
3651
3652 val64 = readq(&vpath->vp_reg->prc_cfg6);
3653 val64 |= VXGE_HW_PRC_CFG6_DOORBELL_MODE_EN;
3654 writeq(val64, &vpath->vp_reg->prc_cfg6);
3655
3656 val64 = readq(&vp_reg->prc_cfg7);
3657
3658 if (vpath->vp_config->ring.scatter_mode !=
3659 VXGE_HW_RING_SCATTER_MODE_USE_FLASH_DEFAULT) {
3660
3661 val64 &= ~VXGE_HW_PRC_CFG7_SCATTER_MODE(0x3);
3662
3663 switch (vpath->vp_config->ring.scatter_mode) {
3664 case VXGE_HW_RING_SCATTER_MODE_A:
3665 val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
3666 VXGE_HW_PRC_CFG7_SCATTER_MODE_A);
3667 break;
3668 case VXGE_HW_RING_SCATTER_MODE_B:
3669 val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
3670 VXGE_HW_PRC_CFG7_SCATTER_MODE_B);
3671 break;
3672 case VXGE_HW_RING_SCATTER_MODE_C:
3673 val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
3674 VXGE_HW_PRC_CFG7_SCATTER_MODE_C);
3675 break;
3676 }
3677 }
3678
3679 writeq(val64, &vp_reg->prc_cfg7);
3680
3681 writeq(VXGE_HW_PRC_CFG5_RXD0_ADD(
3682 __vxge_hw_ring_first_block_address_get(
3683 vpath->ringh) >> 3), &vp_reg->prc_cfg5);
3684
3685 val64 = readq(&vp_reg->prc_cfg4);
3686 val64 |= VXGE_HW_PRC_CFG4_IN_SVC;
3687 val64 &= ~VXGE_HW_PRC_CFG4_RING_MODE(0x3);
3688
3689 val64 |= VXGE_HW_PRC_CFG4_RING_MODE(
3690 VXGE_HW_PRC_CFG4_RING_MODE_ONE_BUFFER);
3691
3692 if (hldev->config.rth_en == VXGE_HW_RTH_DISABLE)
3693 val64 |= VXGE_HW_PRC_CFG4_RTH_DISABLE;
3694 else
3695 val64 &= ~VXGE_HW_PRC_CFG4_RTH_DISABLE;
3696
3697 writeq(val64, &vp_reg->prc_cfg4);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003698}
3699
3700/*
3701 * __vxge_hw_vpath_kdfc_configure
3702 * This routine configures the kdfc registers of virtual path using the
3703 * config passed
3704 */
stephen hemminger42821a52010-10-21 07:50:53 +00003705static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003706__vxge_hw_vpath_kdfc_configure(struct __vxge_hw_device *hldev, u32 vp_id)
3707{
3708 u64 val64;
3709 u64 vpath_stride;
3710 enum vxge_hw_status status = VXGE_HW_OK;
3711 struct __vxge_hw_virtualpath *vpath;
3712 struct vxge_hw_vpath_reg __iomem *vp_reg;
3713
3714 vpath = &hldev->virtual_paths[vp_id];
3715 vp_reg = vpath->vp_reg;
3716 status = __vxge_hw_kdfc_swapper_set(hldev->legacy_reg, vp_reg);
3717
3718 if (status != VXGE_HW_OK)
3719 goto exit;
3720
3721 val64 = readq(&vp_reg->kdfc_drbl_triplet_total);
3722
3723 vpath->max_kdfc_db =
3724 (u32)VXGE_HW_KDFC_DRBL_TRIPLET_TOTAL_GET_KDFC_MAX_SIZE(
3725 val64+1)/2;
3726
3727 if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
3728
3729 vpath->max_nofl_db = vpath->max_kdfc_db;
3730
3731 if (vpath->max_nofl_db <
3732 ((vpath->vp_config->fifo.memblock_size /
3733 (vpath->vp_config->fifo.max_frags *
3734 sizeof(struct vxge_hw_fifo_txd))) *
3735 vpath->vp_config->fifo.fifo_blocks)) {
3736
3737 return VXGE_HW_BADCFG_FIFO_BLOCKS;
3738 }
3739 val64 = VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_0(
3740 (vpath->max_nofl_db*2)-1);
3741 }
3742
3743 writeq(val64, &vp_reg->kdfc_fifo_trpl_partition);
3744
3745 writeq(VXGE_HW_KDFC_FIFO_TRPL_CTRL_TRIPLET_ENABLE,
3746 &vp_reg->kdfc_fifo_trpl_ctrl);
3747
3748 val64 = readq(&vp_reg->kdfc_trpl_fifo_0_ctrl);
3749
3750 val64 &= ~(VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(0x3) |
3751 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0xFF));
3752
3753 val64 |= VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(
3754 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_NON_OFFLOAD_ONLY) |
3755#ifndef __BIG_ENDIAN
3756 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SWAP_EN |
3757#endif
3758 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0);
3759
3760 writeq(val64, &vp_reg->kdfc_trpl_fifo_0_ctrl);
3761 writeq((u64)0, &vp_reg->kdfc_trpl_fifo_0_wb_address);
3762 wmb();
3763 vpath_stride = readq(&hldev->toc_reg->toc_kdfc_vpath_stride);
3764
3765 vpath->nofl_db =
3766 (struct __vxge_hw_non_offload_db_wrapper __iomem *)
3767 (hldev->kdfc + (vp_id *
3768 VXGE_HW_TOC_KDFC_VPATH_STRIDE_GET_TOC_KDFC_VPATH_STRIDE(
3769 vpath_stride)));
3770exit:
3771 return status;
3772}
3773
3774/*
3775 * __vxge_hw_vpath_mac_configure
3776 * This routine configures the mac of virtual path using the config passed
3777 */
stephen hemminger42821a52010-10-21 07:50:53 +00003778static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003779__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *hldev, u32 vp_id)
3780{
3781 u64 val64;
3782 enum vxge_hw_status status = VXGE_HW_OK;
3783 struct __vxge_hw_virtualpath *vpath;
3784 struct vxge_hw_vp_config *vp_config;
3785 struct vxge_hw_vpath_reg __iomem *vp_reg;
3786
3787 vpath = &hldev->virtual_paths[vp_id];
3788 vp_reg = vpath->vp_reg;
3789 vp_config = vpath->vp_config;
3790
3791 writeq(VXGE_HW_XMAC_VSPORT_CHOICE_VSPORT_NUMBER(
3792 vpath->vsport_number), &vp_reg->xmac_vsport_choice);
3793
3794 if (vp_config->ring.enable == VXGE_HW_RING_ENABLE) {
3795
3796 val64 = readq(&vp_reg->xmac_rpa_vcfg);
3797
3798 if (vp_config->rpa_strip_vlan_tag !=
3799 VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) {
3800 if (vp_config->rpa_strip_vlan_tag)
3801 val64 |= VXGE_HW_XMAC_RPA_VCFG_STRIP_VLAN_TAG;
3802 else
3803 val64 &= ~VXGE_HW_XMAC_RPA_VCFG_STRIP_VLAN_TAG;
3804 }
3805
3806 writeq(val64, &vp_reg->xmac_rpa_vcfg);
3807 val64 = readq(&vp_reg->rxmac_vcfg0);
3808
3809 if (vp_config->mtu !=
3810 VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) {
3811 val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
3812 if ((vp_config->mtu +
3813 VXGE_HW_MAC_HEADER_MAX_SIZE) < vpath->max_mtu)
3814 val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(
3815 vp_config->mtu +
3816 VXGE_HW_MAC_HEADER_MAX_SIZE);
3817 else
3818 val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(
3819 vpath->max_mtu);
3820 }
3821
3822 writeq(val64, &vp_reg->rxmac_vcfg0);
3823
3824 val64 = readq(&vp_reg->rxmac_vcfg1);
3825
3826 val64 &= ~(VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(0x3) |
3827 VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE);
3828
3829 if (hldev->config.rth_it_type ==
3830 VXGE_HW_RTH_IT_TYPE_MULTI_IT) {
3831 val64 |= VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(
3832 0x2) |
3833 VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE;
3834 }
3835
3836 writeq(val64, &vp_reg->rxmac_vcfg1);
3837 }
3838 return status;
3839}
3840
3841/*
3842 * __vxge_hw_vpath_tim_configure
3843 * This routine configures the tim registers of virtual path using the config
3844 * passed
3845 */
stephen hemminger42821a52010-10-21 07:50:53 +00003846static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00003847__vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
3848{
3849 u64 val64;
3850 enum vxge_hw_status status = VXGE_HW_OK;
3851 struct __vxge_hw_virtualpath *vpath;
3852 struct vxge_hw_vpath_reg __iomem *vp_reg;
3853 struct vxge_hw_vp_config *config;
3854
3855 vpath = &hldev->virtual_paths[vp_id];
3856 vp_reg = vpath->vp_reg;
3857 config = vpath->vp_config;
3858
3859 writeq((u64)0, &vp_reg->tim_dest_addr);
3860 writeq((u64)0, &vp_reg->tim_vpath_map);
3861 writeq((u64)0, &vp_reg->tim_bitmap);
3862 writeq((u64)0, &vp_reg->tim_remap);
3863
3864 if (config->ring.enable == VXGE_HW_RING_ENABLE)
3865 writeq(VXGE_HW_TIM_RING_ASSN_INT_NUM(
3866 (vp_id * VXGE_HW_MAX_INTR_PER_VP) +
3867 VXGE_HW_VPATH_INTR_RX), &vp_reg->tim_ring_assn);
3868
3869 val64 = readq(&vp_reg->tim_pci_cfg);
3870 val64 |= VXGE_HW_TIM_PCI_CFG_ADD_PAD;
3871 writeq(val64, &vp_reg->tim_pci_cfg);
3872
3873 if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
3874
3875 val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
3876
3877 if (config->tti.btimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
3878 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
3879 0x3ffffff);
3880 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
3881 config->tti.btimer_val);
3882 }
3883
3884 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BITMP_EN;
3885
3886 if (config->tti.timer_ac_en != VXGE_HW_USE_FLASH_DEFAULT) {
3887 if (config->tti.timer_ac_en)
3888 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
3889 else
3890 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
3891 }
3892
3893 if (config->tti.timer_ci_en != VXGE_HW_USE_FLASH_DEFAULT) {
3894 if (config->tti.timer_ci_en)
3895 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
3896 else
3897 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
3898 }
3899
3900 if (config->tti.urange_a != VXGE_HW_USE_FLASH_DEFAULT) {
3901 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(0x3f);
3902 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(
3903 config->tti.urange_a);
3904 }
3905
3906 if (config->tti.urange_b != VXGE_HW_USE_FLASH_DEFAULT) {
3907 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(0x3f);
3908 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(
3909 config->tti.urange_b);
3910 }
3911
3912 if (config->tti.urange_c != VXGE_HW_USE_FLASH_DEFAULT) {
3913 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(0x3f);
3914 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(
3915 config->tti.urange_c);
3916 }
3917
3918 writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
3919 val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
3920
3921 if (config->tti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
3922 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(0xffff);
3923 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(
3924 config->tti.uec_a);
3925 }
3926
3927 if (config->tti.uec_b != VXGE_HW_USE_FLASH_DEFAULT) {
3928 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(0xffff);
3929 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(
3930 config->tti.uec_b);
3931 }
3932
3933 if (config->tti.uec_c != VXGE_HW_USE_FLASH_DEFAULT) {
3934 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(0xffff);
3935 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(
3936 config->tti.uec_c);
3937 }
3938
3939 if (config->tti.uec_d != VXGE_HW_USE_FLASH_DEFAULT) {
3940 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(0xffff);
3941 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(
3942 config->tti.uec_d);
3943 }
3944
3945 writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
3946 val64 = readq(&vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
3947
3948 if (config->tti.timer_ri_en != VXGE_HW_USE_FLASH_DEFAULT) {
3949 if (config->tti.timer_ri_en)
3950 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
3951 else
3952 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
3953 }
3954
3955 if (config->tti.rtimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
3956 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
3957 0x3ffffff);
3958 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
3959 config->tti.rtimer_val);
3960 }
3961
3962 if (config->tti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
3963 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
3964 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
3965 config->tti.util_sel);
3966 }
3967
3968 if (config->tti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
3969 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
3970 0x3ffffff);
3971 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
3972 config->tti.ltimer_val);
3973 }
3974
3975 writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
3976 }
3977
3978 if (config->ring.enable == VXGE_HW_RING_ENABLE) {
3979
3980 val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
3981
3982 if (config->rti.btimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
3983 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
3984 0x3ffffff);
3985 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
3986 config->rti.btimer_val);
3987 }
3988
3989 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BITMP_EN;
3990
3991 if (config->rti.timer_ac_en != VXGE_HW_USE_FLASH_DEFAULT) {
3992 if (config->rti.timer_ac_en)
3993 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
3994 else
3995 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
3996 }
3997
3998 if (config->rti.timer_ci_en != VXGE_HW_USE_FLASH_DEFAULT) {
3999 if (config->rti.timer_ci_en)
4000 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
4001 else
4002 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
4003 }
4004
4005 if (config->rti.urange_a != VXGE_HW_USE_FLASH_DEFAULT) {
4006 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(0x3f);
4007 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(
4008 config->rti.urange_a);
4009 }
4010
4011 if (config->rti.urange_b != VXGE_HW_USE_FLASH_DEFAULT) {
4012 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(0x3f);
4013 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(
4014 config->rti.urange_b);
4015 }
4016
4017 if (config->rti.urange_c != VXGE_HW_USE_FLASH_DEFAULT) {
4018 val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(0x3f);
4019 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(
4020 config->rti.urange_c);
4021 }
4022
4023 writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
4024 val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
4025
4026 if (config->rti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
4027 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(0xffff);
4028 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(
4029 config->rti.uec_a);
4030 }
4031
4032 if (config->rti.uec_b != VXGE_HW_USE_FLASH_DEFAULT) {
4033 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(0xffff);
4034 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(
4035 config->rti.uec_b);
4036 }
4037
4038 if (config->rti.uec_c != VXGE_HW_USE_FLASH_DEFAULT) {
4039 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(0xffff);
4040 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(
4041 config->rti.uec_c);
4042 }
4043
4044 if (config->rti.uec_d != VXGE_HW_USE_FLASH_DEFAULT) {
4045 val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(0xffff);
4046 val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(
4047 config->rti.uec_d);
4048 }
4049
4050 writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
4051 val64 = readq(&vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
4052
4053 if (config->rti.timer_ri_en != VXGE_HW_USE_FLASH_DEFAULT) {
4054 if (config->rti.timer_ri_en)
4055 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
4056 else
4057 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
4058 }
4059
4060 if (config->rti.rtimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
4061 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
4062 0x3ffffff);
4063 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
4064 config->rti.rtimer_val);
4065 }
4066
4067 if (config->rti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
4068 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
4069 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(
4070 config->rti.util_sel);
4071 }
4072
4073 if (config->rti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
4074 val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
4075 0x3ffffff);
4076 val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
4077 config->rti.ltimer_val);
4078 }
4079
4080 writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
4081 }
4082
4083 val64 = 0;
4084 writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_EINTA]);
4085 writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_EINTA]);
4086 writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_EINTA]);
4087 writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_BMAP]);
4088 writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_BMAP]);
4089 writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_BMAP]);
4090
4091 return status;
4092}
4093
Sreenivasa Honnureb5f10c2009-10-05 01:57:29 +00004094void
4095vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
4096{
4097 struct __vxge_hw_virtualpath *vpath;
4098 struct vxge_hw_vpath_reg __iomem *vp_reg;
4099 struct vxge_hw_vp_config *config;
4100 u64 val64;
4101
4102 vpath = &hldev->virtual_paths[vp_id];
4103 vp_reg = vpath->vp_reg;
4104 config = vpath->vp_config;
4105
4106 if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
4107 val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
4108
4109 if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
4110 config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
4111 val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
4112 writeq(val64,
4113 &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
4114 }
4115 }
Sreenivasa Honnureb5f10c2009-10-05 01:57:29 +00004116}
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004117/*
4118 * __vxge_hw_vpath_initialize
4119 * This routine is the final phase of init which initializes the
4120 * registers of the vpath using the configuration passed.
4121 */
stephen hemminger42821a52010-10-21 07:50:53 +00004122static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004123__vxge_hw_vpath_initialize(struct __vxge_hw_device *hldev, u32 vp_id)
4124{
4125 u64 val64;
4126 u32 val32;
4127 enum vxge_hw_status status = VXGE_HW_OK;
4128 struct __vxge_hw_virtualpath *vpath;
4129 struct vxge_hw_vpath_reg __iomem *vp_reg;
4130
4131 vpath = &hldev->virtual_paths[vp_id];
4132
4133 if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
4134 status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
4135 goto exit;
4136 }
4137 vp_reg = vpath->vp_reg;
4138
4139 status = __vxge_hw_vpath_swapper_set(vpath->vp_reg);
4140
4141 if (status != VXGE_HW_OK)
4142 goto exit;
4143
4144 status = __vxge_hw_vpath_mac_configure(hldev, vp_id);
4145
4146 if (status != VXGE_HW_OK)
4147 goto exit;
4148
4149 status = __vxge_hw_vpath_kdfc_configure(hldev, vp_id);
4150
4151 if (status != VXGE_HW_OK)
4152 goto exit;
4153
4154 status = __vxge_hw_vpath_tim_configure(hldev, vp_id);
4155
4156 if (status != VXGE_HW_OK)
4157 goto exit;
4158
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004159 val64 = readq(&vp_reg->rtdma_rd_optimization_ctrl);
4160
4161 /* Get MRRS value from device control */
4162 status = __vxge_hw_vpath_pci_read(vpath, 1, 0x78, &val32);
4163
4164 if (status == VXGE_HW_OK) {
4165 val32 = (val32 & VXGE_HW_PCI_EXP_DEVCTL_READRQ) >> 12;
4166 val64 &=
4167 ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(7));
4168 val64 |=
4169 VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(val32);
4170
4171 val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_WAIT_FOR_SPACE;
4172 }
4173
4174 val64 &= ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(7));
4175 val64 |=
4176 VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(
4177 VXGE_HW_MAX_PAYLOAD_SIZE_512);
4178
4179 val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY_EN;
4180 writeq(val64, &vp_reg->rtdma_rd_optimization_ctrl);
4181
4182exit:
4183 return status;
4184}
4185
4186/*
4187 * __vxge_hw_vp_initialize - Initialize Virtual Path structure
4188 * This routine is the initial phase of init which resets the vpath and
4189 * initializes the software support structures.
4190 */
stephen hemminger42821a52010-10-21 07:50:53 +00004191static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004192__vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id,
4193 struct vxge_hw_vp_config *config)
4194{
4195 struct __vxge_hw_virtualpath *vpath;
4196 enum vxge_hw_status status = VXGE_HW_OK;
4197
4198 if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
4199 status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
4200 goto exit;
4201 }
4202
4203 vpath = &hldev->virtual_paths[vp_id];
4204
Jon Mason8424e002010-11-11 04:25:56 +00004205 spin_lock_init(&hldev->virtual_paths[vp_id].lock);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004206 vpath->vp_id = vp_id;
4207 vpath->vp_open = VXGE_HW_VP_OPEN;
4208 vpath->hldev = hldev;
4209 vpath->vp_config = config;
4210 vpath->vp_reg = hldev->vpath_reg[vp_id];
4211 vpath->vpmgmt_reg = hldev->vpmgmt_reg[vp_id];
4212
4213 __vxge_hw_vpath_reset(hldev, vp_id);
4214
4215 status = __vxge_hw_vpath_reset_check(vpath);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004216 if (status != VXGE_HW_OK) {
4217 memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
4218 goto exit;
4219 }
4220
4221 status = __vxge_hw_vpath_mgmt_read(hldev, vpath);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004222 if (status != VXGE_HW_OK) {
4223 memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
4224 goto exit;
4225 }
4226
4227 INIT_LIST_HEAD(&vpath->vpath_handles);
4228
4229 vpath->sw_stats = &hldev->stats.sw_dev_info_stats.vpath_info[vp_id];
4230
4231 VXGE_HW_DEVICE_TIM_INT_MASK_SET(hldev->tim_int_mask0,
4232 hldev->tim_int_mask1, vp_id);
4233
4234 status = __vxge_hw_vpath_initialize(hldev, vp_id);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004235 if (status != VXGE_HW_OK)
4236 __vxge_hw_vp_terminate(hldev, vp_id);
4237exit:
4238 return status;
4239}
4240
4241/*
4242 * __vxge_hw_vp_terminate - Terminate Virtual Path structure
4243 * This routine closes all channels it opened and freeup memory
4244 */
stephen hemminger42821a52010-10-21 07:50:53 +00004245static void
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004246__vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id)
4247{
4248 struct __vxge_hw_virtualpath *vpath;
4249
4250 vpath = &hldev->virtual_paths[vp_id];
4251
4252 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN)
4253 goto exit;
4254
4255 VXGE_HW_DEVICE_TIM_INT_MASK_RESET(vpath->hldev->tim_int_mask0,
4256 vpath->hldev->tim_int_mask1, vpath->vp_id);
4257 hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL;
4258
4259 memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
4260exit:
4261 return;
4262}
4263
4264/*
4265 * vxge_hw_vpath_mtu_set - Set MTU.
4266 * Set new MTU value. Example, to use jumbo frames:
4267 * vxge_hw_vpath_mtu_set(my_device, 9600);
4268 */
4269enum vxge_hw_status
4270vxge_hw_vpath_mtu_set(struct __vxge_hw_vpath_handle *vp, u32 new_mtu)
4271{
4272 u64 val64;
4273 enum vxge_hw_status status = VXGE_HW_OK;
4274 struct __vxge_hw_virtualpath *vpath;
4275
4276 if (vp == NULL) {
4277 status = VXGE_HW_ERR_INVALID_HANDLE;
4278 goto exit;
4279 }
4280 vpath = vp->vpath;
4281
4282 new_mtu += VXGE_HW_MAC_HEADER_MAX_SIZE;
4283
4284 if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > vpath->max_mtu))
4285 status = VXGE_HW_ERR_INVALID_MTU_SIZE;
4286
4287 val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
4288
4289 val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
4290 val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(new_mtu);
4291
4292 writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
4293
4294 vpath->vp_config->mtu = new_mtu - VXGE_HW_MAC_HEADER_MAX_SIZE;
4295
4296exit:
4297 return status;
4298}
4299
4300/*
4301 * vxge_hw_vpath_open - Open a virtual path on a given adapter
4302 * This function is used to open access to virtual path of an
4303 * adapter for offload, GRO operations. This function returns
4304 * synchronously.
4305 */
4306enum vxge_hw_status
4307vxge_hw_vpath_open(struct __vxge_hw_device *hldev,
4308 struct vxge_hw_vpath_attr *attr,
4309 struct __vxge_hw_vpath_handle **vpath_handle)
4310{
4311 struct __vxge_hw_virtualpath *vpath;
4312 struct __vxge_hw_vpath_handle *vp;
4313 enum vxge_hw_status status;
4314
4315 vpath = &hldev->virtual_paths[attr->vp_id];
4316
4317 if (vpath->vp_open == VXGE_HW_VP_OPEN) {
4318 status = VXGE_HW_ERR_INVALID_STATE;
4319 goto vpath_open_exit1;
4320 }
4321
4322 status = __vxge_hw_vp_initialize(hldev, attr->vp_id,
4323 &hldev->config.vp_config[attr->vp_id]);
4324
4325 if (status != VXGE_HW_OK)
4326 goto vpath_open_exit1;
4327
4328 vp = (struct __vxge_hw_vpath_handle *)
4329 vmalloc(sizeof(struct __vxge_hw_vpath_handle));
4330 if (vp == NULL) {
4331 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4332 goto vpath_open_exit2;
4333 }
4334
4335 memset(vp, 0, sizeof(struct __vxge_hw_vpath_handle));
4336
4337 vp->vpath = vpath;
4338
4339 if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
4340 status = __vxge_hw_fifo_create(vp, &attr->fifo_attr);
4341 if (status != VXGE_HW_OK)
4342 goto vpath_open_exit6;
4343 }
4344
4345 if (vpath->vp_config->ring.enable == VXGE_HW_RING_ENABLE) {
4346 status = __vxge_hw_ring_create(vp, &attr->ring_attr);
4347 if (status != VXGE_HW_OK)
4348 goto vpath_open_exit7;
4349
4350 __vxge_hw_vpath_prc_configure(hldev, attr->vp_id);
4351 }
4352
4353 vpath->fifoh->tx_intr_num =
4354 (attr->vp_id * VXGE_HW_MAX_INTR_PER_VP) +
4355 VXGE_HW_VPATH_INTR_TX;
4356
4357 vpath->stats_block = __vxge_hw_blockpool_block_allocate(hldev,
4358 VXGE_HW_BLOCK_SIZE);
4359
4360 if (vpath->stats_block == NULL) {
4361 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4362 goto vpath_open_exit8;
4363 }
4364
4365 vpath->hw_stats = (struct vxge_hw_vpath_stats_hw_info *)vpath->
4366 stats_block->memblock;
4367 memset(vpath->hw_stats, 0,
4368 sizeof(struct vxge_hw_vpath_stats_hw_info));
4369
4370 hldev->stats.hw_dev_info_stats.vpath_info[attr->vp_id] =
4371 vpath->hw_stats;
4372
4373 vpath->hw_stats_sav =
4374 &hldev->stats.hw_dev_info_stats.vpath_info_sav[attr->vp_id];
4375 memset(vpath->hw_stats_sav, 0,
4376 sizeof(struct vxge_hw_vpath_stats_hw_info));
4377
4378 writeq(vpath->stats_block->dma_addr, &vpath->vp_reg->stats_cfg);
4379
4380 status = vxge_hw_vpath_stats_enable(vp);
4381 if (status != VXGE_HW_OK)
4382 goto vpath_open_exit8;
4383
4384 list_add(&vp->item, &vpath->vpath_handles);
4385
4386 hldev->vpaths_deployed |= vxge_mBIT(vpath->vp_id);
4387
4388 *vpath_handle = vp;
4389
4390 attr->fifo_attr.userdata = vpath->fifoh;
4391 attr->ring_attr.userdata = vpath->ringh;
4392
4393 return VXGE_HW_OK;
4394
4395vpath_open_exit8:
4396 if (vpath->ringh != NULL)
4397 __vxge_hw_ring_delete(vp);
4398vpath_open_exit7:
4399 if (vpath->fifoh != NULL)
4400 __vxge_hw_fifo_delete(vp);
4401vpath_open_exit6:
4402 vfree(vp);
4403vpath_open_exit2:
4404 __vxge_hw_vp_terminate(hldev, attr->vp_id);
4405vpath_open_exit1:
4406
4407 return status;
4408}
4409
4410/**
4411 * vxge_hw_vpath_rx_doorbell_post - Close the handle got from previous vpath
4412 * (vpath) open
4413 * @vp: Handle got from previous vpath open
4414 *
4415 * This function is used to close access to virtual path opened
4416 * earlier.
4417 */
4418void
4419vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp)
4420{
Jon Masone7935c92010-11-11 04:26:00 +00004421 struct __vxge_hw_virtualpath *vpath = vp->vpath;
4422 struct __vxge_hw_ring *ring = vpath->ringh;
4423 struct vxgedev *vdev = netdev_priv(vpath->hldev->ndev);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004424 u64 new_count, val64, val164;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004425
Jon Masone7935c92010-11-11 04:26:00 +00004426 if (vdev->titan1) {
4427 new_count = readq(&vpath->vp_reg->rxdmem_size);
4428 new_count &= 0x1fff;
4429 } else
4430 new_count = ring->config->ring_blocks * VXGE_HW_BLOCK_SIZE / 8;
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004431
Jon Masone7935c92010-11-11 04:26:00 +00004432 val164 = VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004433
4434 writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val164),
4435 &vpath->vp_reg->prc_rxd_doorbell);
4436 readl(&vpath->vp_reg->prc_rxd_doorbell);
4437
4438 val164 /= 2;
4439 val64 = readq(&vpath->vp_reg->prc_cfg6);
4440 val64 = VXGE_HW_PRC_CFG6_RXD_SPAT(val64);
4441 val64 &= 0x1ff;
4442
4443 /*
4444 * Each RxD is of 4 qwords
4445 */
4446 new_count -= (val64 + 1);
4447 val64 = min(val164, new_count) / 4;
4448
4449 ring->rxds_limit = min(ring->rxds_limit, val64);
4450 if (ring->rxds_limit < 4)
4451 ring->rxds_limit = 4;
4452}
4453
4454/*
4455 * vxge_hw_vpath_close - Close the handle got from previous vpath (vpath) open
4456 * This function is used to close access to virtual path opened
4457 * earlier.
4458 */
4459enum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_vpath_handle *vp)
4460{
4461 struct __vxge_hw_virtualpath *vpath = NULL;
4462 struct __vxge_hw_device *devh = NULL;
4463 u32 vp_id = vp->vpath->vp_id;
4464 u32 is_empty = TRUE;
4465 enum vxge_hw_status status = VXGE_HW_OK;
4466
4467 vpath = vp->vpath;
4468 devh = vpath->hldev;
4469
4470 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4471 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4472 goto vpath_close_exit;
4473 }
4474
4475 list_del(&vp->item);
4476
4477 if (!list_empty(&vpath->vpath_handles)) {
4478 list_add(&vp->item, &vpath->vpath_handles);
4479 is_empty = FALSE;
4480 }
4481
4482 if (!is_empty) {
4483 status = VXGE_HW_FAIL;
4484 goto vpath_close_exit;
4485 }
4486
4487 devh->vpaths_deployed &= ~vxge_mBIT(vp_id);
4488
4489 if (vpath->ringh != NULL)
4490 __vxge_hw_ring_delete(vp);
4491
4492 if (vpath->fifoh != NULL)
4493 __vxge_hw_fifo_delete(vp);
4494
4495 if (vpath->stats_block != NULL)
4496 __vxge_hw_blockpool_block_free(devh, vpath->stats_block);
4497
4498 vfree(vp);
4499
4500 __vxge_hw_vp_terminate(devh, vp_id);
4501
Jon Mason8424e002010-11-11 04:25:56 +00004502 spin_lock(&vpath->lock);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004503 vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
Jon Mason8424e002010-11-11 04:25:56 +00004504 spin_unlock(&vpath->lock);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004505
4506vpath_close_exit:
4507 return status;
4508}
4509
4510/*
4511 * vxge_hw_vpath_reset - Resets vpath
4512 * This function is used to request a reset of vpath
4513 */
4514enum vxge_hw_status vxge_hw_vpath_reset(struct __vxge_hw_vpath_handle *vp)
4515{
4516 enum vxge_hw_status status;
4517 u32 vp_id;
4518 struct __vxge_hw_virtualpath *vpath = vp->vpath;
4519
4520 vp_id = vpath->vp_id;
4521
4522 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4523 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4524 goto exit;
4525 }
4526
4527 status = __vxge_hw_vpath_reset(vpath->hldev, vp_id);
4528 if (status == VXGE_HW_OK)
4529 vpath->sw_stats->soft_reset_cnt++;
4530exit:
4531 return status;
4532}
4533
4534/*
4535 * vxge_hw_vpath_recover_from_reset - Poll for reset complete and re-initialize.
4536 * This function poll's for the vpath reset completion and re initializes
4537 * the vpath.
4538 */
4539enum vxge_hw_status
4540vxge_hw_vpath_recover_from_reset(struct __vxge_hw_vpath_handle *vp)
4541{
4542 struct __vxge_hw_virtualpath *vpath = NULL;
4543 enum vxge_hw_status status;
4544 struct __vxge_hw_device *hldev;
4545 u32 vp_id;
4546
4547 vp_id = vp->vpath->vp_id;
4548 vpath = vp->vpath;
4549 hldev = vpath->hldev;
4550
4551 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4552 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4553 goto exit;
4554 }
4555
4556 status = __vxge_hw_vpath_reset_check(vpath);
4557 if (status != VXGE_HW_OK)
4558 goto exit;
4559
4560 status = __vxge_hw_vpath_sw_reset(hldev, vp_id);
4561 if (status != VXGE_HW_OK)
4562 goto exit;
4563
4564 status = __vxge_hw_vpath_initialize(hldev, vp_id);
4565 if (status != VXGE_HW_OK)
4566 goto exit;
4567
4568 if (vpath->ringh != NULL)
4569 __vxge_hw_vpath_prc_configure(hldev, vp_id);
4570
4571 memset(vpath->hw_stats, 0,
4572 sizeof(struct vxge_hw_vpath_stats_hw_info));
4573
4574 memset(vpath->hw_stats_sav, 0,
4575 sizeof(struct vxge_hw_vpath_stats_hw_info));
4576
4577 writeq(vpath->stats_block->dma_addr,
4578 &vpath->vp_reg->stats_cfg);
4579
4580 status = vxge_hw_vpath_stats_enable(vp);
4581
4582exit:
4583 return status;
4584}
4585
4586/*
4587 * vxge_hw_vpath_enable - Enable vpath.
4588 * This routine clears the vpath reset thereby enabling a vpath
4589 * to start forwarding frames and generating interrupts.
4590 */
4591void
4592vxge_hw_vpath_enable(struct __vxge_hw_vpath_handle *vp)
4593{
4594 struct __vxge_hw_device *hldev;
4595 u64 val64;
4596
4597 hldev = vp->vpath->hldev;
4598
4599 val64 = VXGE_HW_CMN_RSTHDLR_CFG1_CLR_VPATH_RESET(
4600 1 << (16 - vp->vpath->vp_id));
4601
4602 __vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
4603 &hldev->common_reg->cmn_rsthdlr_cfg1);
4604}
4605
4606/*
4607 * vxge_hw_vpath_stats_enable - Enable vpath h/wstatistics.
4608 * Enable the DMA vpath statistics. The function is to be called to re-enable
4609 * the adapter to update stats into the host memory
4610 */
stephen hemminger42821a52010-10-21 07:50:53 +00004611static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004612vxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vp)
4613{
4614 enum vxge_hw_status status = VXGE_HW_OK;
4615 struct __vxge_hw_virtualpath *vpath;
4616
4617 vpath = vp->vpath;
4618
4619 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4620 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4621 goto exit;
4622 }
4623
4624 memcpy(vpath->hw_stats_sav, vpath->hw_stats,
4625 sizeof(struct vxge_hw_vpath_stats_hw_info));
4626
4627 status = __vxge_hw_vpath_stats_get(vpath, vpath->hw_stats);
4628exit:
4629 return status;
4630}
4631
4632/*
4633 * __vxge_hw_vpath_stats_access - Get the statistics from the given location
4634 * and offset and perform an operation
4635 */
stephen hemminger42821a52010-10-21 07:50:53 +00004636static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004637__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
4638 u32 operation, u32 offset, u64 *stat)
4639{
4640 u64 val64;
4641 enum vxge_hw_status status = VXGE_HW_OK;
4642 struct vxge_hw_vpath_reg __iomem *vp_reg;
4643
4644 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4645 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4646 goto vpath_stats_access_exit;
4647 }
4648
4649 vp_reg = vpath->vp_reg;
4650
4651 val64 = VXGE_HW_XMAC_STATS_ACCESS_CMD_OP(operation) |
4652 VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE |
4653 VXGE_HW_XMAC_STATS_ACCESS_CMD_OFFSET_SEL(offset);
4654
4655 status = __vxge_hw_pio_mem_write64(val64,
4656 &vp_reg->xmac_stats_access_cmd,
4657 VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE,
4658 vpath->hldev->config.device_poll_millis);
4659
4660 if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
4661 *stat = readq(&vp_reg->xmac_stats_access_data);
4662 else
4663 *stat = 0;
4664
4665vpath_stats_access_exit:
4666 return status;
4667}
4668
4669/*
4670 * __vxge_hw_vpath_xmac_tx_stats_get - Get the TX Statistics of a vpath
4671 */
stephen hemminger42821a52010-10-21 07:50:53 +00004672static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004673__vxge_hw_vpath_xmac_tx_stats_get(
4674 struct __vxge_hw_virtualpath *vpath,
4675 struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats)
4676{
4677 u64 *val64;
4678 int i;
4679 u32 offset = VXGE_HW_STATS_VPATH_TX_OFFSET;
4680 enum vxge_hw_status status = VXGE_HW_OK;
4681
4682 val64 = (u64 *) vpath_tx_stats;
4683
4684 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4685 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4686 goto exit;
4687 }
4688
4689 for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_tx_stats) / 8; i++) {
4690 status = __vxge_hw_vpath_stats_access(vpath,
4691 VXGE_HW_STATS_OP_READ,
4692 offset, val64);
4693 if (status != VXGE_HW_OK)
4694 goto exit;
4695 offset++;
4696 val64++;
4697 }
4698exit:
4699 return status;
4700}
4701
4702/*
4703 * __vxge_hw_vpath_xmac_rx_stats_get - Get the RX Statistics of a vpath
4704 */
stephen hemminger42821a52010-10-21 07:50:53 +00004705static enum vxge_hw_status
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004706__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
stephen hemminger42821a52010-10-21 07:50:53 +00004707 struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004708{
4709 u64 *val64;
4710 enum vxge_hw_status status = VXGE_HW_OK;
4711 int i;
4712 u32 offset = VXGE_HW_STATS_VPATH_RX_OFFSET;
4713 val64 = (u64 *) vpath_rx_stats;
4714
4715 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4716 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4717 goto exit;
4718 }
4719 for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_rx_stats) / 8; i++) {
4720 status = __vxge_hw_vpath_stats_access(vpath,
4721 VXGE_HW_STATS_OP_READ,
4722 offset >> 3, val64);
4723 if (status != VXGE_HW_OK)
4724 goto exit;
4725
4726 offset += 8;
4727 val64++;
4728 }
4729exit:
4730 return status;
4731}
4732
4733/*
4734 * __vxge_hw_vpath_stats_get - Get the vpath hw statistics.
4735 */
stephen hemminger42821a52010-10-21 07:50:53 +00004736static enum vxge_hw_status
4737__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
4738 struct vxge_hw_vpath_stats_hw_info *hw_stats)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004739{
4740 u64 val64;
4741 enum vxge_hw_status status = VXGE_HW_OK;
4742 struct vxge_hw_vpath_reg __iomem *vp_reg;
4743
4744 if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
4745 status = VXGE_HW_ERR_VPATH_NOT_OPEN;
4746 goto exit;
4747 }
4748 vp_reg = vpath->vp_reg;
4749
4750 val64 = readq(&vp_reg->vpath_debug_stats0);
4751 hw_stats->ini_num_mwr_sent =
4752 (u32)VXGE_HW_VPATH_DEBUG_STATS0_GET_INI_NUM_MWR_SENT(val64);
4753
4754 val64 = readq(&vp_reg->vpath_debug_stats1);
4755 hw_stats->ini_num_mrd_sent =
4756 (u32)VXGE_HW_VPATH_DEBUG_STATS1_GET_INI_NUM_MRD_SENT(val64);
4757
4758 val64 = readq(&vp_reg->vpath_debug_stats2);
4759 hw_stats->ini_num_cpl_rcvd =
4760 (u32)VXGE_HW_VPATH_DEBUG_STATS2_GET_INI_NUM_CPL_RCVD(val64);
4761
4762 val64 = readq(&vp_reg->vpath_debug_stats3);
4763 hw_stats->ini_num_mwr_byte_sent =
4764 VXGE_HW_VPATH_DEBUG_STATS3_GET_INI_NUM_MWR_BYTE_SENT(val64);
4765
4766 val64 = readq(&vp_reg->vpath_debug_stats4);
4767 hw_stats->ini_num_cpl_byte_rcvd =
4768 VXGE_HW_VPATH_DEBUG_STATS4_GET_INI_NUM_CPL_BYTE_RCVD(val64);
4769
4770 val64 = readq(&vp_reg->vpath_debug_stats5);
4771 hw_stats->wrcrdtarb_xoff =
4772 (u32)VXGE_HW_VPATH_DEBUG_STATS5_GET_WRCRDTARB_XOFF(val64);
4773
4774 val64 = readq(&vp_reg->vpath_debug_stats6);
4775 hw_stats->rdcrdtarb_xoff =
4776 (u32)VXGE_HW_VPATH_DEBUG_STATS6_GET_RDCRDTARB_XOFF(val64);
4777
4778 val64 = readq(&vp_reg->vpath_genstats_count01);
4779 hw_stats->vpath_genstats_count0 =
4780 (u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT0(
4781 val64);
4782
4783 val64 = readq(&vp_reg->vpath_genstats_count01);
4784 hw_stats->vpath_genstats_count1 =
4785 (u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT1(
4786 val64);
4787
4788 val64 = readq(&vp_reg->vpath_genstats_count23);
4789 hw_stats->vpath_genstats_count2 =
4790 (u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT2(
4791 val64);
4792
4793 val64 = readq(&vp_reg->vpath_genstats_count01);
4794 hw_stats->vpath_genstats_count3 =
4795 (u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT3(
4796 val64);
4797
4798 val64 = readq(&vp_reg->vpath_genstats_count4);
4799 hw_stats->vpath_genstats_count4 =
4800 (u32)VXGE_HW_VPATH_GENSTATS_COUNT4_GET_PPIF_VPATH_GENSTATS_COUNT4(
4801 val64);
4802
4803 val64 = readq(&vp_reg->vpath_genstats_count5);
4804 hw_stats->vpath_genstats_count5 =
4805 (u32)VXGE_HW_VPATH_GENSTATS_COUNT5_GET_PPIF_VPATH_GENSTATS_COUNT5(
4806 val64);
4807
4808 status = __vxge_hw_vpath_xmac_tx_stats_get(vpath, &hw_stats->tx_stats);
4809 if (status != VXGE_HW_OK)
4810 goto exit;
4811
4812 status = __vxge_hw_vpath_xmac_rx_stats_get(vpath, &hw_stats->rx_stats);
4813 if (status != VXGE_HW_OK)
4814 goto exit;
4815
4816 VXGE_HW_VPATH_STATS_PIO_READ(
4817 VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM0_OFFSET);
4818
4819 hw_stats->prog_event_vnum0 =
4820 (u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM0(val64);
4821
4822 hw_stats->prog_event_vnum1 =
4823 (u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM1(val64);
4824
4825 VXGE_HW_VPATH_STATS_PIO_READ(
4826 VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM2_OFFSET);
4827
4828 hw_stats->prog_event_vnum2 =
4829 (u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM2(val64);
4830
4831 hw_stats->prog_event_vnum3 =
4832 (u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM3(val64);
4833
4834 val64 = readq(&vp_reg->rx_multi_cast_stats);
4835 hw_stats->rx_multi_cast_frame_discard =
4836 (u16)VXGE_HW_RX_MULTI_CAST_STATS_GET_FRAME_DISCARD(val64);
4837
4838 val64 = readq(&vp_reg->rx_frm_transferred);
4839 hw_stats->rx_frm_transferred =
4840 (u32)VXGE_HW_RX_FRM_TRANSFERRED_GET_RX_FRM_TRANSFERRED(val64);
4841
4842 val64 = readq(&vp_reg->rxd_returned);
4843 hw_stats->rxd_returned =
4844 (u16)VXGE_HW_RXD_RETURNED_GET_RXD_RETURNED(val64);
4845
4846 val64 = readq(&vp_reg->dbg_stats_rx_mpa);
4847 hw_stats->rx_mpa_len_fail_frms =
4848 (u16)VXGE_HW_DBG_STATS_GET_RX_MPA_LEN_FAIL_FRMS(val64);
4849 hw_stats->rx_mpa_mrk_fail_frms =
4850 (u16)VXGE_HW_DBG_STATS_GET_RX_MPA_MRK_FAIL_FRMS(val64);
4851 hw_stats->rx_mpa_crc_fail_frms =
4852 (u16)VXGE_HW_DBG_STATS_GET_RX_MPA_CRC_FAIL_FRMS(val64);
4853
4854 val64 = readq(&vp_reg->dbg_stats_rx_fau);
4855 hw_stats->rx_permitted_frms =
4856 (u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_PERMITTED_FRMS(val64);
4857 hw_stats->rx_vp_reset_discarded_frms =
4858 (u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(val64);
4859 hw_stats->rx_wol_frms =
4860 (u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_WOL_FRMS(val64);
4861
4862 val64 = readq(&vp_reg->tx_vp_reset_discarded_frms);
4863 hw_stats->tx_vp_reset_discarded_frms =
4864 (u16)VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_GET_TX_VP_RESET_DISCARDED_FRMS(
4865 val64);
4866exit:
4867 return status;
4868}
4869
stephen hemminger42821a52010-10-21 07:50:53 +00004870
4871static void vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh,
4872 unsigned long size)
4873{
4874 gfp_t flags;
4875 void *vaddr;
4876
4877 if (in_interrupt())
4878 flags = GFP_ATOMIC | GFP_DMA;
4879 else
4880 flags = GFP_KERNEL | GFP_DMA;
4881
4882 vaddr = kmalloc((size), flags);
4883
4884 vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev);
4885}
4886
4887static void vxge_os_dma_free(struct pci_dev *pdev, const void *vaddr,
4888 struct pci_dev **p_dma_acch)
4889{
4890 unsigned long misaligned = *(unsigned long *)p_dma_acch;
4891 u8 *tmp = (u8 *)vaddr;
4892 tmp -= misaligned;
4893 kfree((void *)tmp);
4894}
4895
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00004896/*
4897 * __vxge_hw_blockpool_create - Create block pool
4898 */
4899
4900enum vxge_hw_status
4901__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
4902 struct __vxge_hw_blockpool *blockpool,
4903 u32 pool_size,
4904 u32 pool_max)
4905{
4906 u32 i;
4907 struct __vxge_hw_blockpool_entry *entry = NULL;
4908 void *memblock;
4909 dma_addr_t dma_addr;
4910 struct pci_dev *dma_handle;
4911 struct pci_dev *acc_handle;
4912 enum vxge_hw_status status = VXGE_HW_OK;
4913
4914 if (blockpool == NULL) {
4915 status = VXGE_HW_FAIL;
4916 goto blockpool_create_exit;
4917 }
4918
4919 blockpool->hldev = hldev;
4920 blockpool->block_size = VXGE_HW_BLOCK_SIZE;
4921 blockpool->pool_size = 0;
4922 blockpool->pool_max = pool_max;
4923 blockpool->req_out = 0;
4924
4925 INIT_LIST_HEAD(&blockpool->free_block_list);
4926 INIT_LIST_HEAD(&blockpool->free_entry_list);
4927
4928 for (i = 0; i < pool_size + pool_max; i++) {
4929 entry = kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
4930 GFP_KERNEL);
4931 if (entry == NULL) {
4932 __vxge_hw_blockpool_destroy(blockpool);
4933 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4934 goto blockpool_create_exit;
4935 }
4936 list_add(&entry->item, &blockpool->free_entry_list);
4937 }
4938
4939 for (i = 0; i < pool_size; i++) {
4940
4941 memblock = vxge_os_dma_malloc(
4942 hldev->pdev,
4943 VXGE_HW_BLOCK_SIZE,
4944 &dma_handle,
4945 &acc_handle);
4946
4947 if (memblock == NULL) {
4948 __vxge_hw_blockpool_destroy(blockpool);
4949 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4950 goto blockpool_create_exit;
4951 }
4952
4953 dma_addr = pci_map_single(hldev->pdev, memblock,
4954 VXGE_HW_BLOCK_SIZE, PCI_DMA_BIDIRECTIONAL);
4955
4956 if (unlikely(pci_dma_mapping_error(hldev->pdev,
4957 dma_addr))) {
4958
4959 vxge_os_dma_free(hldev->pdev, memblock, &acc_handle);
4960 __vxge_hw_blockpool_destroy(blockpool);
4961 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4962 goto blockpool_create_exit;
4963 }
4964
4965 if (!list_empty(&blockpool->free_entry_list))
4966 entry = (struct __vxge_hw_blockpool_entry *)
4967 list_first_entry(&blockpool->free_entry_list,
4968 struct __vxge_hw_blockpool_entry,
4969 item);
4970
4971 if (entry == NULL)
4972 entry =
4973 kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
4974 GFP_KERNEL);
4975 if (entry != NULL) {
4976 list_del(&entry->item);
4977 entry->length = VXGE_HW_BLOCK_SIZE;
4978 entry->memblock = memblock;
4979 entry->dma_addr = dma_addr;
4980 entry->acc_handle = acc_handle;
4981 entry->dma_handle = dma_handle;
4982 list_add(&entry->item,
4983 &blockpool->free_block_list);
4984 blockpool->pool_size++;
4985 } else {
4986 __vxge_hw_blockpool_destroy(blockpool);
4987 status = VXGE_HW_ERR_OUT_OF_MEMORY;
4988 goto blockpool_create_exit;
4989 }
4990 }
4991
4992blockpool_create_exit:
4993 return status;
4994}
4995
4996/*
4997 * __vxge_hw_blockpool_destroy - Deallocates the block pool
4998 */
4999
5000void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool)
5001{
5002
5003 struct __vxge_hw_device *hldev;
5004 struct list_head *p, *n;
5005 u16 ret;
5006
5007 if (blockpool == NULL) {
5008 ret = 1;
5009 goto exit;
5010 }
5011
5012 hldev = blockpool->hldev;
5013
5014 list_for_each_safe(p, n, &blockpool->free_block_list) {
5015
5016 pci_unmap_single(hldev->pdev,
5017 ((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
5018 ((struct __vxge_hw_blockpool_entry *)p)->length,
5019 PCI_DMA_BIDIRECTIONAL);
5020
5021 vxge_os_dma_free(hldev->pdev,
5022 ((struct __vxge_hw_blockpool_entry *)p)->memblock,
5023 &((struct __vxge_hw_blockpool_entry *) p)->acc_handle);
5024
5025 list_del(
5026 &((struct __vxge_hw_blockpool_entry *)p)->item);
5027 kfree(p);
5028 blockpool->pool_size--;
5029 }
5030
5031 list_for_each_safe(p, n, &blockpool->free_entry_list) {
5032 list_del(
5033 &((struct __vxge_hw_blockpool_entry *)p)->item);
5034 kfree((void *)p);
5035 }
5036 ret = 0;
5037exit:
5038 return;
5039}
5040
5041/*
5042 * __vxge_hw_blockpool_blocks_add - Request additional blocks
5043 */
5044static
5045void __vxge_hw_blockpool_blocks_add(struct __vxge_hw_blockpool *blockpool)
5046{
5047 u32 nreq = 0, i;
5048
5049 if ((blockpool->pool_size + blockpool->req_out) <
5050 VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE) {
5051 nreq = VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE;
5052 blockpool->req_out += nreq;
5053 }
5054
5055 for (i = 0; i < nreq; i++)
5056 vxge_os_dma_malloc_async(
5057 ((struct __vxge_hw_device *)blockpool->hldev)->pdev,
5058 blockpool->hldev, VXGE_HW_BLOCK_SIZE);
5059}
5060
5061/*
5062 * __vxge_hw_blockpool_blocks_remove - Free additional blocks
5063 */
5064static
5065void __vxge_hw_blockpool_blocks_remove(struct __vxge_hw_blockpool *blockpool)
5066{
5067 struct list_head *p, *n;
5068
5069 list_for_each_safe(p, n, &blockpool->free_block_list) {
5070
5071 if (blockpool->pool_size < blockpool->pool_max)
5072 break;
5073
5074 pci_unmap_single(
5075 ((struct __vxge_hw_device *)blockpool->hldev)->pdev,
5076 ((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
5077 ((struct __vxge_hw_blockpool_entry *)p)->length,
5078 PCI_DMA_BIDIRECTIONAL);
5079
5080 vxge_os_dma_free(
5081 ((struct __vxge_hw_device *)blockpool->hldev)->pdev,
5082 ((struct __vxge_hw_blockpool_entry *)p)->memblock,
5083 &((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
5084
5085 list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
5086
5087 list_add(p, &blockpool->free_entry_list);
5088
5089 blockpool->pool_size--;
5090
5091 }
5092}
5093
5094/*
5095 * vxge_hw_blockpool_block_add - callback for vxge_os_dma_malloc_async
5096 * Adds a block to block pool
5097 */
stephen hemminger42821a52010-10-21 07:50:53 +00005098static void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
5099 void *block_addr,
5100 u32 length,
5101 struct pci_dev *dma_h,
5102 struct pci_dev *acc_handle)
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00005103{
5104 struct __vxge_hw_blockpool *blockpool;
5105 struct __vxge_hw_blockpool_entry *entry = NULL;
5106 dma_addr_t dma_addr;
5107 enum vxge_hw_status status = VXGE_HW_OK;
5108 u32 req_out;
5109
5110 blockpool = &devh->block_pool;
5111
5112 if (block_addr == NULL) {
5113 blockpool->req_out--;
5114 status = VXGE_HW_FAIL;
5115 goto exit;
5116 }
5117
5118 dma_addr = pci_map_single(devh->pdev, block_addr, length,
5119 PCI_DMA_BIDIRECTIONAL);
5120
5121 if (unlikely(pci_dma_mapping_error(devh->pdev, dma_addr))) {
5122
5123 vxge_os_dma_free(devh->pdev, block_addr, &acc_handle);
5124 blockpool->req_out--;
5125 status = VXGE_HW_FAIL;
5126 goto exit;
5127 }
5128
5129
5130 if (!list_empty(&blockpool->free_entry_list))
5131 entry = (struct __vxge_hw_blockpool_entry *)
5132 list_first_entry(&blockpool->free_entry_list,
5133 struct __vxge_hw_blockpool_entry,
5134 item);
5135
5136 if (entry == NULL)
5137 entry = (struct __vxge_hw_blockpool_entry *)
5138 vmalloc(sizeof(struct __vxge_hw_blockpool_entry));
5139 else
5140 list_del(&entry->item);
5141
5142 if (entry != NULL) {
5143 entry->length = length;
5144 entry->memblock = block_addr;
5145 entry->dma_addr = dma_addr;
5146 entry->acc_handle = acc_handle;
5147 entry->dma_handle = dma_h;
5148 list_add(&entry->item, &blockpool->free_block_list);
5149 blockpool->pool_size++;
5150 status = VXGE_HW_OK;
5151 } else
5152 status = VXGE_HW_ERR_OUT_OF_MEMORY;
5153
5154 blockpool->req_out--;
5155
5156 req_out = blockpool->req_out;
5157exit:
5158 return;
5159}
5160
5161/*
5162 * __vxge_hw_blockpool_malloc - Allocate a memory block from pool
5163 * Allocates a block of memory of given size, either from block pool
5164 * or by calling vxge_os_dma_malloc()
5165 */
5166void *
5167__vxge_hw_blockpool_malloc(struct __vxge_hw_device *devh, u32 size,
5168 struct vxge_hw_mempool_dma *dma_object)
5169{
5170 struct __vxge_hw_blockpool_entry *entry = NULL;
5171 struct __vxge_hw_blockpool *blockpool;
5172 void *memblock = NULL;
5173 enum vxge_hw_status status = VXGE_HW_OK;
5174
5175 blockpool = &devh->block_pool;
5176
5177 if (size != blockpool->block_size) {
5178
5179 memblock = vxge_os_dma_malloc(devh->pdev, size,
5180 &dma_object->handle,
5181 &dma_object->acc_handle);
5182
5183 if (memblock == NULL) {
5184 status = VXGE_HW_ERR_OUT_OF_MEMORY;
5185 goto exit;
5186 }
5187
5188 dma_object->addr = pci_map_single(devh->pdev, memblock, size,
5189 PCI_DMA_BIDIRECTIONAL);
5190
5191 if (unlikely(pci_dma_mapping_error(devh->pdev,
5192 dma_object->addr))) {
5193 vxge_os_dma_free(devh->pdev, memblock,
5194 &dma_object->acc_handle);
5195 status = VXGE_HW_ERR_OUT_OF_MEMORY;
5196 goto exit;
5197 }
5198
5199 } else {
5200
5201 if (!list_empty(&blockpool->free_block_list))
5202 entry = (struct __vxge_hw_blockpool_entry *)
5203 list_first_entry(&blockpool->free_block_list,
5204 struct __vxge_hw_blockpool_entry,
5205 item);
5206
5207 if (entry != NULL) {
5208 list_del(&entry->item);
5209 dma_object->addr = entry->dma_addr;
5210 dma_object->handle = entry->dma_handle;
5211 dma_object->acc_handle = entry->acc_handle;
5212 memblock = entry->memblock;
5213
5214 list_add(&entry->item,
5215 &blockpool->free_entry_list);
5216 blockpool->pool_size--;
5217 }
5218
5219 if (memblock != NULL)
5220 __vxge_hw_blockpool_blocks_add(blockpool);
5221 }
5222exit:
5223 return memblock;
5224}
5225
5226/*
5227 * __vxge_hw_blockpool_free - Frees the memory allcoated with
5228 __vxge_hw_blockpool_malloc
5229 */
5230void
5231__vxge_hw_blockpool_free(struct __vxge_hw_device *devh,
5232 void *memblock, u32 size,
5233 struct vxge_hw_mempool_dma *dma_object)
5234{
5235 struct __vxge_hw_blockpool_entry *entry = NULL;
5236 struct __vxge_hw_blockpool *blockpool;
5237 enum vxge_hw_status status = VXGE_HW_OK;
5238
5239 blockpool = &devh->block_pool;
5240
5241 if (size != blockpool->block_size) {
5242 pci_unmap_single(devh->pdev, dma_object->addr, size,
5243 PCI_DMA_BIDIRECTIONAL);
5244 vxge_os_dma_free(devh->pdev, memblock, &dma_object->acc_handle);
5245 } else {
5246
5247 if (!list_empty(&blockpool->free_entry_list))
5248 entry = (struct __vxge_hw_blockpool_entry *)
5249 list_first_entry(&blockpool->free_entry_list,
5250 struct __vxge_hw_blockpool_entry,
5251 item);
5252
5253 if (entry == NULL)
5254 entry = (struct __vxge_hw_blockpool_entry *)
5255 vmalloc(sizeof(
5256 struct __vxge_hw_blockpool_entry));
5257 else
5258 list_del(&entry->item);
5259
5260 if (entry != NULL) {
5261 entry->length = size;
5262 entry->memblock = memblock;
5263 entry->dma_addr = dma_object->addr;
5264 entry->acc_handle = dma_object->acc_handle;
5265 entry->dma_handle = dma_object->handle;
5266 list_add(&entry->item,
5267 &blockpool->free_block_list);
5268 blockpool->pool_size++;
5269 status = VXGE_HW_OK;
5270 } else
5271 status = VXGE_HW_ERR_OUT_OF_MEMORY;
5272
5273 if (status == VXGE_HW_OK)
5274 __vxge_hw_blockpool_blocks_remove(blockpool);
5275 }
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00005276}
5277
5278/*
5279 * __vxge_hw_blockpool_block_allocate - Allocates a block from block pool
5280 * This function allocates a block from block pool or from the system
5281 */
5282struct __vxge_hw_blockpool_entry *
5283__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size)
5284{
5285 struct __vxge_hw_blockpool_entry *entry = NULL;
5286 struct __vxge_hw_blockpool *blockpool;
5287
5288 blockpool = &devh->block_pool;
5289
5290 if (size == blockpool->block_size) {
5291
5292 if (!list_empty(&blockpool->free_block_list))
5293 entry = (struct __vxge_hw_blockpool_entry *)
5294 list_first_entry(&blockpool->free_block_list,
5295 struct __vxge_hw_blockpool_entry,
5296 item);
5297
5298 if (entry != NULL) {
5299 list_del(&entry->item);
5300 blockpool->pool_size--;
5301 }
5302 }
5303
5304 if (entry != NULL)
5305 __vxge_hw_blockpool_blocks_add(blockpool);
5306
5307 return entry;
5308}
5309
5310/*
5311 * __vxge_hw_blockpool_block_free - Frees a block from block pool
5312 * @devh: Hal device
5313 * @entry: Entry of block to be freed
5314 *
5315 * This function frees a block from block pool
5316 */
5317void
5318__vxge_hw_blockpool_block_free(struct __vxge_hw_device *devh,
5319 struct __vxge_hw_blockpool_entry *entry)
5320{
5321 struct __vxge_hw_blockpool *blockpool;
5322
5323 blockpool = &devh->block_pool;
5324
5325 if (entry->length == blockpool->block_size) {
5326 list_add(&entry->item, &blockpool->free_block_list);
5327 blockpool->pool_size++;
5328 }
5329
5330 __vxge_hw_blockpool_blocks_remove(blockpool);
Ramkrishna Vepa40a3a912009-04-01 18:14:40 +00005331}