Commit 10f29808 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-07-24

This series contains updates to igb, ixgbe, i40e and i40evf.

Mark fixes a possible attempt to dereference a NULL pointer in ixgbe_probe().
Also changes some uses of strncpy to strlcpy when clearing is not needed to
prevent information leakage.

Jacob fixes a bug in the misuse of the list_for_each macro to loop over
every entry in the bus_list.  Instead of attempting to loop over the list
from a random entry point, go up to the bus and use the real list_head
entry point.  This prevents the possible read or write of unallocated or
incorrectly addressed memory.  Then provides a patch to prevent the
display of the minimum link qualification check if we might be in a
virtual machine.  This check is incorrect and misleading in this case,
since we actually do not really know what the available bandwidth is.
To do so, we simply check whether each function on the bus matches our
device id.

Carolyn adds a check and prints the error cause register value when the
hardware detects a malformed packet to assist the user.

Toralf Förster fixes a format mismatch in i40e which was found using
cppcheck.

Shannon adds nvmupdate support by implementing a state machine intended
to support the userland tool for updating the device eeprom.

Jesse fixes the extension header checksum logic for IPv6 in i40e and
i40evf.

Mitch reduces a delay in the i40evf driver where we do not need to
delay an entire millisecond to get into our critical section.

Kamil fixes an issue where access to the NVM was being blocked until
a driver reset where a check for NVM related admin queue commands
would not recognize that such a command was received and would not clear
nvm_busy flag.

