diff options
-rw-r--r-- | drivers/net/ethernet/intel/i40e/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e.h | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_common.c | 253 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ddp.c | 481 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_prototype.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_type.h | 23 |
8 files changed, 769 insertions, 22 deletions
diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile index 50590e8d1fd1..2f21b3e89fd0 100644 --- a/drivers/net/ethernet/intel/i40e/Makefile +++ b/drivers/net/ethernet/intel/i40e/Makefile | |||
@@ -21,6 +21,7 @@ i40e-objs := i40e_main.o \ | |||
21 | i40e_diag.o \ | 21 | i40e_diag.o \ |
22 | i40e_txrx.o \ | 22 | i40e_txrx.o \ |
23 | i40e_ptp.o \ | 23 | i40e_ptp.o \ |
24 | i40e_ddp.o \ | ||
24 | i40e_client.o \ | 25 | i40e_client.o \ |
25 | i40e_virtchnl_pf.o \ | 26 | i40e_virtchnl_pf.o \ |
26 | i40e_xsk.o | 27 | i40e_xsk.o |
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index d3cc3427caad..fc4cae2fef4f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h | |||
@@ -321,6 +321,29 @@ struct i40e_udp_port_config { | |||
321 | u8 filter_index; | 321 | u8 filter_index; |
322 | }; | 322 | }; |
323 | 323 | ||
324 | #define I40_DDP_FLASH_REGION 100 | ||
325 | #define I40E_PROFILE_INFO_SIZE 48 | ||
326 | #define I40E_MAX_PROFILE_NUM 16 | ||
327 | #define I40E_PROFILE_LIST_SIZE \ | ||
328 | (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4) | ||
329 | #define I40E_DDP_PROFILE_PATH "intel/i40e/ddp/" | ||
330 | #define I40E_DDP_PROFILE_NAME_MAX 64 | ||
331 | |||
332 | int i40e_ddp_load(struct net_device *netdev, const u8 *data, size_t size, | ||
333 | bool is_add); | ||
334 | int i40e_ddp_flash(struct net_device *netdev, struct ethtool_flash *flash); | ||
335 | |||
336 | struct i40e_ddp_profile_list { | ||
337 | u32 p_count; | ||
338 | struct i40e_profile_info p_info[0]; | ||
339 | }; | ||
340 | |||
341 | struct i40e_ddp_old_profile_list { | ||
342 | struct list_head list; | ||
343 | size_t old_ddp_size; | ||
344 | u8 old_ddp_buf[0]; | ||
345 | }; | ||
346 | |||
324 | /* macros related to FLX_PIT */ | 347 | /* macros related to FLX_PIT */ |
325 | #define I40E_FLEX_SET_FSIZE(fsize) (((fsize) << \ | 348 | #define I40E_FLEX_SET_FSIZE(fsize) (((fsize) << \ |
326 | I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) & \ | 349 | I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) & \ |
@@ -610,6 +633,8 @@ struct i40e_pf { | |||
610 | u16 override_q_count; | 633 | u16 override_q_count; |
611 | u16 last_sw_conf_flags; | 634 | u16 last_sw_conf_flags; |
612 | u16 last_sw_conf_valid_flags; | 635 | u16 last_sw_conf_valid_flags; |
636 | /* List to keep previous DDP profiles to be rolled back in the future */ | ||
637 | struct list_head ddp_old_prof; | ||
613 | }; | 638 | }; |
614 | 639 | ||
615 | /** | 640 | /** |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 97a9b1fb4763..486a406789b8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c | |||
@@ -5448,6 +5448,163 @@ i40e_find_segment_in_package(u32 segment_type, | |||
5448 | return NULL; | 5448 | return NULL; |
5449 | } | 5449 | } |
5450 | 5450 | ||
5451 | /* Get section table in profile */ | ||
5452 | #define I40E_SECTION_TABLE(profile, sec_tbl) \ | ||
5453 | do { \ | ||
5454 | struct i40e_profile_segment *p = (profile); \ | ||
5455 | u32 count; \ | ||
5456 | u32 *nvm; \ | ||
5457 | count = p->device_table_count; \ | ||
5458 | nvm = (u32 *)&p->device_table[count]; \ | ||
5459 | sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; \ | ||
5460 | } while (0) | ||
5461 | |||
5462 | /* Get section header in profile */ | ||
5463 | #define I40E_SECTION_HEADER(profile, offset) \ | ||
5464 | (struct i40e_profile_section_header *)((u8 *)(profile) + (offset)) | ||
5465 | |||
5466 | /** | ||
5467 | * i40e_find_section_in_profile | ||
5468 | * @section_type: the section type to search for (i.e., SECTION_TYPE_NOTE) | ||
5469 | * @profile: pointer to the i40e segment header to be searched | ||
5470 | * | ||
5471 | * This function searches i40e segment for a particular section type. On | ||
5472 | * success it returns a pointer to the section header, otherwise it will | ||
5473 | * return NULL. | ||
5474 | **/ | ||
5475 | struct i40e_profile_section_header * | ||
5476 | i40e_find_section_in_profile(u32 section_type, | ||
5477 | struct i40e_profile_segment *profile) | ||
5478 | { | ||
5479 | struct i40e_profile_section_header *sec; | ||
5480 | struct i40e_section_table *sec_tbl; | ||
5481 | u32 sec_off; | ||
5482 | u32 i; | ||
5483 | |||
5484 | if (profile->header.type != SEGMENT_TYPE_I40E) | ||
5485 | return NULL; | ||
5486 | |||
5487 | I40E_SECTION_TABLE(profile, sec_tbl); | ||
5488 | |||
5489 | for (i = 0; i < sec_tbl->section_count; i++) { | ||
5490 | sec_off = sec_tbl->section_offset[i]; | ||
5491 | sec = I40E_SECTION_HEADER(profile, sec_off); | ||
5492 | if (sec->section.type == section_type) | ||
5493 | return sec; | ||
5494 | } | ||
5495 | |||
5496 | return NULL; | ||
5497 | } | ||
5498 | |||
5499 | /** | ||
5500 | * i40e_ddp_exec_aq_section - Execute generic AQ for DDP | ||
5501 | * @hw: pointer to the hw struct | ||
5502 | * @aq: command buffer containing all data to execute AQ | ||
5503 | **/ | ||
5504 | static enum | ||
5505 | i40e_status_code i40e_ddp_exec_aq_section(struct i40e_hw *hw, | ||
5506 | struct i40e_profile_aq_section *aq) | ||
5507 | { | ||
5508 | i40e_status status; | ||
5509 | struct i40e_aq_desc desc; | ||
5510 | u8 *msg = NULL; | ||
5511 | u16 msglen; | ||
5512 | |||
5513 | i40e_fill_default_direct_cmd_desc(&desc, aq->opcode); | ||
5514 | desc.flags |= cpu_to_le16(aq->flags); | ||
5515 | memcpy(desc.params.raw, aq->param, sizeof(desc.params.raw)); | ||
5516 | |||
5517 | msglen = aq->datalen; | ||
5518 | if (msglen) { | ||
5519 | desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | | ||
5520 | I40E_AQ_FLAG_RD)); | ||
5521 | if (msglen > I40E_AQ_LARGE_BUF) | ||
5522 | desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); | ||
5523 | desc.datalen = cpu_to_le16(msglen); | ||
5524 | msg = &aq->data[0]; | ||
5525 | } | ||
5526 | |||
5527 | status = i40e_asq_send_command(hw, &desc, msg, msglen, NULL); | ||
5528 | |||
5529 | if (status) { | ||
5530 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5531 | "unable to exec DDP AQ opcode %u, error %d\n", | ||
5532 | aq->opcode, status); | ||
5533 | return status; | ||
5534 | } | ||
5535 | |||
5536 | /* copy returned desc to aq_buf */ | ||
5537 | memcpy(aq->param, desc.params.raw, sizeof(desc.params.raw)); | ||
5538 | |||
5539 | return 0; | ||
5540 | } | ||
5541 | |||
5542 | /** | ||
5543 | * i40e_validate_profile | ||
5544 | * @hw: pointer to the hardware structure | ||
5545 | * @profile: pointer to the profile segment of the package to be validated | ||
5546 | * @track_id: package tracking id | ||
5547 | * @rollback: flag if the profile is for rollback. | ||
5548 | * | ||
5549 | * Validates supported devices and profile's sections. | ||
5550 | */ | ||
5551 | static enum i40e_status_code | ||
5552 | i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, | ||
5553 | u32 track_id, bool rollback) | ||
5554 | { | ||
5555 | struct i40e_profile_section_header *sec = NULL; | ||
5556 | i40e_status status = 0; | ||
5557 | struct i40e_section_table *sec_tbl; | ||
5558 | u32 vendor_dev_id; | ||
5559 | u32 dev_cnt; | ||
5560 | u32 sec_off; | ||
5561 | u32 i; | ||
5562 | |||
5563 | if (track_id == I40E_DDP_TRACKID_INVALID) { | ||
5564 | i40e_debug(hw, I40E_DEBUG_PACKAGE, "Invalid track_id\n"); | ||
5565 | return I40E_NOT_SUPPORTED; | ||
5566 | } | ||
5567 | |||
5568 | dev_cnt = profile->device_table_count; | ||
5569 | for (i = 0; i < dev_cnt; i++) { | ||
5570 | vendor_dev_id = profile->device_table[i].vendor_dev_id; | ||
5571 | if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL && | ||
5572 | hw->device_id == (vendor_dev_id & 0xFFFF)) | ||
5573 | break; | ||
5574 | } | ||
5575 | if (dev_cnt && i == dev_cnt) { | ||
5576 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5577 | "Device doesn't support DDP\n"); | ||
5578 | return I40E_ERR_DEVICE_NOT_SUPPORTED; | ||
5579 | } | ||
5580 | |||
5581 | I40E_SECTION_TABLE(profile, sec_tbl); | ||
5582 | |||
5583 | /* Validate sections types */ | ||
5584 | for (i = 0; i < sec_tbl->section_count; i++) { | ||
5585 | sec_off = sec_tbl->section_offset[i]; | ||
5586 | sec = I40E_SECTION_HEADER(profile, sec_off); | ||
5587 | if (rollback) { | ||
5588 | if (sec->section.type == SECTION_TYPE_MMIO || | ||
5589 | sec->section.type == SECTION_TYPE_AQ || | ||
5590 | sec->section.type == SECTION_TYPE_RB_AQ) { | ||
5591 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5592 | "Not a roll-back package\n"); | ||
5593 | return I40E_NOT_SUPPORTED; | ||
5594 | } | ||
5595 | } else { | ||
5596 | if (sec->section.type == SECTION_TYPE_RB_AQ || | ||
5597 | sec->section.type == SECTION_TYPE_RB_MMIO) { | ||
5598 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5599 | "Not an original package\n"); | ||
5600 | return I40E_NOT_SUPPORTED; | ||
5601 | } | ||
5602 | } | ||
5603 | } | ||
5604 | |||
5605 | return status; | ||
5606 | } | ||
5607 | |||
5451 | /** | 5608 | /** |
5452 | * i40e_write_profile | 5609 | * i40e_write_profile |
5453 | * @hw: pointer to the hardware structure | 5610 | * @hw: pointer to the hardware structure |
@@ -5463,47 +5620,99 @@ i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, | |||
5463 | i40e_status status = 0; | 5620 | i40e_status status = 0; |
5464 | struct i40e_section_table *sec_tbl; | 5621 | struct i40e_section_table *sec_tbl; |
5465 | struct i40e_profile_section_header *sec = NULL; | 5622 | struct i40e_profile_section_header *sec = NULL; |
5466 | u32 dev_cnt; | 5623 | struct i40e_profile_aq_section *ddp_aq; |
5467 | u32 vendor_dev_id; | ||
5468 | u32 *nvm; | ||
5469 | u32 section_size = 0; | 5624 | u32 section_size = 0; |
5470 | u32 offset = 0, info = 0; | 5625 | u32 offset = 0, info = 0; |
5626 | u32 sec_off; | ||
5471 | u32 i; | 5627 | u32 i; |
5472 | 5628 | ||
5473 | dev_cnt = profile->device_table_count; | 5629 | status = i40e_validate_profile(hw, profile, track_id, false); |
5630 | if (status) | ||
5631 | return status; | ||
5474 | 5632 | ||
5475 | for (i = 0; i < dev_cnt; i++) { | 5633 | I40E_SECTION_TABLE(profile, sec_tbl); |
5476 | vendor_dev_id = profile->device_table[i].vendor_dev_id; | 5634 | |
5477 | if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL) | 5635 | for (i = 0; i < sec_tbl->section_count; i++) { |
5478 | if (hw->device_id == (vendor_dev_id & 0xFFFF)) | 5636 | sec_off = sec_tbl->section_offset[i]; |
5637 | sec = I40E_SECTION_HEADER(profile, sec_off); | ||
5638 | /* Process generic admin command */ | ||
5639 | if (sec->section.type == SECTION_TYPE_AQ) { | ||
5640 | ddp_aq = (struct i40e_profile_aq_section *)&sec[1]; | ||
5641 | status = i40e_ddp_exec_aq_section(hw, ddp_aq); | ||
5642 | if (status) { | ||
5643 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5644 | "Failed to execute aq: section %d, opcode %u\n", | ||
5645 | i, ddp_aq->opcode); | ||
5479 | break; | 5646 | break; |
5647 | } | ||
5648 | sec->section.type = SECTION_TYPE_RB_AQ; | ||
5649 | } | ||
5650 | |||
5651 | /* Skip any non-mmio sections */ | ||
5652 | if (sec->section.type != SECTION_TYPE_MMIO) | ||
5653 | continue; | ||
5654 | |||
5655 | section_size = sec->section.size + | ||
5656 | sizeof(struct i40e_profile_section_header); | ||
5657 | |||
5658 | /* Write MMIO section */ | ||
5659 | status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size, | ||
5660 | track_id, &offset, &info, NULL); | ||
5661 | if (status) { | ||
5662 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | ||
5663 | "Failed to write profile: section %d, offset %d, info %d\n", | ||
5664 | i, offset, info); | ||
5665 | break; | ||
5666 | } | ||
5480 | } | 5667 | } |
5481 | if (i == dev_cnt) { | 5668 | return status; |
5482 | i40e_debug(hw, I40E_DEBUG_PACKAGE, "Device doesn't support DDP"); | 5669 | } |
5483 | return I40E_ERR_DEVICE_NOT_SUPPORTED; | 5670 | |
5484 | } | 5671 | /** |
5672 | * i40e_rollback_profile | ||
5673 | * @hw: pointer to the hardware structure | ||
5674 | * @profile: pointer to the profile segment of the package to be removed | ||
5675 | * @track_id: package tracking id | ||
5676 | * | ||
5677 | * Rolls back previously loaded package. | ||
5678 | */ | ||
5679 | enum i40e_status_code | ||
5680 | i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, | ||
5681 | u32 track_id) | ||
5682 | { | ||
5683 | struct i40e_profile_section_header *sec = NULL; | ||
5684 | i40e_status status = 0; | ||
5685 | struct i40e_section_table *sec_tbl; | ||
5686 | u32 offset = 0, info = 0; | ||
5687 | u32 section_size = 0; | ||
5688 | u32 sec_off; | ||
5689 | int i; | ||
5485 | 5690 | ||
5486 | nvm = (u32 *)&profile->device_table[dev_cnt]; | 5691 | status = i40e_validate_profile(hw, profile, track_id, true); |
5487 | sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; | 5692 | if (status) |
5693 | return status; | ||
5488 | 5694 | ||
5489 | for (i = 0; i < sec_tbl->section_count; i++) { | 5695 | I40E_SECTION_TABLE(profile, sec_tbl); |
5490 | sec = (struct i40e_profile_section_header *)((u8 *)profile + | ||
5491 | sec_tbl->section_offset[i]); | ||
5492 | 5696 | ||
5493 | /* Skip 'AQ', 'note' and 'name' sections */ | 5697 | /* For rollback write sections in reverse */ |
5494 | if (sec->section.type != SECTION_TYPE_MMIO) | 5698 | for (i = sec_tbl->section_count - 1; i >= 0; i--) { |
5699 | sec_off = sec_tbl->section_offset[i]; | ||
5700 | sec = I40E_SECTION_HEADER(profile, sec_off); | ||
5701 | |||
5702 | /* Skip any non-rollback sections */ | ||
5703 | if (sec->section.type != SECTION_TYPE_RB_MMIO) | ||
5495 | continue; | 5704 | continue; |
5496 | 5705 | ||
5497 | section_size = sec->section.size + | 5706 | section_size = sec->section.size + |
5498 | sizeof(struct i40e_profile_section_header); | 5707 | sizeof(struct i40e_profile_section_header); |
5499 | 5708 | ||
5500 | /* Write profile */ | 5709 | /* Write roll-back MMIO section */ |
5501 | status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size, | 5710 | status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size, |
5502 | track_id, &offset, &info, NULL); | 5711 | track_id, &offset, &info, NULL); |
5503 | if (status) { | 5712 | if (status) { |
5504 | i40e_debug(hw, I40E_DEBUG_PACKAGE, | 5713 | i40e_debug(hw, I40E_DEBUG_PACKAGE, |
5505 | "Failed to write profile: offset %d, info %d", | 5714 | "Failed to write profile: section %d, offset %d, info %d\n", |
5506 | offset, info); | 5715 | i, offset, info); |
5507 | break; | 5716 | break; |
5508 | } | 5717 | } |
5509 | } | 5718 | } |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ddp.c b/drivers/net/ethernet/intel/i40e/i40e_ddp.c new file mode 100644 index 000000000000..5e08f100c413 --- /dev/null +++ b/drivers/net/ethernet/intel/i40e/i40e_ddp.c | |||
@@ -0,0 +1,481 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* Copyright(c) 2013 - 2018 Intel Corporation. */ | ||
3 | |||
4 | #include "i40e.h" | ||
5 | |||
6 | #include <linux/firmware.h> | ||
7 | |||
8 | /** | ||
9 | * i40e_ddp_profiles_eq - checks if DDP profiles are the equivalent | ||
10 | * @a: new profile info | ||
11 | * @b: old profile info | ||
12 | * | ||
13 | * checks if DDP profiles are the equivalent. | ||
14 | * Returns true if profiles are the same. | ||
15 | **/ | ||
16 | static bool i40e_ddp_profiles_eq(struct i40e_profile_info *a, | ||
17 | struct i40e_profile_info *b) | ||
18 | { | ||
19 | return a->track_id == b->track_id && | ||
20 | !memcmp(&a->version, &b->version, sizeof(a->version)) && | ||
21 | !memcmp(&a->name, &b->name, I40E_DDP_NAME_SIZE); | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * i40e_ddp_does_profile_exist - checks if DDP profile loaded already | ||
26 | * @hw: HW data structure | ||
27 | * @pinfo: DDP profile information structure | ||
28 | * | ||
29 | * checks if DDP profile loaded already. | ||
30 | * Returns >0 if the profile exists. | ||
31 | * Returns 0 if the profile is absent. | ||
32 | * Returns <0 if error. | ||
33 | **/ | ||
34 | static int i40e_ddp_does_profile_exist(struct i40e_hw *hw, | ||
35 | struct i40e_profile_info *pinfo) | ||
36 | { | ||
37 | struct i40e_ddp_profile_list *profile_list; | ||
38 | u8 buff[I40E_PROFILE_LIST_SIZE]; | ||
39 | i40e_status status; | ||
40 | int i; | ||
41 | |||
42 | status = i40e_aq_get_ddp_list(hw, buff, I40E_PROFILE_LIST_SIZE, 0, | ||
43 | NULL); | ||
44 | if (status) | ||
45 | return -1; | ||
46 | |||
47 | profile_list = (struct i40e_ddp_profile_list *)buff; | ||
48 | for (i = 0; i < profile_list->p_count; i++) { | ||
49 | if (i40e_ddp_profiles_eq(pinfo, &profile_list->p_info[i])) | ||
50 | return 1; | ||
51 | } | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * i40e_ddp_profiles_overlap - checks if DDP profiles overlap. | ||
57 | * @new: new profile info | ||
58 | * @old: old profile info | ||
59 | * | ||
60 | * checks if DDP profiles overlap. | ||
61 | * Returns true if profiles are overlap. | ||
62 | **/ | ||
63 | static bool i40e_ddp_profiles_overlap(struct i40e_profile_info *new, | ||
64 | struct i40e_profile_info *old) | ||
65 | { | ||
66 | unsigned int group_id_old = (u8)((old->track_id & 0x00FF0000) >> 16); | ||
67 | unsigned int group_id_new = (u8)((new->track_id & 0x00FF0000) >> 16); | ||
68 | |||
69 | /* 0x00 group must be only the first */ | ||
70 | if (group_id_new == 0) | ||
71 | return true; | ||
72 | /* 0xFF group is compatible with anything else */ | ||
73 | if (group_id_new == 0xFF || group_id_old == 0xFF) | ||
74 | return false; | ||
75 | /* otherwise only profiles from the same group are compatible*/ | ||
76 | return group_id_old != group_id_new; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * i40e_ddp_does_profiles_ - checks if DDP overlaps with existing one. | ||
81 | * @hw: HW data structure | ||
82 | * @pinfo: DDP profile information structure | ||
83 | * | ||
84 | * checks if DDP profile overlaps with existing one. | ||
85 | * Returns >0 if the profile overlaps. | ||
86 | * Returns 0 if the profile is ok. | ||
87 | * Returns <0 if error. | ||
88 | **/ | ||
89 | static int i40e_ddp_does_profile_overlap(struct i40e_hw *hw, | ||
90 | struct i40e_profile_info *pinfo) | ||
91 | { | ||
92 | struct i40e_ddp_profile_list *profile_list; | ||
93 | u8 buff[I40E_PROFILE_LIST_SIZE]; | ||
94 | i40e_status status; | ||
95 | int i; | ||
96 | |||
97 | status = i40e_aq_get_ddp_list(hw, buff, I40E_PROFILE_LIST_SIZE, 0, | ||
98 | NULL); | ||
99 | if (status) | ||
100 | return -EIO; | ||
101 | |||
102 | profile_list = (struct i40e_ddp_profile_list *)buff; | ||
103 | for (i = 0; i < profile_list->p_count; i++) { | ||
104 | if (i40e_ddp_profiles_overlap(pinfo, | ||
105 | &profile_list->p_info[i])) | ||
106 | return 1; | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * i40e_add_pinfo | ||
113 | * @hw: pointer to the hardware structure | ||
114 | * @profile: pointer to the profile segment of the package | ||
115 | * @profile_info_sec: buffer for information section | ||
116 | * @track_id: package tracking id | ||
117 | * | ||
118 | * Register a profile to the list of loaded profiles. | ||
119 | */ | ||
120 | static enum i40e_status_code | ||
121 | i40e_add_pinfo(struct i40e_hw *hw, struct i40e_profile_segment *profile, | ||
122 | u8 *profile_info_sec, u32 track_id) | ||
123 | { | ||
124 | struct i40e_profile_section_header *sec; | ||
125 | struct i40e_profile_info *pinfo; | ||
126 | i40e_status status; | ||
127 | u32 offset = 0, info = 0; | ||
128 | |||
129 | sec = (struct i40e_profile_section_header *)profile_info_sec; | ||
130 | sec->tbl_size = 1; | ||
131 | sec->data_end = sizeof(struct i40e_profile_section_header) + | ||
132 | sizeof(struct i40e_profile_info); | ||
133 | sec->section.type = SECTION_TYPE_INFO; | ||
134 | sec->section.offset = sizeof(struct i40e_profile_section_header); | ||
135 | sec->section.size = sizeof(struct i40e_profile_info); | ||
136 | pinfo = (struct i40e_profile_info *)(profile_info_sec + | ||
137 | sec->section.offset); | ||
138 | pinfo->track_id = track_id; | ||
139 | pinfo->version = profile->version; | ||
140 | pinfo->op = I40E_DDP_ADD_TRACKID; | ||
141 | |||
142 | /* Clear reserved field */ | ||
143 | memset(pinfo->reserved, 0, sizeof(pinfo->reserved)); | ||
144 | memcpy(pinfo->name, profile->name, I40E_DDP_NAME_SIZE); | ||
145 | |||
146 | status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end, | ||
147 | track_id, &offset, &info, NULL); | ||
148 | return status; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * i40e_del_pinfo - delete DDP profile info from NIC | ||
153 | * @hw: HW data structure | ||
154 | * @profile: DDP profile segment to be deleted | ||
155 | * @profile_info_sec: DDP profile section header | ||
156 | * @track_id: track ID of the profile for deletion | ||
157 | * | ||
158 | * Removes DDP profile from the NIC. | ||
159 | **/ | ||
160 | static enum i40e_status_code | ||
161 | i40e_del_pinfo(struct i40e_hw *hw, struct i40e_profile_segment *profile, | ||
162 | u8 *profile_info_sec, u32 track_id) | ||
163 | { | ||
164 | struct i40e_profile_section_header *sec; | ||
165 | struct i40e_profile_info *pinfo; | ||
166 | i40e_status status; | ||
167 | u32 offset = 0, info = 0; | ||
168 | |||
169 | sec = (struct i40e_profile_section_header *)profile_info_sec; | ||
170 | sec->tbl_size = 1; | ||
171 | sec->data_end = sizeof(struct i40e_profile_section_header) + | ||
172 | sizeof(struct i40e_profile_info); | ||
173 | sec->section.type = SECTION_TYPE_INFO; | ||
174 | sec->section.offset = sizeof(struct i40e_profile_section_header); | ||
175 | sec->section.size = sizeof(struct i40e_profile_info); | ||
176 | pinfo = (struct i40e_profile_info *)(profile_info_sec + | ||
177 | sec->section.offset); | ||
178 | pinfo->track_id = track_id; | ||
179 | pinfo->version = profile->version; | ||
180 | pinfo->op = I40E_DDP_REMOVE_TRACKID; | ||
181 | |||
182 | /* Clear reserved field */ | ||
183 | memset(pinfo->reserved, 0, sizeof(pinfo->reserved)); | ||
184 | memcpy(pinfo->name, profile->name, I40E_DDP_NAME_SIZE); | ||
185 | |||
186 | status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end, | ||
187 | track_id, &offset, &info, NULL); | ||
188 | return status; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * i40e_ddp_is_pkg_hdr_valid - performs basic pkg header integrity checks | ||
193 | * @netdev: net device structure (for logging purposes) | ||
194 | * @pkg_hdr: pointer to package header | ||
195 | * @size_huge: size of the whole DDP profile package in size_t | ||
196 | * | ||
197 | * Checks correctness of pkg header: Version, size too big/small, and | ||
198 | * all segment offsets alignment and boundaries. This function lets | ||
199 | * reject non DDP profile file to be loaded by administrator mistake. | ||
200 | **/ | ||
201 | static bool i40e_ddp_is_pkg_hdr_valid(struct net_device *netdev, | ||
202 | struct i40e_package_header *pkg_hdr, | ||
203 | size_t size_huge) | ||
204 | { | ||
205 | u32 size = 0xFFFFFFFFU & size_huge; | ||
206 | u32 pkg_hdr_size; | ||
207 | u32 segment; | ||
208 | |||
209 | if (!pkg_hdr) | ||
210 | return false; | ||
211 | |||
212 | if (pkg_hdr->version.major > 0) { | ||
213 | struct i40e_ddp_version ver = pkg_hdr->version; | ||
214 | |||
215 | netdev_err(netdev, "Unsupported DDP profile version %u.%u.%u.%u", | ||
216 | ver.major, ver.minor, ver.update, ver.draft); | ||
217 | return false; | ||
218 | } | ||
219 | if (size_huge > size) { | ||
220 | netdev_err(netdev, "Invalid DDP profile - size is bigger than 4G"); | ||
221 | return false; | ||
222 | } | ||
223 | if (size < (sizeof(struct i40e_package_header) + | ||
224 | sizeof(struct i40e_metadata_segment) + sizeof(u32) * 2)) { | ||
225 | netdev_err(netdev, "Invalid DDP profile - size is too small."); | ||
226 | return false; | ||
227 | } | ||
228 | |||
229 | pkg_hdr_size = sizeof(u32) * (pkg_hdr->segment_count + 2U); | ||
230 | if (size < pkg_hdr_size) { | ||
231 | netdev_err(netdev, "Invalid DDP profile - too many segments"); | ||
232 | return false; | ||
233 | } | ||
234 | for (segment = 0; segment < pkg_hdr->segment_count; ++segment) { | ||
235 | u32 offset = pkg_hdr->segment_offset[segment]; | ||
236 | |||
237 | if (0xFU & offset) { | ||
238 | netdev_err(netdev, | ||
239 | "Invalid DDP profile %u segment alignment", | ||
240 | segment); | ||
241 | return false; | ||
242 | } | ||
243 | if (pkg_hdr_size > offset || offset >= size) { | ||
244 | netdev_err(netdev, | ||
245 | "Invalid DDP profile %u segment offset", | ||
246 | segment); | ||
247 | return false; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | return true; | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * i40e_ddp_load - performs DDP loading | ||
256 | * @netdev: net device structure | ||
257 | * @data: buffer containing recipe file | ||
258 | * @size: size of the buffer | ||
259 | * @is_add: true when loading profile, false when rolling back the previous one | ||
260 | * | ||
261 | * Checks correctness and loads DDP profile to the NIC. The function is | ||
262 | * also used for rolling back previously loaded profile. | ||
263 | **/ | ||
264 | int i40e_ddp_load(struct net_device *netdev, const u8 *data, size_t size, | ||
265 | bool is_add) | ||
266 | { | ||
267 | u8 profile_info_sec[sizeof(struct i40e_profile_section_header) + | ||
268 | sizeof(struct i40e_profile_info)]; | ||
269 | struct i40e_metadata_segment *metadata_hdr; | ||
270 | struct i40e_profile_segment *profile_hdr; | ||
271 | struct i40e_profile_info pinfo; | ||
272 | struct i40e_package_header *pkg_hdr; | ||
273 | i40e_status status; | ||
274 | struct i40e_netdev_priv *np = netdev_priv(netdev); | ||
275 | struct i40e_vsi *vsi = np->vsi; | ||
276 | struct i40e_pf *pf = vsi->back; | ||
277 | u32 track_id; | ||
278 | int istatus; | ||
279 | |||
280 | pkg_hdr = (struct i40e_package_header *)data; | ||
281 | if (!i40e_ddp_is_pkg_hdr_valid(netdev, pkg_hdr, size)) | ||
282 | return -EINVAL; | ||
283 | |||
284 | if (size < (sizeof(struct i40e_package_header) + | ||
285 | sizeof(struct i40e_metadata_segment) + sizeof(u32) * 2)) { | ||
286 | netdev_err(netdev, "Invalid DDP recipe size."); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | /* Find beginning of segment data in buffer */ | ||
291 | metadata_hdr = (struct i40e_metadata_segment *) | ||
292 | i40e_find_segment_in_package(SEGMENT_TYPE_METADATA, pkg_hdr); | ||
293 | if (!metadata_hdr) { | ||
294 | netdev_err(netdev, "Failed to find metadata segment in DDP recipe."); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | track_id = metadata_hdr->track_id; | ||
299 | profile_hdr = (struct i40e_profile_segment *) | ||
300 | i40e_find_segment_in_package(SEGMENT_TYPE_I40E, pkg_hdr); | ||
301 | if (!profile_hdr) { | ||
302 | netdev_err(netdev, "Failed to find profile segment in DDP recipe."); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | |||
306 | pinfo.track_id = track_id; | ||
307 | pinfo.version = profile_hdr->version; | ||
308 | if (is_add) | ||
309 | pinfo.op = I40E_DDP_ADD_TRACKID; | ||
310 | else | ||
311 | pinfo.op = I40E_DDP_REMOVE_TRACKID; | ||
312 | |||
313 | memcpy(pinfo.name, profile_hdr->name, I40E_DDP_NAME_SIZE); | ||
314 | |||
315 | /* Check if profile data already exists*/ | ||
316 | istatus = i40e_ddp_does_profile_exist(&pf->hw, &pinfo); | ||
317 | if (istatus < 0) { | ||
318 | netdev_err(netdev, "Failed to fetch loaded profiles."); | ||
319 | return istatus; | ||
320 | } | ||
321 | if (is_add) { | ||
322 | if (istatus > 0) { | ||
323 | netdev_err(netdev, "DDP profile already loaded."); | ||
324 | return -EINVAL; | ||
325 | } | ||
326 | istatus = i40e_ddp_does_profile_overlap(&pf->hw, &pinfo); | ||
327 | if (istatus < 0) { | ||
328 | netdev_err(netdev, "Failed to fetch loaded profiles."); | ||
329 | return istatus; | ||
330 | } | ||
331 | if (istatus > 0) { | ||
332 | netdev_err(netdev, "DDP profile overlaps with existing one."); | ||
333 | return -EINVAL; | ||
334 | } | ||
335 | } else { | ||
336 | if (istatus == 0) { | ||
337 | netdev_err(netdev, | ||
338 | "DDP profile for deletion does not exist."); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* Load profile data */ | ||
344 | if (is_add) { | ||
345 | status = i40e_write_profile(&pf->hw, profile_hdr, track_id); | ||
346 | if (status) { | ||
347 | if (status == I40E_ERR_DEVICE_NOT_SUPPORTED) { | ||
348 | netdev_err(netdev, | ||
349 | "Profile is not supported by the device."); | ||
350 | return -EPERM; | ||
351 | } | ||
352 | netdev_err(netdev, "Failed to write DDP profile."); | ||
353 | return -EIO; | ||
354 | } | ||
355 | } else { | ||
356 | status = i40e_rollback_profile(&pf->hw, profile_hdr, track_id); | ||
357 | if (status) { | ||
358 | netdev_err(netdev, "Failed to remove DDP profile."); | ||
359 | return -EIO; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /* Add/remove profile to/from profile list in FW */ | ||
364 | if (is_add) { | ||
365 | status = i40e_add_pinfo(&pf->hw, profile_hdr, profile_info_sec, | ||
366 | track_id); | ||
367 | if (status) { | ||
368 | netdev_err(netdev, "Failed to add DDP profile info."); | ||
369 | return -EIO; | ||
370 | } | ||
371 | } else { | ||
372 | status = i40e_del_pinfo(&pf->hw, profile_hdr, profile_info_sec, | ||
373 | track_id); | ||
374 | if (status) { | ||
375 | netdev_err(netdev, "Failed to restore DDP profile info."); | ||
376 | return -EIO; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * i40e_ddp_restore - restore previously loaded profile and remove from list | ||
385 | * @pf: PF data struct | ||
386 | * | ||
387 | * Restores previously loaded profile stored on the list in driver memory. | ||
388 | * After rolling back removes entry from the list. | ||
389 | **/ | ||
390 | static int i40e_ddp_restore(struct i40e_pf *pf) | ||
391 | { | ||
392 | struct i40e_ddp_old_profile_list *entry; | ||
393 | struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev; | ||
394 | int status = 0; | ||
395 | |||
396 | if (!list_empty(&pf->ddp_old_prof)) { | ||
397 | entry = list_first_entry(&pf->ddp_old_prof, | ||
398 | struct i40e_ddp_old_profile_list, | ||
399 | list); | ||
400 | status = i40e_ddp_load(netdev, entry->old_ddp_buf, | ||
401 | entry->old_ddp_size, false); | ||
402 | list_del(&entry->list); | ||
403 | kfree(entry); | ||
404 | } | ||
405 | return status; | ||
406 | } | ||
407 | |||
408 | /** | ||
409 | * i40e_ddp_flash - callback function for ethtool flash feature | ||
410 | * @netdev: net device structure | ||
411 | * @flash: kernel flash structure | ||
412 | * | ||
413 | * Ethtool callback function used for loading and unloading DDP profiles. | ||
414 | **/ | ||
415 | int i40e_ddp_flash(struct net_device *netdev, struct ethtool_flash *flash) | ||
416 | { | ||
417 | const struct firmware *ddp_config; | ||
418 | struct i40e_netdev_priv *np = netdev_priv(netdev); | ||
419 | struct i40e_vsi *vsi = np->vsi; | ||
420 | struct i40e_pf *pf = vsi->back; | ||
421 | int status = 0; | ||
422 | |||
423 | /* Check for valid region first */ | ||
424 | if (flash->region != I40_DDP_FLASH_REGION) { | ||
425 | netdev_err(netdev, "Requested firmware region is not recognized by this driver."); | ||
426 | return -EINVAL; | ||
427 | } | ||
428 | if (pf->hw.bus.func != 0) { | ||
429 | netdev_err(netdev, "Any DDP operation is allowed only on Phy0 NIC interface"); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | |||
433 | /* If the user supplied "-" instead of file name rollback previously | ||
434 | * stored profile. | ||
435 | */ | ||
436 | if (strncmp(flash->data, "-", 2) != 0) { | ||
437 | struct i40e_ddp_old_profile_list *list_entry; | ||
438 | char profile_name[sizeof(I40E_DDP_PROFILE_PATH) | ||
439 | + I40E_DDP_PROFILE_NAME_MAX]; | ||
440 | |||
441 | profile_name[sizeof(profile_name) - 1] = 0; | ||
442 | strncpy(profile_name, I40E_DDP_PROFILE_PATH, | ||
443 | sizeof(profile_name) - 1); | ||
444 | strncat(profile_name, flash->data, I40E_DDP_PROFILE_NAME_MAX); | ||
445 | /* Load DDP recipe. */ | ||
446 | status = request_firmware(&ddp_config, profile_name, | ||
447 | &netdev->dev); | ||
448 | if (status) { | ||
449 | netdev_err(netdev, "DDP recipe file request failed."); | ||
450 | return status; | ||
451 | } | ||
452 | |||
453 | status = i40e_ddp_load(netdev, ddp_config->data, | ||
454 | ddp_config->size, true); | ||
455 | |||
456 | if (!status) { | ||
457 | list_entry = | ||
458 | kzalloc(sizeof(struct i40e_ddp_old_profile_list) + | ||
459 | ddp_config->size, GFP_KERNEL); | ||
460 | if (!list_entry) { | ||
461 | netdev_info(netdev, "Failed to allocate memory for previous DDP profile data."); | ||
462 | netdev_info(netdev, "New profile loaded but roll-back will be impossible."); | ||
463 | } else { | ||
464 | memcpy(list_entry->old_ddp_buf, | ||
465 | ddp_config->data, ddp_config->size); | ||
466 | list_entry->old_ddp_size = ddp_config->size; | ||
467 | list_add(&list_entry->list, &pf->ddp_old_prof); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | release_firmware(ddp_config); | ||
472 | } else { | ||
473 | if (!list_empty(&pf->ddp_old_prof)) { | ||
474 | status = i40e_ddp_restore(pf); | ||
475 | } else { | ||
476 | netdev_warn(netdev, "There is no DDP profile to restore."); | ||
477 | status = -ENOENT; | ||
478 | } | ||
479 | } | ||
480 | return status; | ||
481 | } | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 7874d0ec7fb0..1f9a3ee713f9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c | |||
@@ -5171,6 +5171,7 @@ static const struct ethtool_ops i40e_ethtool_ops = { | |||
5171 | .set_link_ksettings = i40e_set_link_ksettings, | 5171 | .set_link_ksettings = i40e_set_link_ksettings, |
5172 | .get_fecparam = i40e_get_fec_param, | 5172 | .get_fecparam = i40e_get_fec_param, |
5173 | .set_fecparam = i40e_set_fec_param, | 5173 | .set_fecparam = i40e_set_fec_param, |
5174 | .flash_device = i40e_ddp_flash, | ||
5174 | }; | 5175 | }; |
5175 | 5176 | ||
5176 | void i40e_set_ethtool_ops(struct net_device *netdev) | 5177 | void i40e_set_ethtool_ops(struct net_device *netdev) |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1993b3708815..9de18aa8fa86 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c | |||
@@ -13987,6 +13987,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
13987 | 13987 | ||
13988 | INIT_LIST_HEAD(&pf->l3_flex_pit_list); | 13988 | INIT_LIST_HEAD(&pf->l3_flex_pit_list); |
13989 | INIT_LIST_HEAD(&pf->l4_flex_pit_list); | 13989 | INIT_LIST_HEAD(&pf->l4_flex_pit_list); |
13990 | INIT_LIST_HEAD(&pf->ddp_old_prof); | ||
13990 | 13991 | ||
13991 | /* set up the locks for the AQ, do this only once in probe | 13992 | /* set up the locks for the AQ, do this only once in probe |
13992 | * and destroy them only once in remove | 13993 | * and destroy them only once in remove |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index e08d754824b1..663c8bf4d3d8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h | |||
@@ -429,10 +429,16 @@ i40e_status i40e_aq_get_ddp_list(struct i40e_hw *hw, void *buff, | |||
429 | struct i40e_generic_seg_header * | 429 | struct i40e_generic_seg_header * |
430 | i40e_find_segment_in_package(u32 segment_type, | 430 | i40e_find_segment_in_package(u32 segment_type, |
431 | struct i40e_package_header *pkg_header); | 431 | struct i40e_package_header *pkg_header); |
432 | struct i40e_profile_section_header * | ||
433 | i40e_find_section_in_profile(u32 section_type, | ||
434 | struct i40e_profile_segment *profile); | ||
432 | enum i40e_status_code | 435 | enum i40e_status_code |
433 | i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg, | 436 | i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg, |
434 | u32 track_id); | 437 | u32 track_id); |
435 | enum i40e_status_code | 438 | enum i40e_status_code |
439 | i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg, | ||
440 | u32 track_id); | ||
441 | enum i40e_status_code | ||
436 | i40e_add_pinfo_to_list(struct i40e_hw *hw, | 442 | i40e_add_pinfo_to_list(struct i40e_hw *hw, |
437 | struct i40e_profile_segment *profile, | 443 | struct i40e_profile_segment *profile, |
438 | u8 *profile_info_sec, u32 track_id); | 444 | u8 *profile_info_sec, u32 track_id); |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 2781ab91ca82..79420bcc7414 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h | |||
@@ -1527,6 +1527,8 @@ struct i40e_generic_seg_header { | |||
1527 | struct i40e_metadata_segment { | 1527 | struct i40e_metadata_segment { |
1528 | struct i40e_generic_seg_header header; | 1528 | struct i40e_generic_seg_header header; |
1529 | struct i40e_ddp_version version; | 1529 | struct i40e_ddp_version version; |
1530 | #define I40E_DDP_TRACKID_RDONLY 0 | ||
1531 | #define I40E_DDP_TRACKID_INVALID 0xFFFFFFFF | ||
1530 | u32 track_id; | 1532 | u32 track_id; |
1531 | char name[I40E_DDP_NAME_SIZE]; | 1533 | char name[I40E_DDP_NAME_SIZE]; |
1532 | }; | 1534 | }; |
@@ -1555,15 +1557,36 @@ struct i40e_profile_section_header { | |||
1555 | struct { | 1557 | struct { |
1556 | #define SECTION_TYPE_INFO 0x00000010 | 1558 | #define SECTION_TYPE_INFO 0x00000010 |
1557 | #define SECTION_TYPE_MMIO 0x00000800 | 1559 | #define SECTION_TYPE_MMIO 0x00000800 |
1560 | #define SECTION_TYPE_RB_MMIO 0x00001800 | ||
1558 | #define SECTION_TYPE_AQ 0x00000801 | 1561 | #define SECTION_TYPE_AQ 0x00000801 |
1562 | #define SECTION_TYPE_RB_AQ 0x00001801 | ||
1559 | #define SECTION_TYPE_NOTE 0x80000000 | 1563 | #define SECTION_TYPE_NOTE 0x80000000 |
1560 | #define SECTION_TYPE_NAME 0x80000001 | 1564 | #define SECTION_TYPE_NAME 0x80000001 |
1565 | #define SECTION_TYPE_PROTO 0x80000002 | ||
1566 | #define SECTION_TYPE_PCTYPE 0x80000003 | ||
1567 | #define SECTION_TYPE_PTYPE 0x80000004 | ||
1561 | u32 type; | 1568 | u32 type; |
1562 | u32 offset; | 1569 | u32 offset; |
1563 | u32 size; | 1570 | u32 size; |
1564 | } section; | 1571 | } section; |
1565 | }; | 1572 | }; |
1566 | 1573 | ||
1574 | struct i40e_profile_tlv_section_record { | ||
1575 | u8 rtype; | ||
1576 | u8 type; | ||
1577 | u16 len; | ||
1578 | u8 data[12]; | ||
1579 | }; | ||
1580 | |||
1581 | /* Generic AQ section in proflie */ | ||
1582 | struct i40e_profile_aq_section { | ||
1583 | u16 opcode; | ||
1584 | u16 flags; | ||
1585 | u8 param[16]; | ||
1586 | u16 datalen; | ||
1587 | u8 data[1]; | ||
1588 | }; | ||
1589 | |||
1567 | struct i40e_profile_info { | 1590 | struct i40e_profile_info { |
1568 | u32 track_id; | 1591 | u32 track_id; |
1569 | struct i40e_ddp_version version; | 1592 | struct i40e_ddp_version version; |