Appliance image builds and boots for the locked-in hardware: kernel/ixgbe-sff.patch carries the product driver subset (raw I2C + sff_i2c, ETQF steering with rule round-trip, FCoE slot guard — bench-only reg_ops/ts_bench excluded), ported to v7.2 and compile-verified; mkimage applies it or dies, builds IXGBE=y (ICE/I40E out with the ice.pkg blob) and puts ixgbe.allow_unsupported_sfp=1 on the cmdline; load-ixgbe joins the repo anchored to its own path; module bringup ordered after the host checks because a down port's TX_DISABLE powers the PHY core down while the mailbox keeps answering (proven by flipping admin state: down reads 0xffff everywhere, core wakes 0.07-0.24s after the raise) with identify settling 3s bounded; cold-boot condition reproduced on the bench (ports downed first) and passing, confirmed on the appliance
This commit is contained in:
@@ -0,0 +1,571 @@
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
|
||||
index 9b8217523fd2..15d77ccb749d 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
|
||||
@@ -771,6 +771,13 @@ struct ixgbe_adapter {
|
||||
u32 atr_sample_rate;
|
||||
spinlock_t fdir_perfect_lock;
|
||||
|
||||
+ struct ixgbe_etqf_entry {
|
||||
+ bool used;
|
||||
+ u32 loc;
|
||||
+ u16 etype;
|
||||
+ u8 ring;
|
||||
+ } etqf_filters[IXGBE_MAX_ETQF_FILTERS];
|
||||
+
|
||||
bool fw_emp_reset_disabled;
|
||||
|
||||
#ifdef IXGBE_FCOE
|
||||
@@ -1010,6 +1017,8 @@ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
|
||||
int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
|
||||
struct ixgbe_fdir_filter *input,
|
||||
u16 sw_idx);
|
||||
+void ixgbe_etqf_filter_restore(struct ixgbe_adapter *adapter);
|
||||
+void ixgbe_etqf_filter_exit(struct ixgbe_adapter *adapter);
|
||||
void ixgbe_set_rx_mode(struct net_device *netdev);
|
||||
#ifdef CONFIG_IXGBE_DCB
|
||||
void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
|
||||
index 5b1cf49df3d3..75689ca7eb2d 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "ixgbe.h"
|
||||
+#include "ixgbe_phy.h"
|
||||
|
||||
static struct dentry *ixgbe_dbg_root;
|
||||
|
||||
@@ -185,6 +186,123 @@ static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
|
||||
.write = ixgbe_dbg_netdev_ops_write,
|
||||
};
|
||||
|
||||
+#define IXGBE_SFF_I2C_MAX 32
|
||||
+
|
||||
+struct ixgbe_sff_i2c_ctx {
|
||||
+ struct ixgbe_adapter *adapter;
|
||||
+ int resp_len;
|
||||
+ char resp[IXGBE_SFF_I2C_MAX * 3 + 16];
|
||||
+};
|
||||
+
|
||||
+static int ixgbe_dbg_sff_i2c_open(struct inode *inode, struct file *filp)
|
||||
+{
|
||||
+ struct ixgbe_sff_i2c_ctx *ctx;
|
||||
+
|
||||
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
+ if (!ctx)
|
||||
+ return -ENOMEM;
|
||||
+ ctx->adapter = inode->i_private;
|
||||
+ filp->private_data = ctx;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ixgbe_dbg_sff_i2c_release(struct inode *inode, struct file *filp)
|
||||
+{
|
||||
+ kfree(filp->private_data);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t ixgbe_dbg_sff_i2c_write(struct file *filp,
|
||||
+ const char __user *ubuf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ixgbe_sff_i2c_ctx *ctx = filp->private_data;
|
||||
+ struct ixgbe_hw *hw = &ctx->adapter->hw;
|
||||
+ u8 data[IXGBE_SFF_I2C_MAX];
|
||||
+ u8 wdata[IXGBE_SFF_I2C_MAX];
|
||||
+ char cmd[160];
|
||||
+ unsigned int addr, raddr, delay, n, wn, v;
|
||||
+ int status, off, consumed, i;
|
||||
+ char op;
|
||||
+
|
||||
+ if (*ppos != 0 || count >= sizeof(cmd))
|
||||
+ return -EINVAL;
|
||||
+ if (copy_from_user(cmd, ubuf, count))
|
||||
+ return -EFAULT;
|
||||
+ cmd[count] = '\0';
|
||||
+
|
||||
+ if (sscanf(cmd, " %c %x %n", &op, &addr, &off) < 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (op == 'r') {
|
||||
+ if (sscanf(cmd + off, "%x", &n) != 1 || n < 1 ||
|
||||
+ n > IXGBE_SFF_I2C_MAX)
|
||||
+ return -EINVAL;
|
||||
+ status = ixgbe_i2c_raw_read(hw, addr, data, n);
|
||||
+ } else if (op == 'w') {
|
||||
+ n = 0;
|
||||
+ while (n < IXGBE_SFF_I2C_MAX &&
|
||||
+ sscanf(cmd + off, "%x%n", &v, &consumed) == 1) {
|
||||
+ data[n++] = v;
|
||||
+ off += consumed;
|
||||
+ }
|
||||
+ status = ixgbe_i2c_raw_write(hw, addr, data, n);
|
||||
+ } else if (op == 'x') {
|
||||
+ if (sscanf(cmd + off, "%x %u %x %n", &raddr, &delay, &n,
|
||||
+ &consumed) < 3)
|
||||
+ return -EINVAL;
|
||||
+ off += consumed;
|
||||
+ if (n > IXGBE_SFF_I2C_MAX || delay > 50000)
|
||||
+ return -EINVAL;
|
||||
+ wn = 0;
|
||||
+ while (wn < IXGBE_SFF_I2C_MAX &&
|
||||
+ sscanf(cmd + off, "%x%n", &v, &consumed) == 1) {
|
||||
+ wdata[wn++] = v;
|
||||
+ off += consumed;
|
||||
+ }
|
||||
+ status = ixgbe_i2c_raw_xfer(hw, addr, wdata, wn, delay,
|
||||
+ raddr, data, n);
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (status) {
|
||||
+ ctx->resp_len = scnprintf(ctx->resp, sizeof(ctx->resp),
|
||||
+ "err %d\n", status);
|
||||
+ } else if (op == 'r' || (op == 'x' && n)) {
|
||||
+ off = scnprintf(ctx->resp, sizeof(ctx->resp), "ok");
|
||||
+ for (i = 0; i < n; i++)
|
||||
+ off += scnprintf(ctx->resp + off,
|
||||
+ sizeof(ctx->resp) - off,
|
||||
+ " %02x", data[i]);
|
||||
+ off += scnprintf(ctx->resp + off, sizeof(ctx->resp) - off,
|
||||
+ "\n");
|
||||
+ ctx->resp_len = off;
|
||||
+ } else {
|
||||
+ ctx->resp_len = scnprintf(ctx->resp, sizeof(ctx->resp), "ok\n");
|
||||
+ }
|
||||
+
|
||||
+ *ppos = 0;
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t ixgbe_dbg_sff_i2c_read(struct file *filp, char __user *ubuf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ixgbe_sff_i2c_ctx *ctx = filp->private_data;
|
||||
+
|
||||
+ return simple_read_from_buffer(ubuf, count, ppos, ctx->resp,
|
||||
+ ctx->resp_len);
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations ixgbe_dbg_sff_i2c_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .open = ixgbe_dbg_sff_i2c_open,
|
||||
+ .release = ixgbe_dbg_sff_i2c_release,
|
||||
+ .read = ixgbe_dbg_sff_i2c_read,
|
||||
+ .write = ixgbe_dbg_sff_i2c_write,
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* ixgbe_dbg_adapter_init - setup the debugfs directory for the adapter
|
||||
* @adapter: the adapter that is starting up
|
||||
@@ -198,6 +316,8 @@ void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter)
|
||||
adapter, &ixgbe_dbg_reg_ops_fops);
|
||||
debugfs_create_file("netdev_ops", 0600, adapter->ixgbe_dbg_adapter,
|
||||
adapter, &ixgbe_dbg_netdev_ops_fops);
|
||||
+ debugfs_create_file("sff_i2c", 0600, adapter->ixgbe_dbg_adapter,
|
||||
+ adapter, &ixgbe_dbg_sff_i2c_fops);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
|
||||
index 36e43b5e88d1..8bcb0ec0e65d 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
|
||||
@@ -2664,6 +2664,142 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static u32 ixgbe_etqf_filter_count(struct ixgbe_adapter *adapter)
|
||||
+{
|
||||
+ u32 n = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++)
|
||||
+ if (adapter->etqf_filters[i].used)
|
||||
+ n++;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+static int ixgbe_add_etqf_entry(struct ixgbe_adapter *adapter,
|
||||
+ struct ethtool_rxnfc *cmd)
|
||||
+{
|
||||
+ struct ethtool_rx_flow_spec *fsp =
|
||||
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
|
||||
+ static const u8 zero_mac[ETH_ALEN];
|
||||
+ struct ixgbe_etqf_entry *slot = NULL;
|
||||
+ struct ixgbe_hw *hw = &adapter->hw;
|
||||
+ u16 etype = ntohs(fsp->h_u.ether_spec.h_proto);
|
||||
+ u32 ring;
|
||||
+ int i;
|
||||
+
|
||||
+ if (fsp->flow_type != ETHER_FLOW)
|
||||
+ return -EINVAL;
|
||||
+ if (fsp->m_u.ether_spec.h_proto != htons(0xFFFF) ||
|
||||
+ !ether_addr_equal(fsp->m_u.ether_spec.h_dest, zero_mac) ||
|
||||
+ !ether_addr_equal(fsp->m_u.ether_spec.h_source, zero_mac))
|
||||
+ return -EINVAL;
|
||||
+ if (etype == ETH_P_1588)
|
||||
+ return -EINVAL;
|
||||
+ if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
|
||||
+ return -EINVAL;
|
||||
+ ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
|
||||
+ if (ethtool_get_flow_spec_ring_vf(fsp->ring_cookie) ||
|
||||
+ ring >= adapter->num_rx_queues)
|
||||
+ return -EINVAL;
|
||||
+ if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ spin_lock(&adapter->fdir_perfect_lock);
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ struct ixgbe_etqf_entry *e = &adapter->etqf_filters[i];
|
||||
+
|
||||
+ if (!e->used)
|
||||
+ continue;
|
||||
+ if (e->etype == etype && e->loc != fsp->location) {
|
||||
+ spin_unlock(&adapter->fdir_perfect_lock);
|
||||
+ return -EEXIST;
|
||||
+ }
|
||||
+ if (e->loc == fsp->location)
|
||||
+ slot = e;
|
||||
+ }
|
||||
+ if (!slot) {
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ if (i == IXGBE_ETQF_FILTER_1588 ||
|
||||
+ adapter->etqf_filters[i].used ||
|
||||
+ (IXGBE_READ_REG(hw, IXGBE_ETQF(i)) &
|
||||
+ IXGBE_ETQF_FILTER_EN))
|
||||
+ continue;
|
||||
+ slot = &adapter->etqf_filters[i];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!slot) {
|
||||
+ spin_unlock(&adapter->fdir_perfect_lock);
|
||||
+ return -ENOSPC;
|
||||
+ }
|
||||
+
|
||||
+ i = slot - adapter->etqf_filters;
|
||||
+ slot->used = true;
|
||||
+ slot->loc = fsp->location;
|
||||
+ slot->etype = etype;
|
||||
+ slot->ring = ring;
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQS(i), IXGBE_ETQS_QUEUE_EN |
|
||||
+ ((u32)adapter->rx_ring[ring]->reg_idx <<
|
||||
+ IXGBE_ETQS_RX_QUEUE_SHIFT));
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(i), IXGBE_ETQF_FILTER_EN | etype);
|
||||
+ spin_unlock(&adapter->fdir_perfect_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Caller holds fdir_perfect_lock. */
|
||||
+static int ixgbe_del_etqf_entry(struct ixgbe_adapter *adapter, u32 loc)
|
||||
+{
|
||||
+ struct ixgbe_hw *hw = &adapter->hw;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ struct ixgbe_etqf_entry *e = &adapter->etqf_filters[i];
|
||||
+
|
||||
+ if (!e->used || e->loc != loc)
|
||||
+ continue;
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(i), 0);
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQS(i), 0);
|
||||
+ e->used = false;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return -ENOENT;
|
||||
+}
|
||||
+
|
||||
+void ixgbe_etqf_filter_restore(struct ixgbe_adapter *adapter)
|
||||
+{
|
||||
+ struct ixgbe_hw *hw = &adapter->hw;
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock(&adapter->fdir_perfect_lock);
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ struct ixgbe_etqf_entry *e = &adapter->etqf_filters[i];
|
||||
+
|
||||
+ if (!e->used)
|
||||
+ continue;
|
||||
+ if (e->ring >= adapter->num_rx_queues) {
|
||||
+ e->used = false;
|
||||
+ continue;
|
||||
+ }
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQS(i), IXGBE_ETQS_QUEUE_EN |
|
||||
+ ((u32)adapter->rx_ring[e->ring]->reg_idx <<
|
||||
+ IXGBE_ETQS_RX_QUEUE_SHIFT));
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(i),
|
||||
+ IXGBE_ETQF_FILTER_EN | e->etype);
|
||||
+ }
|
||||
+ spin_unlock(&adapter->fdir_perfect_lock);
|
||||
+}
|
||||
+
|
||||
+void ixgbe_etqf_filter_exit(struct ixgbe_adapter *adapter)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock(&adapter->fdir_perfect_lock);
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++)
|
||||
+ adapter->etqf_filters[i].used = false;
|
||||
+ spin_unlock(&adapter->fdir_perfect_lock);
|
||||
+}
|
||||
+
|
||||
static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
|
||||
struct ethtool_rxnfc *cmd)
|
||||
{
|
||||
@@ -2672,10 +2808,23 @@ static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
|
||||
(struct ethtool_rx_flow_spec *)&cmd->fs;
|
||||
struct hlist_node *node2;
|
||||
struct ixgbe_fdir_filter *rule = NULL;
|
||||
+ int i;
|
||||
|
||||
/* report total rule count */
|
||||
cmd->data = (1024 << adapter->fdir_pballoc) - 2;
|
||||
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ struct ixgbe_etqf_entry *e = &adapter->etqf_filters[i];
|
||||
+
|
||||
+ if (!e->used || e->loc != fsp->location)
|
||||
+ continue;
|
||||
+ fsp->flow_type = ETHER_FLOW;
|
||||
+ fsp->h_u.ether_spec.h_proto = htons(e->etype);
|
||||
+ fsp->m_u.ether_spec.h_proto = htons(0xFFFF);
|
||||
+ fsp->ring_cookie = e->ring;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
hlist_for_each_entry_safe(rule, node2,
|
||||
&adapter->fdir_filter_list, fdir_node) {
|
||||
if (fsp->location <= rule->sw_idx)
|
||||
@@ -2740,6 +2889,7 @@ static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
|
||||
struct hlist_node *node2;
|
||||
struct ixgbe_fdir_filter *rule;
|
||||
int cnt = 0;
|
||||
+ int i;
|
||||
|
||||
/* report total rule count */
|
||||
cmd->data = (1024 << adapter->fdir_pballoc) - 2;
|
||||
@@ -2752,6 +2902,17 @@ static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
|
||||
cnt++;
|
||||
}
|
||||
|
||||
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
|
||||
+ struct ixgbe_etqf_entry *e = &adapter->etqf_filters[i];
|
||||
+
|
||||
+ if (!e->used)
|
||||
+ continue;
|
||||
+ if (cnt == cmd->rule_cnt)
|
||||
+ return -EMSGSIZE;
|
||||
+ rule_locs[cnt] = e->loc;
|
||||
+ cnt++;
|
||||
+ }
|
||||
+
|
||||
cmd->rule_cnt = cnt;
|
||||
|
||||
return 0;
|
||||
@@ -2825,7 +2986,9 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_GRXCLSRLCNT:
|
||||
- cmd->rule_cnt = adapter->fdir_filter_count;
|
||||
+ cmd->rule_cnt = adapter->fdir_filter_count +
|
||||
+ ixgbe_etqf_filter_count(adapter);
|
||||
+ cmd->data = (1024 << adapter->fdir_pballoc) - 2;
|
||||
ret = 0;
|
||||
break;
|
||||
case ETHTOOL_GRXCLSRULE:
|
||||
@@ -3077,7 +3240,10 @@ static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
|
||||
int err;
|
||||
|
||||
spin_lock(&adapter->fdir_perfect_lock);
|
||||
- err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
|
||||
+ err = ixgbe_del_etqf_entry(adapter, fsp->location);
|
||||
+ if (err)
|
||||
+ err = ixgbe_update_ethtool_fdir_entry(adapter, NULL,
|
||||
+ fsp->location);
|
||||
spin_unlock(&adapter->fdir_perfect_lock);
|
||||
|
||||
return err;
|
||||
@@ -3207,7 +3373,10 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_SRXCLSRLINS:
|
||||
- ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
|
||||
+ if ((cmd->fs.flow_type & ~FLOW_EXT) == ETHER_FLOW)
|
||||
+ ret = ixgbe_add_etqf_entry(adapter, cmd);
|
||||
+ else
|
||||
+ ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
|
||||
break;
|
||||
case ETHTOOL_SRXCLSRLDEL:
|
||||
ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
|
||||
index 011fda9c6193..1b5cb4f7bb68 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
|
||||
@@ -647,6 +647,10 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
|
||||
if (!(adapter->netdev->features & NETIF_F_FCOE_CRC))
|
||||
return;
|
||||
|
||||
+ /* leave registers un-configured if FCoE is disabled */
|
||||
+ if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
|
||||
+ return;
|
||||
+
|
||||
/* Enable L2 EtherType filter for FCoE, needed for FCoE CRC and DDP */
|
||||
etqf = ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN;
|
||||
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
|
||||
@@ -656,10 +660,6 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE), etqf);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0);
|
||||
|
||||
- /* leave registers un-configured if FCoE is disabled */
|
||||
- if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
|
||||
- return;
|
||||
-
|
||||
/* Use one or more Rx queues for FCoE by redirection table */
|
||||
fcreta_size = IXGBE_FCRETA_SIZE;
|
||||
if (adapter->hw.mac.type == ixgbe_mac_X550)
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
||||
index 8873a8cc4a18..85fdf1ab4177 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
||||
@@ -5911,6 +5911,8 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
|
||||
ixgbe_fdir_filter_restore(adapter);
|
||||
}
|
||||
|
||||
+ ixgbe_etqf_filter_restore(adapter);
|
||||
+
|
||||
switch (hw->mac.type) {
|
||||
case ixgbe_mac_82599EB:
|
||||
case ixgbe_mac_X540:
|
||||
@@ -7533,6 +7535,7 @@ int ixgbe_close(struct net_device *netdev)
|
||||
ixgbe_close_suspend(adapter);
|
||||
|
||||
ixgbe_fdir_filter_exit(adapter);
|
||||
+ ixgbe_etqf_filter_exit(adapter);
|
||||
|
||||
ixgbe_release_hw_control(adapter);
|
||||
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
||||
index ab733e73927d..fb876b9e9395 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
|
||||
@@ -60,6 +60,102 @@ static int ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte)
|
||||
return ixgbe_clock_out_i2c_bit(hw, false);
|
||||
}
|
||||
|
||||
+static int ixgbe_i2c_raw_write_unlocked(struct ixgbe_hw *hw, u8 addr,
|
||||
+ const u8 *buf, u8 len)
|
||||
+{
|
||||
+ int status;
|
||||
+ u8 i;
|
||||
+
|
||||
+ ixgbe_i2c_start(hw);
|
||||
+ status = ixgbe_out_i2c_byte_ack(hw, addr);
|
||||
+ for (i = 0; !status && i < len; i++)
|
||||
+ status = ixgbe_out_i2c_byte_ack(hw, buf[i]);
|
||||
+
|
||||
+ if (status)
|
||||
+ ixgbe_i2c_bus_clear(hw);
|
||||
+ else
|
||||
+ ixgbe_i2c_stop(hw);
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+static int ixgbe_i2c_raw_read_unlocked(struct ixgbe_hw *hw, u8 addr,
|
||||
+ u8 *buf, u8 len)
|
||||
+{
|
||||
+ u32 i2cctl;
|
||||
+ int status;
|
||||
+ u8 i;
|
||||
+
|
||||
+ ixgbe_i2c_start(hw);
|
||||
+ status = ixgbe_out_i2c_byte_ack(hw, addr);
|
||||
+ for (i = 0; !status && i < len; i++) {
|
||||
+ status = ixgbe_clock_in_i2c_byte(hw, &buf[i]);
|
||||
+ if (!status)
|
||||
+ status = ixgbe_clock_out_i2c_bit(hw, i == len - 1);
|
||||
+ if (!status && i != len - 1) {
|
||||
+ /* our ACK left SDA driven low; release it so the
|
||||
+ * slave can drive the next byte
|
||||
+ */
|
||||
+ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
|
||||
+ i2cctl |= IXGBE_I2C_DATA_OUT(hw);
|
||||
+ i2cctl |= IXGBE_I2C_DATA_OE_N_EN(hw);
|
||||
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
|
||||
+ IXGBE_WRITE_FLUSH(hw);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (status)
|
||||
+ ixgbe_i2c_bus_clear(hw);
|
||||
+ else
|
||||
+ ixgbe_i2c_stop(hw);
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+int ixgbe_i2c_raw_write(struct ixgbe_hw *hw, u8 addr, const u8 *buf, u8 len)
|
||||
+{
|
||||
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
|
||||
+ int status;
|
||||
+
|
||||
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
|
||||
+ return -EBUSY;
|
||||
+ status = ixgbe_i2c_raw_write_unlocked(hw, addr, buf, len);
|
||||
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+int ixgbe_i2c_raw_read(struct ixgbe_hw *hw, u8 addr, u8 *buf, u8 len)
|
||||
+{
|
||||
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
|
||||
+ int status;
|
||||
+
|
||||
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
|
||||
+ return -EBUSY;
|
||||
+ status = ixgbe_i2c_raw_read_unlocked(hw, addr, buf, len);
|
||||
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+int ixgbe_i2c_raw_xfer(struct ixgbe_hw *hw, u8 waddr, const u8 *wbuf, u8 wlen,
|
||||
+ u32 delay_us, u8 raddr, u8 *rbuf, u8 rlen)
|
||||
+{
|
||||
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
|
||||
+ int status = 0;
|
||||
+
|
||||
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ if (wlen)
|
||||
+ status = ixgbe_i2c_raw_write_unlocked(hw, waddr, wbuf, wlen);
|
||||
+ if (!status && delay_us)
|
||||
+ usleep_range(delay_us, delay_us + delay_us / 10 + 10);
|
||||
+ if (!status && rlen)
|
||||
+ status = ixgbe_i2c_raw_read_unlocked(hw, raddr, rbuf, rlen);
|
||||
+
|
||||
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* ixgbe_ones_comp_byte_add - Perform one's complement addition
|
||||
* @add1: addend 1
|
||||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
||||
index 039ba4b6c120..b93bdd972d7a 100644
|
||||
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
||||
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
|
||||
@@ -178,4 +178,8 @@ int ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
|
||||
u16 *val, bool lock);
|
||||
int ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
|
||||
u16 val, bool lock);
|
||||
+int ixgbe_i2c_raw_write(struct ixgbe_hw *hw, u8 addr, const u8 *buf, u8 len);
|
||||
+int ixgbe_i2c_raw_read(struct ixgbe_hw *hw, u8 addr, u8 *buf, u8 len);
|
||||
+int ixgbe_i2c_raw_xfer(struct ixgbe_hw *hw, u8 waddr, const u8 *wbuf, u8 wlen,
|
||||
+ u32 delay_us, u8 raddr, u8 *rbuf, u8 rlen);
|
||||
#endif /* _IXGBE_PHY_H_ */
|
||||
Reference in New Issue
Block a user