Commit c1c27fb9 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2014-06-26

This series contains updates to i40e and i40evf.

Kamil provides a cleanup patch to i40e where we do not need to acquire the
NVM for shadow RAM checksum calculation, since we only read the shadow RAM
through SRCTL register.

Paul provides a fix for handling HMC for big endian architectures for i40e
and i40evf.

Mitch provides four cleanup and fixes for i40evf.  Fix an issue where if
the VF driver fails to complete early init, then rmmod can cause a softlock
when the driver tries to stop a watchdog timer that never got initialized.
So add a check to see if the timer is actually initialized before stopping
it.  Make the function i40evf_send_api_ver() return more useful information,
instead of just returning -EIO by propagating firmware errors back to the
caller and log a message if the PF sends an invalid reply.  Fix up a log
message that was missing a word, which makes the log message more readable.
Fix an initialization failure if many VFs are instantiated at the same time
and the VF module is autoloaded by simply resending firmware request if
there is no response the first time.

Jacob does a rename of the function i40e_ptp_enable() to
i40e_ptp_feature_enable(), like he did for ixgbe, to reduce possible
confusion and ambugity in the purpose of the function.  Does follow on
PTP work on i40e, like he did for ixgbe, by breaking the PTP hardware
control from the ioctl command for timestamping mode.  By doing this,
we can maintain state about the 1588 timestamping mode and properly
re-enable to the last known mode during a re-initialization of 1588 bits.

