Skip to content

Commit f4492db

Browse files
Greg RoseJeff Kirsher
authored andcommitted
i40e: Add NPAR BW get and set functions
We need to be able to get, set and commit permanently the NPAR partition BW configuration through configfs. These are necessary precursor functions for that feature. Also update the copyright year. Change-ID: I9d5ca160a9288145f1dd2042994028679fff55f3 Signed-off-by: Greg Rose <[email protected]> Tested-by: Jim Young <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 2bc7ee8 commit f4492db

File tree

5 files changed

+273
-1
lines changed

5 files changed

+273
-1
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ struct i40e_pf {
385385
bool ptp_tx;
386386
bool ptp_rx;
387387
u16 rss_table_size;
388+
/* These are only valid in NPAR modes */
389+
u32 npar_max_bw;
390+
u32 npar_min_bw;
388391
};
389392

390393
struct i40e_mac_filter {
@@ -732,4 +735,8 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
732735
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
733736
void i40e_ptp_init(struct i40e_pf *pf);
734737
void i40e_ptp_stop(struct i40e_pf *pf);
738+
739+
i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf);
740+
i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf);
741+
i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf);
735742
#endif /* _I40E_H_ */

drivers/net/ethernet/intel/i40e/i40e_common.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3353,6 +3353,47 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
33533353
return status;
33543354
}
33553355

3356+
/**
3357+
* i40e_aq_alternate_read
3358+
* @hw: pointer to the hardware structure
3359+
* @reg_addr0: address of first dword to be read
3360+
* @reg_val0: pointer for data read from 'reg_addr0'
3361+
* @reg_addr1: address of second dword to be read
3362+
* @reg_val1: pointer for data read from 'reg_addr1'
3363+
*
3364+
* Read one or two dwords from alternate structure. Fields are indicated
3365+
* by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer
3366+
* is not passed then only register at 'reg_addr0' is read.
3367+
*
3368+
**/
3369+
i40e_status i40e_aq_alternate_read(struct i40e_hw *hw,
3370+
u32 reg_addr0, u32 *reg_val0,
3371+
u32 reg_addr1, u32 *reg_val1)
3372+
{
3373+
struct i40e_aq_desc desc;
3374+
struct i40e_aqc_alternate_write *cmd_resp =
3375+
(struct i40e_aqc_alternate_write *)&desc.params.raw;
3376+
i40e_status status;
3377+
3378+
if (!reg_val0)
3379+
return I40E_ERR_PARAM;
3380+
3381+
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_read);
3382+
cmd_resp->address0 = cpu_to_le32(reg_addr0);
3383+
cmd_resp->address1 = cpu_to_le32(reg_addr1);
3384+
3385+
status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL);
3386+
3387+
if (!status) {
3388+
*reg_val0 = le32_to_cpu(cmd_resp->data0);
3389+
3390+
if (reg_val1)
3391+
*reg_val1 = le32_to_cpu(cmd_resp->data1);
3392+
}
3393+
3394+
return status;
3395+
}
3396+
33563397
/**
33573398
* i40e_aq_resume_port_tx
33583399
* @hw: pointer to the hardware structure
@@ -3417,3 +3458,79 @@ void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status)
34173458
break;
34183459
}
34193460
}
3461+
3462+
/**
3463+
* i40e_read_bw_from_alt_ram
3464+
* @hw: pointer to the hardware structure
3465+
* @max_bw: pointer for max_bw read
3466+
* @min_bw: pointer for min_bw read
3467+
* @min_valid: pointer for bool that is true if min_bw is a valid value
3468+
* @max_valid: pointer for bool that is true if max_bw is a valid value
3469+
*
3470+
* Read bw from the alternate ram for the given pf
3471+
**/
3472+
i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw,
3473+
u32 *max_bw, u32 *min_bw,
3474+
bool *min_valid, bool *max_valid)
3475+
{
3476+
i40e_status status;
3477+
u32 max_bw_addr, min_bw_addr;
3478+
3479+
/* Calculate the address of the min/max bw registers */
3480+
max_bw_addr = I40E_ALT_STRUCT_FIRST_PF_OFFSET +
3481+
I40E_ALT_STRUCT_MAX_BW_OFFSET +
3482+
(I40E_ALT_STRUCT_DWORDS_PER_PF * hw->pf_id);
3483+
min_bw_addr = I40E_ALT_STRUCT_FIRST_PF_OFFSET +
3484+
I40E_ALT_STRUCT_MIN_BW_OFFSET +
3485+
(I40E_ALT_STRUCT_DWORDS_PER_PF * hw->pf_id);
3486+
3487+
/* Read the bandwidths from alt ram */
3488+
status = i40e_aq_alternate_read(hw, max_bw_addr, max_bw,
3489+
min_bw_addr, min_bw);
3490+
3491+
if (*min_bw & I40E_ALT_BW_VALID_MASK)
3492+
*min_valid = true;
3493+
else
3494+
*min_valid = false;
3495+
3496+
if (*max_bw & I40E_ALT_BW_VALID_MASK)
3497+
*max_valid = true;
3498+
else
3499+
*max_valid = false;
3500+
3501+
return status;
3502+
}
3503+
3504+
/**
3505+
* i40e_aq_configure_partition_bw
3506+
* @hw: pointer to the hardware structure
3507+
* @bw_data: Buffer holding valid pfs and bw limits
3508+
* @cmd_details: pointer to command details
3509+
*
3510+
* Configure partitions guaranteed/max bw
3511+
**/
3512+
i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
3513+
struct i40e_aqc_configure_partition_bw_data *bw_data,
3514+
struct i40e_asq_cmd_details *cmd_details)
3515+
{
3516+
i40e_status status;
3517+
struct i40e_aq_desc desc;
3518+
u16 bwd_size = sizeof(*bw_data);
3519+
3520+
i40e_fill_default_direct_cmd_desc(&desc,
3521+
i40e_aqc_opc_configure_partition_bw);
3522+
3523+
/* Indirect command */
3524+
desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
3525+
desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_RD);
3526+
3527+
if (bwd_size > I40E_AQ_LARGE_BUF)
3528+
desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
3529+
3530+
desc.datalen = cpu_to_le16(bwd_size);
3531+
3532+
status = i40e_asq_send_command(hw, &desc, bw_data, bwd_size,
3533+
cmd_details);
3534+
3535+
return status;
3536+
}

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7253,6 +7253,128 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
72537253
return pf->rss_size;
72547254
}
72557255

