summaryrefslogtreecommitdiff
path: root/drivers/net/benet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/benet')
-rw-r--r--drivers/net/benet/be.h9
-rw-r--r--drivers/net/benet/be_cmds.c107
-rw-r--r--drivers/net/benet/be_cmds.h21
-rw-r--r--drivers/net/benet/be_ethtool.c59
-rw-r--r--drivers/net/benet/be_hw.h4
-rw-r--r--drivers/net/benet/be_main.c112
6 files changed, 241 insertions, 71 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 66823eded7a3..ea1ea824d7c7 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -84,7 +84,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MCC_CQ_LEN 256
#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */
-#define BE_MAX_MSIX_VECTORS (MAX_RSS_QS + 1 + 1)/* RSS qs + 1 def Rx + Tx */
+#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
+#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
@@ -276,7 +277,7 @@ struct be_adapter {
spinlock_t mcc_cq_lock;
struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
- bool msix_enabled;
+ u32 num_msix_vec;
bool isr_registered;
/* TX Rings */
@@ -287,7 +288,7 @@ struct be_adapter {
u32 cache_line_break[8];
/* Rx rings */
- struct be_rx_obj rx_obj[MAX_RSS_QS + 1]; /* one default non-rss Q */
+ struct be_rx_obj rx_obj[MAX_RX_QS];
u32 num_rx_qs;
u32 big_page_size; /* Compounded page size shared by rx wrbs */
@@ -312,6 +313,7 @@ struct be_adapter {
char fw_ver[FW_VER_LEN];
u32 if_handle; /* Used to configure filtering */
u32 pmac_id; /* MAC addr handle used by BE card */
+ u32 beacon_state; /* for set_phys_id */
bool eeh_err;
bool link_up;
@@ -351,6 +353,7 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops;
+#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
#define tx_stats(adapter) (&adapter->tx_stats)
#define rx_stats(rxo) (&rxo->stats)
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 5a4a87e7c5ea..2aadf88eaa0a 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1186,6 +1186,113 @@ err:
return status;
}
+/* Uses synchronous mcc */
+int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_fat *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+ OPCODE_COMMON_MANAGE_FAT);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MANAGE_FAT, sizeof(*req));
+ req->fat_operation = cpu_to_le32(QUERY_FAT);
+ status = be_mcc_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
+ if (log_size && resp->log_size)
+ *log_size = le32_to_cpu(resp->log_size -
+ sizeof(u32));
+ }
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
+void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
+{
+ struct be_dma_mem get_fat_cmd;
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_fat *req;
+ struct be_sge *sge;
+ u32 offset = 0, total_size, buf_size, log_offset = sizeof(u32);
+ int status;
+
+ if (buf_len == 0)
+ return;
+
+ total_size = buf_len;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ while (total_size) {
+ buf_size = min(total_size, (u32)60*1024);
+ total_size -= buf_size;
+
+ get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + buf_size;
+ get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
+ get_fat_cmd.size,
+ &get_fat_cmd.dma);
+ if (!get_fat_cmd.va) {
+ status = -ENOMEM;
+ dev_err(&adapter->pdev->dev,
+ "Memory allocation failure while retrieving FAT data\n");
+ goto err;
+ }
+ req = get_fat_cmd.va;
+ sge = nonembedded_sgl(wrb);
+
+ be_wrb_hdr_prepare(wrb, get_fat_cmd.size, false, 1,
+ OPCODE_COMMON_MANAGE_FAT);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MANAGE_FAT, get_fat_cmd.size);
+
+ sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.size));
+ sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF);
+ sge->len = cpu_to_le32(get_fat_cmd.size);
+
+ req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
+ req->read_log_offset = cpu_to_le32(log_offset);
+ req->read_log_length = cpu_to_le32(buf_size);
+ req->data_buffer_size = cpu_to_le32(buf_size);
+
+ status = be_mcc_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
+ memcpy(buf + offset,
+ resp->data_buffer,
+ resp->read_log_length);
+ }
+ pci_free_consistent(adapter->pdev, get_fat_cmd.size,
+ get_fat_cmd.va,
+ get_fat_cmd.dma);
+ if (status)
+ dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
+
+ offset += buf_size;
+ log_offset += buf_size;
+ }
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+}
+
/* Uses Mbox */
int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
{
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 4f254cfaabe2..3fb6e0a3ad7a 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -186,6 +186,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_NTWK_PMAC_ADD 59
#define OPCODE_COMMON_NTWK_PMAC_DEL 60
#define OPCODE_COMMON_FUNCTION_RESET 61
+#define OPCODE_COMMON_MANAGE_FAT 68
#define OPCODE_COMMON_ENABLE_DISABLE_BEACON 69
#define OPCODE_COMMON_GET_BEACON_STATE 70
#define OPCODE_COMMON_READ_TRANSRECV_DATA 73
@@ -380,6 +381,24 @@ struct be_cmd_resp_cq_create {
u16 rsvd0;
} __packed;
+struct be_cmd_req_get_fat {
+ struct be_cmd_req_hdr hdr;
+ u32 fat_operation;
+ u32 read_log_offset;
+ u32 read_log_length;
+ u32 data_buffer_size;
+ u32 data_buffer[1];
+} __packed;
+
+struct be_cmd_resp_get_fat {
+ struct be_cmd_resp_hdr hdr;
+ u32 log_size;
+ u32 read_log_length;
+ u32 rsvd[2];
+ u32 data_buffer[1];
+} __packed;
+
+
/******************** Create MCCQ ***************************/
/* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field */
@@ -1148,4 +1167,6 @@ extern void be_detect_dump_ue(struct be_adapter *adapter);
extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
extern int be_cmd_check_native_mode(struct be_adapter *adapter);
+extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
+extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index aac248fbd18b..a665697df824 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -156,6 +156,25 @@ be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
}
static int
+be_get_reg_len(struct net_device *netdev)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+ u32 log_size = 0;
+
+ be_cmd_get_reg_len(adapter, &log_size);
+ return log_size;
+}
+
+static void
+be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ memset(buf, 0, regs->len);
+ be_cmd_get_regs(adapter, regs->len, buf);
+}
+
+static int
be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct be_adapter *adapter = netdev_priv(netdev);
@@ -507,29 +526,33 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
}
static int
-be_phys_id(struct net_device *netdev, u32 data)
+be_set_phys_id(struct net_device *netdev,
+ enum ethtool_phys_id_state state)
{
struct be_adapter *adapter = netdev_priv(netdev);
- int status;
- u32 cur;
- be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &cur);
-
- if (cur == BEACON_STATE_ENABLED)
- return 0;
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ be_cmd_get_beacon_state(adapter, adapter->hba_port_num,
+ &adapter->beacon_state);
+ return -EINVAL;
- if (data < 2)
- data = 2;
+ case ETHTOOL_ID_ON:
+ be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
+ BEACON_STATE_ENABLED);
+ break;
- status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
- BEACON_STATE_ENABLED);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(data*HZ);
+ case ETHTOOL_ID_OFF:
+ be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
+ BEACON_STATE_DISABLED);
+ break;
- status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
- BEACON_STATE_DISABLED);
+ case ETHTOOL_ID_INACTIVE:
+ be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
+ adapter->beacon_state);
+ }
- return status;
+ return 0;
}
static bool
@@ -734,9 +757,11 @@ const struct ethtool_ops be_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_strings = be_get_stat_strings,
- .phys_id = be_phys_id,
+ .set_phys_id = be_set_phys_id,
.get_sset_count = be_get_sset_count,
.get_ethtool_stats = be_get_ethtool_stats,
+ .get_regs_len = be_get_reg_len,
+ .get_regs = be_get_regs,
.flash_device = be_do_flash,
.self_test = be_self_test,
};
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index d4344a06090b..53d658afea2a 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -155,6 +155,10 @@
/********** SRIOV VF PCICFG OFFSET ********/
#define SRIOV_VF_PCICFG_OFFSET (4096)
+/********** FAT TABLE ********/
+#define RETRIEVE_FAT 0
+#define QUERY_FAT 1
+
/* Flashrom related descriptors */
#define IMAGE_TYPE_FIRMWARE 160
#define IMAGE_TYPE_BOOTCODE 224
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 88d4c8038be4..2c3685389485 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1101,8 +1101,12 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter,
AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl);
rxcp->pkt_type =
AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl);
- rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl);
- rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, compl);
+ if (rxcp->vlanf) {
+ rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm,
+ compl);
+ rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
+ compl);
+ }
}
static void be_parse_rx_compl_v0(struct be_adapter *adapter,
@@ -1127,8 +1131,12 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter,
AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl);
rxcp->pkt_type =
AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl);
- rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl);
- rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, compl);
+ if (rxcp->vlanf) {
+ rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm,
+ compl);
+ rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
+ compl);
+ }
}
static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
@@ -1150,15 +1158,19 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
else
be_parse_rx_compl_v0(adapter, compl, rxcp);
- /* vlanf could be wrongly set in some cards. ignore if vtm is not set */
- if ((adapter->function_mode & 0x400) && !rxcp->vtm)
- rxcp->vlanf = 0;
+ if (rxcp->vlanf) {
+ /* vlanf could be wrongly set in some cards.
+ * ignore if vtm is not set */
+ if ((adapter->function_mode & 0x400) && !rxcp->vtm)
+ rxcp->vlanf = 0;
- if (!lancer_chip(adapter))
- rxcp->vid = swab16(rxcp->vid);
+ if (!lancer_chip(adapter))
+ rxcp->vid = swab16(rxcp->vid);
- if ((adapter->pvid == rxcp->vid) && !adapter->vlan_tag[rxcp->vid])
- rxcp->vlanf = 0;
+ if ((adapter->pvid == rxcp->vid) &&
+ !adapter->vlan_tag[rxcp->vid])
+ rxcp->vlanf = 0;
+ }
/* As the compl has been parsed, reset it; we wont touch it again */
compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] = 0;
@@ -1567,12 +1579,31 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
}
}
+static u32 be_num_rxqs_want(struct be_adapter *adapter)
+{
+ if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+ !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
+ return 1 + MAX_RSS_QS; /* one default non-RSS queue */
+ } else {
+ dev_warn(&adapter->pdev->dev,
+ "No support for multiple RX queues\n");
+ return 1;
+ }
+}
+
static int be_rx_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *eq, *q, *cq;
struct be_rx_obj *rxo;
int rc, i;
+ adapter->num_rx_qs = min(be_num_rxqs_want(adapter),
+ msix_enabled(adapter) ?
+ adapter->num_msix_vec - 1 : 1);
+ if (adapter->num_rx_qs != MAX_RX_QS)
+ dev_warn(&adapter->pdev->dev,
+ "Can create only %d RX queues", adapter->num_rx_qs);
+
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
for_all_rx_queues(adapter, rxo, i) {
rxo->adapter = adapter;
@@ -1837,6 +1868,9 @@ static void be_worker(struct work_struct *work)
struct be_rx_obj *rxo;
int i;
+ if (!adapter->ue_detected && !lancer_chip(adapter))
+ be_detect_dump_ue(adapter);
+
/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
@@ -1849,9 +1883,6 @@ static void be_worker(struct work_struct *work)
be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
}
- if (!adapter->ue_detected && !lancer_chip(adapter))
- be_detect_dump_ue(adapter);
-
goto reschedule;
}
@@ -1869,8 +1900,6 @@ static void be_worker(struct work_struct *work)
be_post_rx_frags(rxo, GFP_KERNEL);
}
}
- if (!adapter->ue_detected && !lancer_chip(adapter))
- be_detect_dump_ue(adapter);
reschedule:
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -1878,51 +1907,35 @@ reschedule:
static void be_msix_disable(struct be_adapter *adapter)
{
- if (adapter->msix_enabled) {
+ if (msix_enabled(adapter)) {
pci_disable_msix(adapter->pdev);
- adapter->msix_enabled = false;
- }
-}
-
-static int be_num_rxqs_get(struct be_adapter *adapter)
-{
- if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
- return 1 + MAX_RSS_QS; /* one default non-RSS queue */
- } else {
- dev_warn(&adapter->pdev->dev,
- "No support for multiple RX queues\n");
- return 1;
+ adapter->num_msix_vec = 0;
}
}
static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */
- int i, status;
+ int i, status, num_vec;
- adapter->num_rx_qs = be_num_rxqs_get(adapter);
+ num_vec = be_num_rxqs_want(adapter) + 1;
- for (i = 0; i < (adapter->num_rx_qs + 1); i++)
+ for (i = 0; i < num_vec; i++)
adapter->msix_entries[i].entry = i;
- status = pci_enable_msix(adapter->pdev, adapter->msix_entries,
- adapter->num_rx_qs + 1);
+ status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec);
if (status == 0) {
goto done;
} else if (status >= BE_MIN_MSIX_VECTORS) {
+ num_vec = status;
if (pci_enable_msix(adapter->pdev, adapter->msix_entries,
- status) == 0) {
- adapter->num_rx_qs = status - 1;
- dev_warn(&adapter->pdev->dev,
- "Could alloc only %d MSIx vectors. "
- "Using %d RX Qs\n", status, adapter->num_rx_qs);
+ num_vec) == 0)
goto done;
- }
}
return;
done:
- adapter->msix_enabled = true;
+ adapter->num_msix_vec = num_vec;
+ return;
}
static void be_sriov_enable(struct be_adapter *adapter)
@@ -2003,8 +2016,7 @@ err_msix:
err:
dev_warn(&adapter->pdev->dev,
"MSIX Request IRQ failed - err %d\n", status);
- pci_disable_msix(adapter->pdev);
- adapter->msix_enabled = false;
+ be_msix_disable(adapter);
return status;
}
@@ -2013,7 +2025,7 @@ static int be_irq_register(struct be_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int status;
- if (adapter->msix_enabled) {
+ if (msix_enabled(adapter)) {
status = be_msix_register(adapter);
if (status == 0)
goto done;
@@ -2046,7 +2058,7 @@ static void be_irq_unregister(struct be_adapter *adapter)
return;
/* INTx */
- if (!adapter->msix_enabled) {
+ if (!msix_enabled(adapter)) {
free_irq(netdev->irq, adapter);
goto done;
}
@@ -2088,7 +2100,7 @@ static int be_close(struct net_device *netdev)
be_cq_notify(adapter, rxo->cq.id, false, 0);
}
- if (adapter->msix_enabled) {
+ if (msix_enabled(adapter)) {
vec = be_msix_vec_get(adapter, tx_eq);
synchronize_irq(vec);
@@ -2261,7 +2273,7 @@ static int be_setup(struct be_adapter *adapter)
BE_IF_FLAGS_PASS_L3L4_ERRORS;
en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS;
- if (be_multi_rxq(adapter)) {
+ if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
cap_flags |= BE_IF_FLAGS_RSS;
en_flags |= BE_IF_FLAGS_RSS;
}
@@ -2318,7 +2330,6 @@ static int be_setup(struct be_adapter *adapter)
return 0;
- be_mcc_queues_destroy(adapter);
rx_qs_destroy:
be_rx_queues_destroy(adapter);
tx_qs_destroy:
@@ -3146,8 +3157,7 @@ static void be_shutdown(struct pci_dev *pdev)
if (!adapter)
return;
- if (netif_running(adapter->netdev))
- cancel_delayed_work_sync(&adapter->work);
+ cancel_delayed_work_sync(&adapter->work);
netif_device_detach(adapter->netdev);