Catherine fixes a couple of firmware API version errors.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f6e67532 e3effd73
......@@ -38,8 +38,8 @@ static void i40e_resume_aq(struct i40e_hw *hw);
**/
static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
{
return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
(desc->opcode == i40e_aqc_opc_nvm_update);
return (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_erase)) ||
(desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_update));
}
/**
......@@ -889,14 +889,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
}
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
if (le16_to_cpu(desc->datalen) == buff_size) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
"AQTX: desc and buffer writeback:\n");
i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
}
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
"AQTX: desc and buffer writeback:\n");
i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
/* update the error if time out occurred */
if ((!cmd_completed) &&
......@@ -907,6 +902,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
}
if (!status && i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
asq_send_command_error:
mutex_unlock(&hw->aq.asq_mutex);
asq_send_command_exit:
......@@ -979,17 +977,14 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
hw->aq.arq_last_status);
} else {
e->desc = *desc;
datalen = le16_to_cpu(desc->datalen);
e->msg_size = min(datalen, e->msg_size);
if (e->msg_buf != NULL && (e->msg_size != 0))
memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
e->msg_size);
}
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
e->desc = *desc;
datalen = le16_to_cpu(desc->datalen);
e->msg_size = min(datalen, e->msg_size);
if (e->msg_buf != NULL && (e->msg_size != 0))
memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
e->msg_size);
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
......@@ -1023,6 +1018,14 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
mutex_unlock(&hw->aq.arq_mutex);
if (i40e_is_nvm_update_op(&e->desc)) {
hw->aq.nvm_busy = false;
if (hw->aq.nvm_release_on_done) {
i40e_release_nvm(hw);
hw->aq.nvm_release_on_done = false;
}
}
return ret_code;
}
......
......@@ -94,6 +94,7 @@ struct i40e_adminq_info {
u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */
bool nvm_busy;
bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */
......@@ -103,6 +104,41 @@ struct i40e_adminq_info {
enum i40e_admin_queue_err arq_last_status;
};
/**
* i40e_aq_rc_to_posix - convert errors to user-land codes
* aq_rc: AdminQ error code to convert
**/
static inline int i40e_aq_rc_to_posix(u16 aq_rc)
{
int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */
-EPERM, /* I40E_AQ_RC_EPERM */
-ENOENT, /* I40E_AQ_RC_ENOENT */
-ESRCH, /* I40E_AQ_RC_ESRCH */
-EINTR, /* I40E_AQ_RC_EINTR */
-EIO, /* I40E_AQ_RC_EIO */
-ENXIO, /* I40E_AQ_RC_ENXIO */
-E2BIG, /* I40E_AQ_RC_E2BIG */
-EAGAIN, /* I40E_AQ_RC_EAGAIN */
-ENOMEM, /* I40E_AQ_RC_ENOMEM */
-EACCES, /* I40E_AQ_RC_EACCES */
-EFAULT, /* I40E_AQ_RC_EFAULT */
-EBUSY, /* I40E_AQ_RC_EBUSY */
-EEXIST, /* I40E_AQ_RC_EEXIST */
-EINVAL, /* I40E_AQ_RC_EINVAL */
-ENOTTY, /* I40E_AQ_RC_ENOTTY */
-ENOSPC, /* I40E_AQ_RC_ENOSPC */
-ENOSYS, /* I40E_AQ_RC_ENOSYS */
-ERANGE, /* I40E_AQ_RC_ERANGE */
-EPIPE, /* I40E_AQ_RC_EFLUSHED */
-ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
-EROFS, /* I40E_AQ_RC_EMODE */
-EFBIG, /* I40E_AQ_RC_EFBIG */
};
return aq_to_posix[aq_rc];
}
/* general information */
#define I40E_AQ_LARGE_BUF 512
#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
......
......@@ -2121,6 +2121,47 @@ i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
return status;
}
/**
* i40e_aq_erase_nvm
* @hw: pointer to the hw struct
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: offset in the module (expressed in 4 KB from module's beginning)
* @length: length of the section to be erased (expressed in 4 KB)
* @last_command: tells if this is the last command in a series
* @cmd_details: pointer to command details structure or NULL
*
* Erase the NVM sector using the admin queue commands
**/
i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, bool last_command,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_nvm_update *cmd =
(struct i40e_aqc_nvm_update *)&desc.params.raw;
i40e_status status;
/* In offset the highest byte must be zeroed. */
if (offset & 0xFF000000) {
status = I40E_ERR_PARAM;
goto i40e_aq_erase_nvm_exit;
}
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_erase);
/* If this is the last command in a series, set the proper flag. */
if (last_command)
cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
cmd->module_pointer = module_pointer;
cmd->offset = cpu_to_le32(offset);
cmd->length = cpu_to_le16(length);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
i40e_aq_erase_nvm_exit:
return status;
}
#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01
#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02
#define I40E_DEV_FUNC_CAP_NPAR 0x03
......@@ -2350,6 +2391,53 @@ i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
return status;
}
/**
* i40e_aq_update_nvm
* @hw: pointer to the hw struct
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: byte offset from the module beginning
* @length: length of the section to be written (in bytes from the offset)
* @data: command buffer (size [bytes] = length)
* @last_command: tells if this is the last command in a series
* @cmd_details: pointer to command details structure or NULL
*
* Update the NVM using the admin queue commands
**/
i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, void *data,
bool last_command,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_nvm_update *cmd =
(struct i40e_aqc_nvm_update *)&desc.params.raw;
i40e_status status;
/* In offset the highest byte must be zeroed. */
if (offset & 0xFF000000) {
status = I40E_ERR_PARAM;
goto i40e_aq_update_nvm_exit;
}
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
/* If this is the last command in a series, set the proper flag. */
if (last_command)
cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
cmd->module_pointer = module_pointer;
cmd->offset = cpu_to_le32(offset);
cmd->length = cpu_to_le16(length);
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
if (length > I40E_AQ_LARGE_BUF)
desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
status = i40e_asq_send_command(hw, &desc, data, length, cmd_details);
i40e_aq_update_nvm_exit:
return status;
}
/**
* i40e_aq_get_lldp_mib
* @hw: pointer to the hw struct
......
......@@ -1238,7 +1238,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {
i40e_status ret;
u16 vid;
int v;
unsigned int v;
cnt = sscanf(&cmd_buf[8], "%i %u", &vsi_seid, &v);
if (cnt != 2) {
......@@ -1254,7 +1254,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
goto command_write_done;
}
vid = (unsigned)v;
vid = v;
ret = i40e_vsi_add_pvid(vsi, vid);
if (!ret)
dev_info(&pf->pdev->dev,
......
......@@ -630,7 +630,7 @@ static int i40e_set_pauseparam(struct net_device *netdev,
bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
i40e_status status;
u8 aq_failures;
int err;
int err = 0;
if (vsi != pf->vsi[pf->lan_vsi])
return -EOPNOTSUPP;
......@@ -683,8 +683,12 @@ static int i40e_set_pauseparam(struct net_device *netdev,
err = -EAGAIN;
}
if (!test_bit(__I40E_DOWN, &pf->state))
return i40e_nway_reset(netdev);
if (!test_bit(__I40E_DOWN, &pf->state)) {
/* Give it a little more time to try to come back */
msleep(75);
if (!test_bit(__I40E_DOWN, &pf->state))
return i40e_nway_reset(netdev);
}
return err;
}
......@@ -759,10 +763,33 @@ static int i40e_get_eeprom(struct net_device *netdev,
u8 *eeprom_buff;
u16 i, sectors;
bool last;
u32 magic;
#define I40E_NVM_SECTOR_SIZE 4096
if (eeprom->len == 0)
return -EINVAL;
/* check for NVMUpdate access method */
magic = hw->vendor_id | (hw->device_id << 16);
if (eeprom->magic && eeprom->magic != magic) {
int errno;
/* make sure it is the right magic for NVMUpdate */
if ((eeprom->magic >> 16) != hw->device_id)
return -EINVAL;
ret_val = i40e_nvmupd_command(hw,
(struct i40e_nvm_access *)eeprom,
bytes, &errno);
if (ret_val)
dev_info(&pf->pdev->dev,
"NVMUpdate read failed err=%d status=0x%x\n",
ret_val, hw->aq.asq_last_status);
return errno;
}
/* normal ethtool get_eeprom support */
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL);
......@@ -789,7 +816,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
ret_val = i40e_aq_read_nvm(hw, 0x0,
eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
len,
eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
(u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
last, NULL);
if (ret_val) {
dev_info(&pf->pdev->dev,
......@@ -801,7 +828,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
release_nvm:
i40e_release_nvm(hw);
memcpy(bytes, eeprom_buff, eeprom->len);
memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
free_buff:
kfree(eeprom_buff);
return ret_val;
......@@ -821,6 +848,39 @@ static int i40e_get_eeprom_len(struct net_device *netdev)
return val;
}
static int i40e_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_hw *hw = &np->vsi->back->hw;
struct i40e_pf *pf = np->vsi->back;
int ret_val = 0;
int errno;
u32 magic;
/* normal ethtool set_eeprom is not supported */
magic = hw->vendor_id | (hw->device_id << 16);
if (eeprom->magic == magic)
return -EOPNOTSUPP;
/* check for NVMUpdate access method */
if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id)
return -EINVAL;
if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
return -EBUSY;
ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom,
bytes, &errno);
if (ret_val)
dev_info(&pf->pdev->dev,
"NVMUpdate write failed err=%d status=0x%x\n",
ret_val, hw->aq.asq_last_status);
return errno;
}
static void i40e_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
......@@ -2094,6 +2154,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_wol = i40e_get_wol,
.set_wol = i40e_set_wol,
.set_eeprom = i40e_set_eeprom,
.get_eeprom_len = i40e_get_eeprom_len,
.get_eeprom = i40e_get_eeprom,
.get_ringparam = i40e_get_ringparam,
......
......@@ -8642,24 +8642,18 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
if (err) {
dev_info(&pdev->dev,
"init_adminq failed: %d expecting API %02x.%02x\n",
err,
I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
"The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
goto err_pf_reset;
}
if (hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
dev_info(&pdev->dev,
"Note: FW API version %02x.%02x newer than expected %02x.%02x, recommend driver update.\n",
hw->aq.api_maj_ver, hw->aq.api_min_ver,
I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR-1))
"The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1))
dev_info(&pdev->dev,
"Note: FW API version %02x.%02x older than expected %02x.%02x, recommend nvm update.\n",
hw->aq.api_maj_ver, hw->aq.api_min_ver,
I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
"The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
i40e_verify_eeprom(pf);
......
This diff is collapsed.
......@@ -150,6 +150,9 @@ i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, void *data,
bool last_command,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, bool last_command,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
void *buff, u16 buff_size, u16 *data_size,
enum i40e_admin_queue_opc list_type_opc,
......@@ -245,8 +248,12 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u16 *data);
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data);
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 *checksum);
i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
struct i40e_nvm_access *cmd,
u8 *bytes, int *);
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
......
......@@ -1237,8 +1237,6 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
/* likely incorrect csum if alternate IP extension headers found */
if (ipv6 &&
decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
/* don't increment checksum err here, non-fatal err */
return;
......
......@@ -269,6 +269,61 @@ struct i40e_nvm_info {
u32 eetrack; /* NVM data version */
};
/* definitions used in NVM update support */
enum i40e_nvmupd_cmd {
I40E_NVMUPD_INVALID,
I40E_NVMUPD_READ_CON,
I40E_NVMUPD_READ_SNT,
I40E_NVMUPD_READ_LCB,
I40E_NVMUPD_READ_SA,
I40E_NVMUPD_WRITE_ERA,
I40E_NVMUPD_WRITE_CON,
I40E_NVMUPD_WRITE_SNT,
I40E_NVMUPD_WRITE_LCB,
I40E_NVMUPD_WRITE_SA,
I40E_NVMUPD_CSUM_CON,
I40E_NVMUPD_CSUM_SA,
I40E_NVMUPD_CSUM_LCB,
};
enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_INIT,
I40E_NVMUPD_STATE_READING,
I40E_NVMUPD_STATE_WRITING
};
/* nvm_access definition and its masks/shifts need to be accessible to
* application, core driver, and shared code. Where is the right file?
*/
#define I40E_NVM_READ 0xB
#define I40E_NVM_WRITE 0xC
#define I40E_NVM_MOD_PNT_MASK 0xFF
#define I40E_NVM_TRANS_SHIFT 8
#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
#define I40E_NVM_CON 0x0
#define I40E_NVM_SNT 0x1
#define I40E_NVM_LCB 0x2
#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
#define I40E_NVM_ERA 0x4
#define I40E_NVM_CSUM 0x8
#define I40E_NVM_ADAPT_SHIFT 16
#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
#define I40E_NVMUPD_MAX_DATA 4096
#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
struct i40e_nvm_access {
u32 command;
u32 config;
u32 offset; /* in bytes */
u32 data_size; /* in bytes */
u8 data[1];
};
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
......@@ -404,6 +459,9 @@ struct i40e_hw {
/* Admin Queue info */
struct i40e_adminq_info aq;
/* state of nvm update process */
enum i40e_nvmupd_state nvmupd_state;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
......
......@@ -708,12 +708,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
goto asq_send_command_exit;
}
if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
status = I40E_ERR_NVM;
goto asq_send_command_exit;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
if (cmd_details) {
*details = *cmd_details;
......@@ -846,11 +840,9 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
if (le16_to_cpu(desc->datalen) == buff_size) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
"AQTX: desc and buffer writeback:\n");
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
}
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
"AQTX: desc and buffer writeback:\n");
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
/* update the error if time out occurred */
if ((!cmd_completed) &&
......@@ -933,15 +925,15 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
hw->aq.arq_last_status);
} else {
e->desc = *desc;
datalen = le16_to_cpu(desc->datalen);
e->msg_size = min(datalen, e->msg_size);
if (e->msg_buf != NULL && (e->msg_size != 0))
memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
e->msg_size);
}
e->desc = *desc;
datalen = le16_to_cpu(desc->datalen);
e->msg_size = min(datalen, e->msg_size);
if (e->msg_buf != NULL && (e->msg_size != 0))
memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
e->msg_size);
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
......
......@@ -94,6 +94,7 @@ struct i40e_adminq_info {
u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */
bool nvm_busy;
bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */
......@@ -103,6 +104,41 @@ struct i40e_adminq_info {
enum i40e_admin_queue_err arq_last_status;
};
/**
* i40e_aq_rc_to_posix - convert errors to user-land codes
* aq_rc: AdminQ error code to convert
**/
static inline int i40e_aq_rc_to_posix(u16 aq_rc)
{
int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */
-EPERM, /* I40E_AQ_RC_EPERM */
-ENOENT, /* I40E_AQ_RC_ENOENT */
-ESRCH, /* I40E_AQ_RC_ESRCH */
-EINTR, /* I40E_AQ_RC_EINTR */
-EIO, /* I40E_AQ_RC_EIO */
-ENXIO, /* I40E_AQ_RC_ENXIO */
-E2BIG, /* I40E_AQ_RC_E2BIG */
-EAGAIN, /* I40E_AQ_RC_EAGAIN */
-ENOMEM, /* I40E_AQ_RC_ENOMEM */
-EACCES, /* I40E_AQ_RC_EACCES */
-EFAULT, /* I40E_AQ_RC_EFAULT */
-EBUSY, /* I40E_AQ_RC_EBUSY */
-EEXIST, /* I40E_AQ_RC_EEXIST */
-EINVAL, /* I40E_AQ_RC_EINVAL */
-ENOTTY, /* I40E_AQ_RC_ENOTTY */
-ENOSPC, /* I40E_AQ_RC_ENOSPC */
-ENOSYS, /* I40E_AQ_RC_ENOSYS */
-ERANGE, /* I40E_AQ_RC_ERANGE */
-EPIPE, /* I40E_AQ_RC_EFLUSHED */
-ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
-EROFS, /* I40E_AQ_RC_EMODE */
-EFBIG, /* I40E_AQ_RC_EFBIG */
};
return aq_to_posix[aq_rc];
}
/* general information */
#define I40E_AQ_LARGE_BUF 512
#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
......
......@@ -773,8 +773,6 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
/* likely incorrect csum if alternate IP extension headers found */
if (ipv6 &&
decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
/* don't increment checksum err here, non-fatal err */
return;
......
......@@ -268,6 +268,61 @@ struct i40e_nvm_info {
u32 eetrack; /* NVM data version */
};
/* definitions used in NVM update support */
enum i40e_nvmupd_cmd {
I40E_NVMUPD_INVALID,
I40E_NVMUPD_READ_CON,
I40E_NVMUPD_READ_SNT,
I40E_NVMUPD_READ_LCB,
I40E_NVMUPD_READ_SA,
I40E_NVMUPD_WRITE_ERA,
I40E_NVMUPD_WRITE_CON,
I40E_NVMUPD_WRITE_SNT,
I40E_NVMUPD_WRITE_LCB,
I40E_NVMUPD_WRITE_SA,
I40E_NVMUPD_CSUM_CON,
I40E_NVMUPD_CSUM_SA,
I40E_NVMUPD_CSUM_LCB,
};
enum i40e_nvmupd_state {
I40E_NVMUPD_STATE_INIT,
I40E_NVMUPD_STATE_READING,
I40E_NVMUPD_STATE_WRITING
};
/* nvm_access definition and its masks/shifts need to be accessible to
* application, core driver, and shared code. Where is the right file?
*/
#define I40E_NVM_READ 0xB
#define I40E_NVM_WRITE 0xC
#define I40E_NVM_MOD_PNT_MASK 0xFF
#define I40E_NVM_TRANS_SHIFT 8
#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
#define I40E_NVM_CON 0x0
#define I40E_NVM_SNT 0x1
#define I40E_NVM_LCB 0x2
#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
#define I40E_NVM_ERA 0x4
#define I40E_NVM_CSUM 0x8
#define I40E_NVM_ADAPT_SHIFT 16
#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
#define I40E_NVMUPD_MAX_DATA 4096
#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
struct i40e_nvm_access {
u32 command;
u32 config;
u32 offset; /* in bytes */
u32 data_size; /* in bytes */
u8 data[1];
};
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
......@@ -403,6 +458,9 @@ struct i40e_hw {
/* Admin Queue info */
struct i40e_adminq_info aq;
/* state of nvm update process */
enum i40e_nvmupd_state nvmupd_state;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
......
......@@ -768,7 +768,7 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section))
mdelay(1);
udelay(1);
f = i40evf_find_filter(adapter, macaddr);
if (NULL == f) {
......@@ -840,7 +840,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev)
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section))
mdelay(1);
udelay(1);
/* remove filter if not in netdev list */
list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
bool found = false;
......
......@@ -355,6 +355,7 @@
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
/* These act per VF so an array friendly macro is used */
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
......
......@@ -57,8 +57,8 @@
#include "igb.h"
#define MAJ 5
#define MIN 0
#define BUILD 5
#define MIN 2
#define BUILD 13
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
......@@ -4166,6 +4166,26 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event)
return ret;
}
/**
* igb_check_lvmmc - check for malformed packets received
* and indicated in LVMMC register
* @adapter: pointer to adapter
**/
static void igb_check_lvmmc(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 lvmmc;
lvmmc = rd32(E1000_LVMMC);
if (lvmmc) {
if (unlikely(net_ratelimit())) {
netdev_warn(adapter->netdev,
"malformed Tx packet detected and dropped, LVMMC:0x%08x\n",
lvmmc);
}
}
}
/**
* igb_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
......@@ -4361,6 +4381,11 @@ static void igb_watchdog_task(struct work_struct *work)
igb_spoof_check(adapter);
igb_ptp_rx_hang(adapter);
/* Check LVMMC register on i350/i354 only */
if ((adapter->hw.mac.type == e1000_i350) ||
(adapter->hw.mac.type == e1000_i354))
igb_check_lvmmc(adapter);
/* Reset the timer */
if (!test_bit(__IGB_DOWN, &adapter->state)) {
if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)
......
......@@ -7973,23 +7973,32 @@ static const struct net_device_ops ixgbe_netdev_ops = {
**/
static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
{
struct list_head *entry;
struct pci_dev *entry, *pdev = adapter->pdev;
int physfns = 0;
/* Some cards can not use the generic count PCIe functions method,
* because they are behind a parent switch, so we hardcode these with
* the correct number of functions.
*/
if (ixgbe_pcie_from_parent(&adapter->hw)) {
if (ixgbe_pcie_from_parent(&adapter->hw))
physfns = 4;
} else {
list_for_each(entry, &adapter->pdev->bus_list) {
struct pci_dev *pdev =
list_entry(entry, struct pci_dev, bus_list);
/* don't count virtual functions */
if (!pdev->is_virtfn)
physfns++;
}
list_for_each_entry(entry, &adapter->pdev->bus->devices, bus_list) {
/* don't count virtual functions */
if (entry->is_virtfn)
continue;
/* When the devices on the bus don't all match our device ID,
* we can't reliably determine the correct number of
* functions. This can occur if a function has been direct
* attached to a virtual machine using VT-d, for example. In
* this case, simply return -1 to indicate this.
*/
if ((entry->vendor != pdev->vendor) ||
(entry->device != pdev->device))
return -1;
physfns++;
}
return physfns;
......@@ -8161,7 +8170,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &ixgbe_netdev_ops;
ixgbe_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
adapter->bd_number = cards_found;
......@@ -8384,11 +8393,14 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
expected_gts = ixgbe_enumerate_functions(adapter) * 10;
break;
}
ixgbe_check_minimum_link(adapter, expected_gts);
err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
/* don't check link if we failed to enumerate functions */
if (expected_gts > 0)
ixgbe_check_minimum_link(adapter, expected_gts);
err = ixgbe_read_pba_string_generic(hw, part_str, sizeof(part_str));
if (err)
strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
strlcpy(part_str, "Unknown", sizeof(part_str));
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
......@@ -8477,7 +8489,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_select_bars(pdev, IORESOURCE_MEM));
err_pci_reg:
err_dma:
if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
if (!adapter || !test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
pci_disable_device(pdev);
return err;
}
......
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