7256+
/**
7257+
* i40e_get_npar_bw_setting - Retrieve BW settings for this PF partition
7258+
* @pf: board private structure
7259+
**/
7260+
i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf)
7261+
{
7262+
i40e_status status;
7263+
bool min_valid, max_valid;
7264+
u32 max_bw, min_bw;
7265+
7266+
status = i40e_read_bw_from_alt_ram(&pf->hw, &max_bw, &min_bw,
7267+
&min_valid, &max_valid);
7268+
7269+
if (!status) {
7270+
if (min_valid)
7271+
pf->npar_min_bw = min_bw;
7272+
if (max_valid)
7273+
pf->npar_max_bw = max_bw;
7274+
}
7275+
7276+
return status;
7277+
}
7278+
7279+
/**
7280+
* i40e_set_npar_bw_setting - Set BW settings for this PF partition
7281+
* @pf: board private structure
7282+
**/
7283+
i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf)
7284+
{
7285+
struct i40e_aqc_configure_partition_bw_data bw_data;
7286+
i40e_status status;
7287+
7288+
/* Set the valid bit for this pf */
7289+
bw_data.pf_valid_bits = cpu_to_le16(1 << pf->hw.pf_id);
7290+
bw_data.max_bw[pf->hw.pf_id] = pf->npar_max_bw & I40E_ALT_BW_VALUE_MASK;
7291+
bw_data.min_bw[pf->hw.pf_id] = pf->npar_min_bw & I40E_ALT_BW_VALUE_MASK;
7292+
7293+
/* Set the new bandwidths */
7294+
status = i40e_aq_configure_partition_bw(&pf->hw, &bw_data, NULL);
7295+
7296+
return status;
7297+
}
7298+
7299+
/**
7300+
* i40e_commit_npar_bw_setting - Commit BW settings for this PF partition
7301+
* @pf: board private structure
7302+
**/
7303+
i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf)
7304+
{
7305+
/* Commit temporary BW setting to permanent NVM image */
7306+
enum i40e_admin_queue_err last_aq_status;
7307+
i40e_status ret;
7308+
u16 nvm_word;
7309+
7310+
if (pf->hw.partition_id != 1) {
7311+
dev_info(&pf->pdev->dev,
7312+
"Commit BW only works on partition 1! This is partition %d",
7313+
pf->hw.partition_id);
7314+
ret = I40E_NOT_SUPPORTED;
7315+
goto bw_commit_out;
7316+
}
7317+
7318+
/* Acquire NVM for read access */
7319+
ret = i40e_acquire_nvm(&pf->hw, I40E_RESOURCE_READ);
7320+
last_aq_status = pf->hw.aq.asq_last_status;
7321+
if (ret) {
7322+
dev_info(&pf->pdev->dev,
7323+
"Cannot acquire NVM for read access, err %d: aq_err %d\n",
7324+
ret, last_aq_status);
7325+
goto bw_commit_out;
7326+
}
7327+
7328+
/* Read word 0x10 of NVM - SW compatibility word 1 */
7329+
ret = i40e_aq_read_nvm(&pf->hw,
7330+
I40E_SR_NVM_CONTROL_WORD,
7331+
0x10, sizeof(nvm_word), &nvm_word,
7332+
false, NULL);
7333+
/* Save off last admin queue command status before releasing
7334+
* the NVM
7335+
*/
7336+
last_aq_status = pf->hw.aq.asq_last_status;
7337+
i40e_release_nvm(&pf->hw);
7338+
if (ret) {
7339+
dev_info(&pf->pdev->dev, "NVM read error, err %d aq_err %d\n",
7340+
ret, last_aq_status);
7341+
goto bw_commit_out;
7342+
}
7343+
7344+
/* Wait a bit for NVM release to complete */
7345+
msleep(50);
7346+
7347+
/* Acquire NVM for write access */
7348+
ret = i40e_acquire_nvm(&pf->hw, I40E_RESOURCE_WRITE);
7349+
last_aq_status = pf->hw.aq.asq_last_status;
7350+
if (ret) {
7351+
dev_info(&pf->pdev->dev,
7352+
"Cannot acquire NVM for write access, err %d: aq_err %d\n",
7353+
ret, last_aq_status);
7354+
goto bw_commit_out;
7355+
}
7356+
/* Write it back out unchanged to initiate update NVM,
7357+
* which will force a write of the shadow (alt) RAM to
7358+
* the NVM - thus storing the bandwidth values permanently.
7359+
*/
7360+
ret = i40e_aq_update_nvm(&pf->hw,
7361+
I40E_SR_NVM_CONTROL_WORD,
7362+
0x10, sizeof(nvm_word),
7363+
&nvm_word, true, NULL);
7364+
/* Save off last admin queue command status before releasing
7365+
* the NVM
7366+
*/
7367+
last_aq_status = pf->hw.aq.asq_last_status;
7368+
i40e_release_nvm(&pf->hw);
7369+
if (ret)
7370+
dev_info(&pf->pdev->dev,
7371+
"BW settings NOT SAVED, err %d aq_err %d\n",
7372+
ret, last_aq_status);
7373+
bw_commit_out:
7374+
7375+
return ret;
7376+
}
7377+
72567378
/**
72577379
* i40e_sw_init - Initialize general software structures (struct i40e_pf)
72587380
* @pf: board private structure to initialize
@@ -7306,6 +7428,13 @@ static int i40e_sw_init(struct i40e_pf *pf)
73067428
if (pf->hw.func_caps.npar_enable || pf->hw.func_caps.mfp_mode_1) {
73077429
pf->flags |= I40E_FLAG_MFP_ENABLED;
73087430
dev_info(&pf->pdev->dev, "MFP mode Enabled\n");
7431+
if (i40e_get_npar_bw_setting(pf))
7432+
dev_warn(&pf->pdev->dev,
7433+
"Could not get NPAR bw settings\n");
7434+
else
7435+
dev_info(&pf->pdev->dev,
7436+
"Min BW = %8.8x, Max BW = %8.8x\n",
7437+
pf->npar_min_bw, pf->npar_max_bw);
73097438
}
73107439

73117440
/* FW/NVM is not yet fixed in this regard */