Anjali cleans up the i40e driver where TCP-IPv4 filters were being added
twice, which seems to be left over from when we had to add two PTYPEs for
one filter.  Fixes the flow director sideband logic to detect when there
is a full flow director table.  Also fixes the programming of FDIR where
a couple of fields in the descriptor setup that were not being
programmed, which left the opportunity for stale data to be pushed as
part of the descriptor next time it was used.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0ff9275a 99753ea6
...@@ -154,7 +154,7 @@ struct i40e_lump_tracking { ...@@ -154,7 +154,7 @@ struct i40e_lump_tracking {
#define I40E_DEFAULT_ATR_SAMPLE_RATE 20 #define I40E_DEFAULT_ATR_SAMPLE_RATE 20
#define I40E_FDIR_MAX_RAW_PACKET_SIZE 512 #define I40E_FDIR_MAX_RAW_PACKET_SIZE 512
#define I40E_FDIR_BUFFER_FULL_MARGIN 10 #define I40E_FDIR_BUFFER_FULL_MARGIN 10
#define I40E_FDIR_BUFFER_HEAD_ROOM 200 #define I40E_FDIR_BUFFER_HEAD_ROOM 32
enum i40e_fd_stat_idx { enum i40e_fd_stat_idx {
I40E_FD_STAT_ATR, I40E_FD_STAT_ATR,
...@@ -582,6 +582,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi, ...@@ -582,6 +582,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add); struct i40e_fdir_filter *input, bool add);
void i40e_fdir_check_and_reenable(struct i40e_pf *pf); void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
int i40e_get_current_fd_count(struct i40e_pf *pf); int i40e_get_current_fd_count(struct i40e_pf *pf);
int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features); bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
void i40e_set_ethtool_ops(struct net_device *netdev); void i40e_set_ethtool_ops(struct net_device *netdev);
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
......
...@@ -1743,6 +1743,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ...@@ -1743,6 +1743,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false); i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false);
} else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) { } else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) {
i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true); i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true);
} else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) {
dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n",
i40e_get_current_fd_count(pf));
} else if (strncmp(cmd_buf, "lldp", 4) == 0) { } else if (strncmp(cmd_buf, "lldp", 4) == 0) {
if (strncmp(&cmd_buf[5], "stop", 4) == 0) { if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
int ret; int ret;
...@@ -1962,6 +1965,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ...@@ -1962,6 +1965,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, " rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n"); dev_info(&pf->pdev->dev, " rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
dev_info(&pf->pdev->dev, " fd-atr off\n"); dev_info(&pf->pdev->dev, " fd-atr off\n");
dev_info(&pf->pdev->dev, " fd-atr on\n"); dev_info(&pf->pdev->dev, " fd-atr on\n");
dev_info(&pf->pdev->dev, " fd current cnt");
dev_info(&pf->pdev->dev, " lldp start\n"); dev_info(&pf->pdev->dev, " lldp start\n");
dev_info(&pf->pdev->dev, " lldp stop\n"); dev_info(&pf->pdev->dev, " lldp stop\n");
dev_info(&pf->pdev->dev, " lldp get local\n"); dev_info(&pf->pdev->dev, " lldp get local\n");
......
...@@ -746,6 +746,194 @@ static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = { ...@@ -746,6 +746,194 @@ static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = {
{ 0 } { 0 }
}; };
/**
* i40e_write_byte - replace HMC context byte
* @hmc_bits: pointer to the HMC memory
* @ce_info: a description of the struct to be read from
* @src: the struct to be read from
**/
static void i40e_write_byte(u8 *hmc_bits,
struct i40e_context_ele *ce_info,
u8 *src)
{
u8 src_byte, dest_byte, mask;
u8 *from, *dest;
u16 shift_width;
/* copy from the next struct field */
from = src + ce_info->offset;
/* prepare the bits and mask */
shift_width = ce_info->lsb % 8;
mask = ((u8)1 << ce_info->width) - 1;
src_byte = *from;
src_byte &= mask;
/* shift to correct alignment */
mask <<= shift_width;
src_byte <<= shift_width;
/* get the current bits from the target bit string */
dest = hmc_bits + (ce_info->lsb / 8);
memcpy(&dest_byte, dest, sizeof(dest_byte));
dest_byte &= ~mask; /* get the bits not changing */
dest_byte |= src_byte; /* add in the new bits */
/* put it all back */
memcpy(dest, &dest_byte, sizeof(dest_byte));
}
/**
* i40e_write_word - replace HMC context word
* @hmc_bits: pointer to the HMC memory
* @ce_info: a description of the struct to be read from
* @src: the struct to be read from
**/
static void i40e_write_word(u8 *hmc_bits,
struct i40e_context_ele *ce_info,
u8 *src)
{
u16 src_word, mask;
u8 *from, *dest;
u16 shift_width;
__le16 dest_word;
/* copy from the next struct field */
from = src + ce_info->offset;
/* prepare the bits and mask */
shift_width = ce_info->lsb % 8;
mask = ((u16)1 << ce_info->width) - 1;
/* don't swizzle the bits until after the mask because the mask bits
* will be in a different bit position on big endian machines
*/
src_word = *(u16 *)from;
src_word &= mask;
/* shift to correct alignment */
mask <<= shift_width;
src_word <<= shift_width;
/* get the current bits from the target bit string */
dest = hmc_bits + (ce_info->lsb / 8);
memcpy(&dest_word, dest, sizeof(dest_word));
dest_word &= ~(cpu_to_le16(mask)); /* get the bits not changing */
dest_word |= cpu_to_le16(src_word); /* add in the new bits */
/* put it all back */
memcpy(dest, &dest_word, sizeof(dest_word));
}
/**
* i40e_write_dword - replace HMC context dword
* @hmc_bits: pointer to the HMC memory
* @ce_info: a description of the struct to be read from
* @src: the struct to be read from
**/
static void i40e_write_dword(u8 *hmc_bits,
struct i40e_context_ele *ce_info,
u8 *src)
{
u32 src_dword, mask;
u8 *from, *dest;
u16 shift_width;
__le32 dest_dword;
/* copy from the next struct field */
from = src + ce_info->offset;
/* prepare the bits and mask */
shift_width = ce_info->lsb % 8;
/* if the field width is exactly 32 on an x86 machine, then the shift
* operation will not work because the SHL instructions count is masked
* to 5 bits so the shift will do nothing
*/
if (ce_info->width < 32)
mask = ((u32)1 << ce_info->width) - 1;
else
mask = -1;
/* don't swizzle the bits until after the mask because the mask bits
* will be in a different bit position on big endian machines
*/
src_dword = *(u32 *)from;
src_dword &= mask;
/* shift to correct alignment */
mask <<= shift_width;
src_dword <<= shift_width;
/* get the current bits from the target bit string */
dest = hmc_bits + (ce_info->lsb / 8);
memcpy(&dest_dword, dest, sizeof(dest_dword));
dest_dword &= ~(cpu_to_le32(mask)); /* get the bits not changing */
dest_dword |= cpu_to_le32(src_dword); /* add in the new bits */
/* put it all back */
memcpy(dest, &dest_dword, sizeof(dest_dword));
}
/**
* i40e_write_qword - replace HMC context qword
* @hmc_bits: pointer to the HMC memory
* @ce_info: a description of the struct to be read from
* @src: the struct to be read from
**/
static void i40e_write_qword(u8 *hmc_bits,
struct i40e_context_ele *ce_info,
u8 *src)
{
u64 src_qword, mask;
u8 *from, *dest;
u16 shift_width;
__le64 dest_qword;
/* copy from the next struct field */
from = src + ce_info->offset;
/* prepare the bits and mask */
shift_width = ce_info->lsb % 8;
/* if the field width is exactly 64 on an x86 machine, then the shift
* operation will not work because the SHL instructions count is masked
* to 6 bits so the shift will do nothing
*/
if (ce_info->width < 64)
mask = ((u64)1 << ce_info->width) - 1;
else
mask = -1;
/* don't swizzle the bits until after the mask because the mask bits
* will be in a different bit position on big endian machines
*/
src_qword = *(u64 *)from;
src_qword &= mask;
/* shift to correct alignment */
mask <<= shift_width;
src_qword <<= shift_width;
/* get the current bits from the target bit string */
dest = hmc_bits + (ce_info->lsb / 8);
memcpy(&dest_qword, dest, sizeof(dest_qword));
dest_qword &= ~(cpu_to_le64(mask)); /* get the bits not changing */
dest_qword |= cpu_to_le64(src_qword); /* add in the new bits */
/* put it all back */
memcpy(dest, &dest_qword, sizeof(dest_qword));
}
/** /**
* i40e_clear_hmc_context - zero out the HMC context bits * i40e_clear_hmc_context - zero out the HMC context bits
* @hw: the hardware struct * @hw: the hardware struct
...@@ -772,71 +960,28 @@ static i40e_status i40e_set_hmc_context(u8 *context_bytes, ...@@ -772,71 +960,28 @@ static i40e_status i40e_set_hmc_context(u8 *context_bytes,
struct i40e_context_ele *ce_info, struct i40e_context_ele *ce_info,
u8 *dest) u8 *dest)
{ {
u16 shift_width;
u64 bitfield;
u8 hi_byte;
u8 hi_mask;
u64 t_bits;
u64 mask;
u8 *p;
int f; int f;
for (f = 0; ce_info[f].width != 0; f++) { for (f = 0; ce_info[f].width != 0; f++) {
/* clear out the field */
bitfield = 0;
/* copy from the next struct field */ /* we have to deal with each element of the HMC using the
p = dest + ce_info[f].offset; * correct size so that we are correct regardless of the
* endianness of the machine
*/
switch (ce_info[f].size_of) { switch (ce_info[f].size_of) {
case 1: case 1:
bitfield = *p; i40e_write_byte(context_bytes, &ce_info[f], dest);
break; break;
case 2: case 2:
bitfield = cpu_to_le16(*(u16 *)p); i40e_write_word(context_bytes, &ce_info[f], dest);
break; break;
case 4: case 4:
bitfield = cpu_to_le32(*(u32 *)p); i40e_write_dword(context_bytes, &ce_info[f], dest);
break; break;
case 8: case 8:
bitfield = cpu_to_le64(*(u64 *)p); i40e_write_qword(context_bytes, &ce_info[f], dest);
break; break;
} }
/* prepare the bits and mask */
shift_width = ce_info[f].lsb % 8;
mask = ((u64)1 << ce_info[f].width) - 1;
/* save upper bytes for special case */
hi_mask = (u8)((mask >> 56) & 0xff);
hi_byte = (u8)((bitfield >> 56) & 0xff);
/* shift to correct alignment */
mask <<= shift_width;
bitfield <<= shift_width;
/* get the current bits from the target bit string */
p = context_bytes + (ce_info[f].lsb / 8);
memcpy(&t_bits, p, sizeof(u64));
t_bits &= ~mask; /* get the bits not changing */
t_bits |= bitfield; /* add in the new bits */
/* put it all back */
memcpy(p, &t_bits, sizeof(u64));
/* deal with the special case if needed
* example: 62 bit field that starts in bit 5 of first byte
* will overlap 3 bits into byte 9
*/
if ((shift_width + ce_info[f].width) > 64) {
u8 byte;
hi_mask >>= (8 - shift_width);
hi_byte >>= (8 - shift_width);
byte = p[8] & ~hi_mask; /* get the bits not changing */
byte |= hi_byte; /* add in the new bits */
p[8] = byte; /* put it back */
}
} }
return 0; return 0;
......
...@@ -32,16 +32,22 @@ struct i40e_hw; ...@@ -32,16 +32,22 @@ struct i40e_hw;
/* HMC element context information */ /* HMC element context information */
/* Rx queue context data */ /* Rx queue context data
*
* The sizes of the variables may be larger than needed due to crossing byte
* boundaries. If we do not have the width of the variable set to the correct
* size then we could end up shifting bits off the top of the variable when the
* variable is at the top of a byte and crosses over into the next byte.
*/
struct i40e_hmc_obj_rxq { struct i40e_hmc_obj_rxq {
u16 head; u16 head;
u8 cpuid; u16 cpuid; /* bigger than needed, see above for reason */
u64 base; u64 base;
u16 qlen; u16 qlen;
#define I40E_RXQ_CTX_DBUFF_SHIFT 7 #define I40E_RXQ_CTX_DBUFF_SHIFT 7
u8 dbuff; u16 dbuff; /* bigger than needed, see above for reason */
#define I40E_RXQ_CTX_HBUFF_SHIFT 6 #define I40E_RXQ_CTX_HBUFF_SHIFT 6
u8 hbuff; u16 hbuff; /* bigger than needed, see above for reason */
u8 dtype; u8 dtype;
u8 dsize; u8 dsize;
u8 crcstrip; u8 crcstrip;
...@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq { ...@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
u8 hsplit_0; u8 hsplit_0;
u8 hsplit_1; u8 hsplit_1;
u8 showiv; u8 showiv;
u16 rxmax; u32 rxmax; /* bigger than needed, see above for reason */
u8 tphrdesc_ena; u8 tphrdesc_ena;
u8 tphwdesc_ena; u8 tphwdesc_ena;
u8 tphdata_ena; u8 tphdata_ena;
u8 tphhead_ena; u8 tphhead_ena;
u8 lrxqthresh; u16 lrxqthresh; /* bigger than needed, see above for reason */
u8 prefena; /* NOTE: normally must be set to 1 at init */ u8 prefena; /* NOTE: normally must be set to 1 at init */
}; };
/* Tx queue context data */ /* Tx queue context data
*
* The sizes of the variables may be larger than needed due to crossing byte
* boundaries. If we do not have the width of the variable set to the correct
* size then we could end up shifting bits off the top of the variable when the
* variable is at the top of a byte and crosses over into the next byte.
*/
struct i40e_hmc_obj_txq { struct i40e_hmc_obj_txq {
u16 head; u16 head;
u8 new_context; u8 new_context;
...@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq { ...@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
u8 fd_ena; u8 fd_ena;
u8 alt_vlan_ena; u8 alt_vlan_ena;
u16 thead_wb; u16 thead_wb;
u16 cpuid; u8 cpuid;
u8 head_wb_ena; u8 head_wb_ena;
u16 qlen; u16 qlen;
u8 tphrdesc_ena; u8 tphrdesc_ena;
......
...@@ -4944,7 +4944,20 @@ static void i40e_service_event_complete(struct i40e_pf *pf) ...@@ -4944,7 +4944,20 @@ static void i40e_service_event_complete(struct i40e_pf *pf)
} }
/** /**
* i40e_get_current_fd_count - Get the count of FD filters programmed in the HW * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
* @pf: board private structure
**/
int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
{
int val, fcnt_prog;
val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK);
return fcnt_prog;
}
/**
* i40e_get_current_fd_count - Get the count of total FD filters programmed
* @pf: board private structure * @pf: board private structure
**/ **/
int i40e_get_current_fd_count(struct i40e_pf *pf) int i40e_get_current_fd_count(struct i40e_pf *pf)
...@@ -4956,7 +4969,6 @@ int i40e_get_current_fd_count(struct i40e_pf *pf) ...@@ -4956,7 +4969,6 @@ int i40e_get_current_fd_count(struct i40e_pf *pf)
I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
return fcnt_prog; return fcnt_prog;
} }
/** /**
* i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled * i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
* @pf: board private structure * @pf: board private structure
...@@ -4971,8 +4983,8 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf) ...@@ -4971,8 +4983,8 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) && if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
(pf->flags & I40E_FLAG_FD_SB_ENABLED)) (pf->flags & I40E_FLAG_FD_SB_ENABLED))
return; return;
fcnt_prog = i40e_get_current_fd_count(pf); fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
fcnt_avail = i40e_get_fd_cnt_all(pf); fcnt_avail = pf->fdir_pf_filter_count;
if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) { if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) {
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) && if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
(pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) { (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) {
......
...@@ -324,13 +324,9 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, ...@@ -324,13 +324,9 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 checksum_sr = 0; u16 checksum_sr = 0;
u16 checksum_local = 0; u16 checksum_local = 0;
ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
if (ret_code)
goto i40e_validate_nvm_checksum_exit;
ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
if (ret_code) if (ret_code)
goto i40e_validate_nvm_checksum_free; goto i40e_validate_nvm_checksum_exit;
/* Do not use i40e_read_nvm_word() because we do not want to take /* Do not use i40e_read_nvm_word() because we do not want to take
* the synchronization semaphores twice here. * the synchronization semaphores twice here.
...@@ -347,9 +343,6 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, ...@@ -347,9 +343,6 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
if (checksum) if (checksum)
*checksum = checksum_local; *checksum = checksum_local;
i40e_validate_nvm_checksum_free:
i40e_release_nvm(hw);
i40e_validate_nvm_checksum_exit: i40e_validate_nvm_checksum_exit:
return ret_code; return ret_code;
} }
...@@ -216,7 +216,7 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp, ...@@ -216,7 +216,7 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
} }
/** /**
* i40e_ptp_enable - Enable/disable ancillary features of the PHC subsystem * i40e_ptp_feature_enable - Enable/disable ancillary features of the PHC subsystem
* @ptp: The PTP clock structure * @ptp: The PTP clock structure
* @rq: The requested feature to change * @rq: The requested feature to change
* @on: Enable/disable flag * @on: Enable/disable flag
...@@ -224,7 +224,7 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp, ...@@ -224,7 +224,7 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
* The XL710 does not support any of the ancillary features of the PHC * The XL710 does not support any of the ancillary features of the PHC
* subsystem, so this function may just return. * subsystem, so this function may just return.
**/ **/
static int i40e_ptp_enable(struct ptp_clock_info *ptp, static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on) struct ptp_clock_request *rq, int on)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -423,28 +423,23 @@ int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr) ...@@ -423,28 +423,23 @@ int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
} }
/** /**
* i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping * i40e_ptp_set_timestamp_mode - setup hardware for requested timestamp mode
* @pf: Board private structure * @pf: Board private structure
* @ifreq: ioctl data * @config: hwtstamp settings requested or saved
* *
* Respond to the user filter requests and make the appropriate hardware * Control hardware registers to enter the specific mode requested by the
* changes here. The XL710 cannot support splitting of the Tx/Rx timestamping * user. Also used during reset path to ensure that timestamp settings are
* logic, so keep track in software of whether to indicate these timestamps * maintained.
* or not.
* *
* It is permissible to "upgrade" the user request to a broader filter, as long * Note: modifies config in place, and may update the requested mode to be
* as the user receives the timestamps they care about and the user is notified * more broad if the specific filter is not directly supported.
* the filter has been broadened.
**/ **/
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr) static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
struct hwtstamp_config *config)
{ {
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct hwtstamp_config *config = &pf->tstamp_config;
u32 pf_id, tsyntype, regval; u32 pf_id, tsyntype, regval;
if (copy_from_user(config, ifr->ifr_data, sizeof(*config)))
return -EFAULT;
/* Reserved for future extensions. */ /* Reserved for future extensions. */
if (config->flags) if (config->flags)
return -EINVAL; return -EINVAL;
...@@ -535,23 +530,59 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr) ...@@ -535,23 +530,59 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
wr32(hw, I40E_PRTTSYN_CTL1, regval); wr32(hw, I40E_PRTTSYN_CTL1, regval);
} }
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? return 0;
}
/**
* i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
* @pf: Board private structure
* @ifreq: ioctl data
*
* Respond to the user filter requests and make the appropriate hardware
* changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
* logic, so keep track in software of whether to indicate these timestamps
* or not.
*
* It is permissible to "upgrade" the user request to a broader filter, as long
* as the user receives the timestamps they care about and the user is notified
* the filter has been broadened.
**/
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
{
struct hwtstamp_config config;
int err;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
err = i40e_ptp_set_timestamp_mode(pf, &config);
if (err)
return err;
/* save these settings for future reference */
pf->tstamp_config = config;
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-EFAULT : 0; -EFAULT : 0;
} }
/** /**
* i40e_ptp_init - Initialize the 1588 support and register the PHC * i40e_ptp_create_clock - Create PTP clock device for userspace
* @pf: Board private structure * @pf: Board private structure
* *
* This function registers the device clock as a PHC. If it is successful, it * This function creates a new PTP clock device. It only creates one if we
* starts the clock in the hardware. * don't already have one, so it is safe to call. Will return error if it
* can't create one, but success if we already have a device. Should be used
* by i40e_ptp_init to create clock initially, and prevent global resets from
* creating new clock devices.
**/ **/
void i40e_ptp_init(struct i40e_pf *pf) static long i40e_ptp_create_clock(struct i40e_pf *pf)
{ {
struct i40e_hw *hw = &pf->hw; /* no need to create a clock device if we already have one */
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev; if (!IS_ERR_OR_NULL(pf->ptp_clock))
return 0;
strncpy(pf->ptp_caps.name, "i40e", sizeof(pf->ptp_caps.name)); strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
pf->ptp_caps.owner = THIS_MODULE; pf->ptp_caps.owner = THIS_MODULE;
pf->ptp_caps.max_adj = 999999999; pf->ptp_caps.max_adj = 999999999;
pf->ptp_caps.n_ext_ts = 0; pf->ptp_caps.n_ext_ts = 0;
...@@ -560,11 +591,46 @@ void i40e_ptp_init(struct i40e_pf *pf) ...@@ -560,11 +591,46 @@ void i40e_ptp_init(struct i40e_pf *pf)
pf->ptp_caps.adjtime = i40e_ptp_adjtime; pf->ptp_caps.adjtime = i40e_ptp_adjtime;
pf->ptp_caps.gettime = i40e_ptp_gettime; pf->ptp_caps.gettime = i40e_ptp_gettime;
pf->ptp_caps.settime = i40e_ptp_settime; pf->ptp_caps.settime = i40e_ptp_settime;
pf->ptp_caps.enable = i40e_ptp_enable; pf->ptp_caps.enable = i40e_ptp_feature_enable;
/* Attempt to register the clock before enabling the hardware. */ /* Attempt to register the clock before enabling the hardware. */
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev); pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
if (IS_ERR(pf->ptp_clock)) { if (IS_ERR(pf->ptp_clock)) {
return PTR_ERR(pf->ptp_clock);
}
/* clear the hwtstamp settings here during clock create, instead of
* during regular init, so that we can maintain settings across a
* reset or suspend.
*/
pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
return 0;
}
/**
* i40e_ptp_init - Initialize the 1588 support after device probe or reset
* @pf: Board private structure
*
* This function sets device up for 1588 support. The first time it is run, it
* will create a PHC clock device. It does not create a clock device if one
* already exists. It also reconfigures the device after a reset.
**/
void i40e_ptp_init(struct i40e_pf *pf)
{
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
struct i40e_hw *hw = &pf->hw;
long err;
/* we have to initialize the lock first, since we can't control
* when the user will enter the PHC device entry points
*/
spin_lock_init(&pf->tmreg_lock);
/* ensure we have a clock device */
err = i40e_ptp_create_clock(pf);
if (err) {
pf->ptp_clock = NULL; pf->ptp_clock = NULL;
dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n", dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
__func__); __func__);
...@@ -572,8 +638,6 @@ void i40e_ptp_init(struct i40e_pf *pf) ...@@ -572,8 +638,6 @@ void i40e_ptp_init(struct i40e_pf *pf)
struct timespec ts; struct timespec ts;
u32 regval; u32 regval;
spin_lock_init(&pf->tmreg_lock);
dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__, dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
netdev->name); netdev->name);
pf->flags |= I40E_FLAG_PTP; pf->flags |= I40E_FLAG_PTP;
...@@ -589,8 +653,8 @@ void i40e_ptp_init(struct i40e_pf *pf) ...@@ -589,8 +653,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
/* Set the increment value per clock tick. */ /* Set the increment value per clock tick. */
i40e_ptp_set_increment(pf); i40e_ptp_set_increment(pf);
/* reset the tstamp_config */ /* reset timestamping mode */
memset(&pf->tstamp_config, 0, sizeof(pf->tstamp_config)); i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
/* Set the clock value. */ /* Set the clock value. */
ts = ktime_to_timespec(ktime_get_real()); ts = ktime_to_timespec(ktime_get_real());
......
...@@ -100,8 +100,6 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet, ...@@ -100,8 +100,6 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) & I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
I40E_TXD_FLTR_QW0_DEST_VSI_MASK; I40E_TXD_FLTR_QW0_DEST_VSI_MASK;
fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
dcc = I40E_TX_DESC_DTYPE_FILTER_PROG; dcc = I40E_TX_DESC_DTYPE_FILTER_PROG;
if (add) if (add)
...@@ -124,6 +122,8 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet, ...@@ -124,6 +122,8 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
I40E_TXD_FLTR_QW1_CNTINDEX_MASK; I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
} }
fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
fdir_desc->rsvd = cpu_to_le32(0);
fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dcc); fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dcc);
fdir_desc->fd_id = cpu_to_le32(fdir_data->fd_id); fdir_desc->fd_id = cpu_to_le32(fdir_data->fd_id);
...@@ -271,19 +271,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, ...@@ -271,19 +271,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
fd_data->pctype, ret); fd_data->pctype, ret);
} }
fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
return err ? -EOPNOTSUPP : 0; return err ? -EOPNOTSUPP : 0;
} }
...@@ -450,8 +437,8 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, ...@@ -450,8 +437,8 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
rx_desc->wb.qword0.hi_dword.fd_id); rx_desc->wb.qword0.hi_dword.fd_id);
/* filter programming failed most likely due to table full */ /* filter programming failed most likely due to table full */
fcnt_prog = i40e_get_current_fd_count(pf); fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
fcnt_avail = i40e_get_fd_cnt_all(pf); fcnt_avail = pf->fdir_pf_filter_count;
/* If ATR is running fcnt_prog can quickly change, /* If ATR is running fcnt_prog can quickly change,
* if we are very close to full, it makes sense to disable * if we are very close to full, it makes sense to disable
* FD ATR/SB and then re-enable it when there is room. * FD ATR/SB and then re-enable it when there is room.
...@@ -1701,7 +1688,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1701,7 +1688,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
I40E_TXD_FLTR_QW1_CNTINDEX_MASK; I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype); fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
fdir_desc->rsvd = cpu_to_le32(0);
fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dtype_cmd); fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dtype_cmd);
fdir_desc->fd_id = cpu_to_le32(0);
} }
/** /**
......
...@@ -32,16 +32,22 @@ struct i40e_hw; ...@@ -32,16 +32,22 @@ struct i40e_hw;
/* HMC element context information */ /* HMC element context information */
/* Rx queue context data */ /* Rx queue context data
*
* The sizes of the variables may be larger than needed due to crossing byte
* boundaries. If we do not have the width of the variable set to the correct
* size then we could end up shifting bits off the top of the variable when the
* variable is at the top of a byte and crosses over into the next byte.
*/
struct i40e_hmc_obj_rxq { struct i40e_hmc_obj_rxq {
u16 head; u16 head;
u8 cpuid; u16 cpuid; /* bigger than needed, see above for reason */
u64 base; u64 base;
u16 qlen; u16 qlen;
#define I40E_RXQ_CTX_DBUFF_SHIFT 7 #define I40E_RXQ_CTX_DBUFF_SHIFT 7
u8 dbuff; u16 dbuff; /* bigger than needed, see above for reason */
#define I40E_RXQ_CTX_HBUFF_SHIFT 6 #define I40E_RXQ_CTX_HBUFF_SHIFT 6
u8 hbuff; u16 hbuff; /* bigger than needed, see above for reason */
u8 dtype; u8 dtype;
u8 dsize; u8 dsize;
u8 crcstrip; u8 crcstrip;
...@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq { ...@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
u8 hsplit_0; u8 hsplit_0;
u8 hsplit_1; u8 hsplit_1;
u8 showiv; u8 showiv;
u16 rxmax; u32 rxmax; /* bigger than needed, see above for reason */
u8 tphrdesc_ena; u8 tphrdesc_ena;
u8 tphwdesc_ena; u8 tphwdesc_ena;
u8 tphdata_ena; u8 tphdata_ena;
u8 tphhead_ena; u8 tphhead_ena;
u8 lrxqthresh; u16 lrxqthresh; /* bigger than needed, see above for reason */
u8 prefena; /* NOTE: normally must be set to 1 at init */ u8 prefena; /* NOTE: normally must be set to 1 at init */
}; };
/* Tx queue context data */ /* Tx queue context data
*
* The sizes of the variables may be larger than needed due to crossing byte
* boundaries. If we do not have the width of the variable set to the correct
* size then we could end up shifting bits off the top of the variable when the
* variable is at the top of a byte and crosses over into the next byte.
*/
struct i40e_hmc_obj_txq { struct i40e_hmc_obj_txq {
u16 head; u16 head;
u8 new_context; u8 new_context;
...@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq { ...@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
u8 fd_ena; u8 fd_ena;
u8 alt_vlan_ena; u8 alt_vlan_ena;
u16 thead_wb; u16 thead_wb;
u16 cpuid; u8 cpuid;
u8 head_wb_ena; u8 head_wb_ena;
u16 qlen; u16 qlen;
u8 tphrdesc_ena; u8 tphrdesc_ena;
......
...@@ -2018,11 +2018,15 @@ static void i40evf_init_task(struct work_struct *work) ...@@ -2018,11 +2018,15 @@ static void i40evf_init_task(struct work_struct *work)
if (err) { if (err) {
dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n",
err); err);
if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
dev_info(&pdev->dev, "Resending request\n");
err = i40evf_send_api_ver(adapter);
}
goto err; goto err;
} }
err = i40evf_send_vf_config_msg(adapter); err = i40evf_send_vf_config_msg(adapter);
if (err) { if (err) {
dev_err(&pdev->dev, "Unable send config request (%d)\n", dev_err(&pdev->dev, "Unable to send config request (%d)\n",
err); err);
goto err; goto err;
} }
...@@ -2408,7 +2412,9 @@ static void i40evf_remove(struct pci_dev *pdev) ...@@ -2408,7 +2412,9 @@ static void i40evf_remove(struct pci_dev *pdev)
i40evf_reset_interrupt_capability(adapter); i40evf_reset_interrupt_capability(adapter);
} }
if (adapter->watchdog_timer.function)
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
flush_scheduled_work(); flush_scheduled_work();
if (hw->aq.asq.count) if (hw->aq.asq.count)
......
...@@ -80,8 +80,9 @@ int i40evf_send_api_ver(struct i40evf_adapter *adapter) ...@@ -80,8 +80,9 @@ int i40evf_send_api_ver(struct i40evf_adapter *adapter)
* @adapter: adapter structure * @adapter: adapter structure
* *
* Compare API versions with the PF. Must be called after admin queue is * Compare API versions with the PF. Must be called after admin queue is
* initialized. Returns 0 if API versions match, -EIO if * initialized. Returns 0 if API versions match, -EIO if they do not,
* they do not, or I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty. * I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
* from the firmware are propagated.
**/ **/
int i40evf_verify_api_ver(struct i40evf_adapter *adapter) int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
{ {
...@@ -102,13 +103,13 @@ int i40evf_verify_api_ver(struct i40evf_adapter *adapter) ...@@ -102,13 +103,13 @@ int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
goto out_alloc; goto out_alloc;
err = (i40e_status)le32_to_cpu(event.desc.cookie_low); err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
if (err) { if (err)
err = -EIO;
goto out_alloc; goto out_alloc;
}
if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) != if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) !=
I40E_VIRTCHNL_OP_VERSION) { I40E_VIRTCHNL_OP_VERSION) {
dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n",
le32_to_cpu(event.desc.cookie_high));
err = -EIO; err = -EIO;
goto out_alloc; goto out_alloc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment