aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/i40e/i40e_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_common.c')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c253
1 files changed, 231 insertions, 22 deletions
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 **/
5475struct i40e_profile_section_header *
5476i40e_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 **/
5504static enum
5505i40e_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 */
5551static enum i40e_status_code
5552i40e_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 */
5679enum i40e_status_code
5680i40e_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 }