drivers/net/ethernet/intel/i40e/i40e_prototype.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*******************************************************************************
22
*
33
* Intel Ethernet Controller XL710 Family Linux Driver
4-
* Copyright(c) 2013 - 2014 Intel Corporation.
4+
* Copyright(c) 2013 - 2015 Intel Corporation.
55
*
66
* This program is free software; you can redistribute it and/or modify it
77
* under the terms and conditions of the GNU General Public License,
@@ -246,6 +246,12 @@ void i40e_clear_hw(struct i40e_hw *hw);
246246
void i40e_clear_pxe_mode(struct i40e_hw *hw);
247247
bool i40e_get_link_status(struct i40e_hw *hw);
248248
i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
249+
i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw,
250+
u32 *max_bw, u32 *min_bw, bool *min_valid,
251+
bool *max_valid);
252+
i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
253+
struct i40e_aqc_configure_partition_bw_data *bw_data,
254+
struct i40e_asq_cmd_details *cmd_details);
249255
i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
250256
i40e_status i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num,
251257
u32 pba_num_size);

drivers/net/ethernet/intel/i40e/i40e_type.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,19 @@ struct i40e_lldp_variables {
14011401
u16 crc8;
14021402
};
14031403

1404+
/* Offsets into Alternate Ram */
1405+
#define I40E_ALT_STRUCT_FIRST_PF_OFFSET 0 /* in dwords */
1406+
#define I40E_ALT_STRUCT_DWORDS_PER_PF 64 /* in dwords */
1407+
#define I40E_ALT_STRUCT_OUTER_VLAN_TAG_OFFSET 0xD /* in dwords */
1408+
#define I40E_ALT_STRUCT_USER_PRIORITY_OFFSET 0xC /* in dwords */
1409+
#define I40E_ALT_STRUCT_MIN_BW_OFFSET 0xE /* in dwords */
1410+
#define I40E_ALT_STRUCT_MAX_BW_OFFSET 0xF /* in dwords */
1411+
1412+
/* Alternate Ram Bandwidth Masks */
1413+
#define I40E_ALT_BW_VALUE_MASK 0xFF
1414+
#define I40E_ALT_BW_RELATIVE_MASK 0x40000000
1415+
#define I40E_ALT_BW_VALID_MASK 0x80000000
1416+
14041417
/* RSS Hash Table Size */
14051418
#define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000
14061419
#endif /* _I40E_TYPE_H_ */

0 commit comments

Comments
 (0)