* [PATCH 6/8] csiostor: Chelsio FCoE offload driver submission (headers part 1).
From: Naresh Kumar Inna @ 2012-08-23 22:27 UTC (permalink / raw)
To: JBottomley, linux-scsi, dm; +Cc: netdev, naresh, chethan
In-Reply-To: <1345760873-12101-1-git-send-email-naresh@chelsio.com>
This patch contains the first set of the header files for csiostor driver.
Signed-off-by: Naresh Kumar Inna <naresh@chelsio.com>
---
drivers/scsi/csiostor/csio_defs.h | 143 ++++++
drivers/scsi/csiostor/csio_fcoe_proto.h | 843 +++++++++++++++++++++++++++++++
drivers/scsi/csiostor/csio_hw.h | 668 ++++++++++++++++++++++++
drivers/scsi/csiostor/csio_init.h | 158 ++++++
4 files changed, 1812 insertions(+), 0 deletions(-)
create mode 100644 drivers/scsi/csiostor/csio_defs.h
create mode 100644 drivers/scsi/csiostor/csio_fcoe_proto.h
create mode 100644 drivers/scsi/csiostor/csio_hw.h
create mode 100644 drivers/scsi/csiostor/csio_init.h
diff --git a/drivers/scsi/csiostor/csio_defs.h b/drivers/scsi/csiostor/csio_defs.h
new file mode 100644
index 0000000..4f1c713
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_defs.h
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_DEFS_H__
+#define __CSIO_DEFS_H__
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+
+/* Function returns */
+enum csio_retval {
+ CSIO_SUCCESS = 0,
+ CSIO_INVAL = 1,
+ CSIO_BUSY = 2,
+ CSIO_NOSUPP = 3,
+ CSIO_TIMEOUT = 4,
+ CSIO_NOMEM = 5,
+ CSIO_NOPERM = 6,
+ CSIO_RETRY = 7,
+ CSIO_EPROTO = 8,
+ CSIO_EIO = 9,
+ CSIO_CANCELLED = 10,
+};
+
+#define csio_retval_t enum csio_retval
+
+enum {
+ CSIO_FALSE = 0,
+ CSIO_TRUE = 1,
+};
+
+#define CSIO_ROUNDUP(__v, __r) (((__v) + (__r) - 1) / (__r))
+#define CSIO_INVALID_IDX 0xFFFFFFFF
+#define csio_inc_stats(elem, val) ((elem)->stats.val++)
+#define csio_dec_stats(elem, val) ((elem)->stats.val--)
+#define csio_valid_wwn(__n) ((*__n >> 4) == 0x5 ? CSIO_TRUE : \
+ CSIO_FALSE)
+#define CSIO_WORD_TO_BYTE 4
+
+static inline int
+csio_list_deleted(struct list_head *list)
+{
+ return ((list->next == list) && (list->prev == list));
+}
+
+#define csio_list_next(elem) (((struct list_head *)(elem))->next)
+#define csio_list_prev(elem) (((struct list_head *)(elem))->prev)
+
+#define csio_deq_from_head(head, elem) \
+do { \
+ if (!list_empty(head)) { \
+ *((struct list_head **)(elem)) = csio_list_next((head)); \
+ csio_list_next((head)) = \
+ csio_list_next(csio_list_next((head))); \
+ csio_list_prev(csio_list_next((head))) = (head); \
+ INIT_LIST_HEAD(*((struct list_head **)(elem))); \
+ } else \
+ *((struct list_head **)(elem)) = (struct list_head *)NULL;\
+} while (0)
+
+#define csio_deq_from_tail(head, elem) \
+do { \
+ if (!list_empty(head)) { \
+ *((struct list_head **)(elem)) = csio_list_prev((head)); \
+ csio_list_prev((head)) = \
+ csio_list_prev(csio_list_prev((head))); \
+ csio_list_next(csio_list_prev((head))) = (head); \
+ INIT_LIST_HEAD(*((struct list_head **)(elem))); \
+ } else \
+ *((struct list_head **)(elem)) = (struct list_head *)NULL;\
+} while (0)
+
+/* State machine */
+typedef void (*csio_sm_state_t)(void *, uint32_t);
+
+struct csio_sm {
+ struct list_head sm_list;
+ csio_sm_state_t sm_state;
+};
+
+#define csio_init_state(__smp, __state) \
+ (((struct csio_sm *)(__smp))->sm_state = (csio_sm_state_t)(__state))
+
+#define csio_set_state(__smp, __state) \
+ (((struct csio_sm *)(__smp))->sm_state = (csio_sm_state_t)(__state))
+
+
+#define csio_post_event(__smp, __evt) \
+ (((struct csio_sm *)(__smp))->sm_state((__smp), (uint32_t)(__evt)))
+
+#define csio_get_state(__smp) (((struct csio_sm *)(__smp))->sm_state)
+
+#define csio_match_state(__smp, __state) \
+ (csio_get_state((__smp)) == (csio_sm_state_t)(__state))
+
+#define CSIO_ASSERT(cond) \
+do { \
+ if (unlikely(!((cond)))) \
+ BUG(); \
+} while (0)
+
+#ifdef __CSIO_DEBUG__
+#define CSIO_DB_ASSERT(__c) CSIO_ASSERT((__c))
+#else
+#define CSIO_DB_ASSERT(__c)
+#endif
+
+#endif /* ifndef __CSIO_DEFS_H__ */
diff --git a/drivers/scsi/csiostor/csio_fcoe_proto.h b/drivers/scsi/csiostor/csio_fcoe_proto.h
new file mode 100644
index 0000000..32e6f43
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_fcoe_proto.h
@@ -0,0 +1,843 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_FCOE_PROTO_H__
+#define __CSIO_FCOE_PROTO_H__
+
+/* FC header type */
+#define FC_TYPE_ELS_DATA 0x1
+#define FC_TYPE_CT_DATA 0x20
+#define FC_TYPE_FCP_DATA 0x8
+
+/* FC header rctl */
+#define FC_RCTL_ELS_REQ 0x22
+#define FC_RCTL_ELS_RSP 0x23
+#define FC_RCTL_FCP_CMND 0x6
+
+/* Well known Fibre channel Address */
+#define FDMI_DID 0xFFFFFA /* Management server */
+#define NS_DID 0xFFFFFC /* Name server */
+#define FABCTL_DID 0xFFFFFD /* Fabric Controller */
+#define FABRIC_DID 0xFFFFFE /* Fabric Login */
+#define BCAST_DID 0xFFFFFF /* Broadcast */
+#define UNKNOWN_DID 0x000000 /* Unknown DID */
+#define DID_MASK 0xFFFFFF /* DID Mask */
+#define WK_DID_MASK 0xFFFFF0 /* Well known did mask */
+
+/* FC4 Device Data Frame - TYPE */
+#define FC4_FCP_TYPE 0x8 /* FCP */
+
+/* MAX FC Payload */
+#define MAX_FC_PAYLOAD 2112
+
+/*Service option: Shift & Mask bits defines */
+#define SP_CLASS_SUPPORT_EN 1 /* Class support enable */
+#define S_SP_CLASS_SUPPORT 7
+#define M_SP_CLASS_SUPPORT 1
+#define V_SP_CLASS_SUPPORT(x) ((x) << S_SP_CLASS_SUPPORT)
+#define G_SP_CLASS_SUPPORT(x) \
+ (((x) >> S_SP_CLASS_SUPPORT) & M_SP_CLASS_SUPPORT)
+
+/* Class service parameters */
+struct csio_class_sp {
+ uint8_t serv_option; /* Service option */
+ uint8_t rsvd1;
+ uint8_t init_ctl_option; /* initiator cntl option */
+ uint8_t rsvd2;
+ uint8_t rcv_ctl_option; /* receiver cntl option */
+ uint8_t rsvd3;
+ uint16_t rcv_data_sz; /* receive data size */
+ uint16_t concurrent_seq; /* Total concurent sequence */
+ uint16_t ee_credit; /* EE credit */
+ uint16_t openseq_per_xchg; /* Open sequence per exch */
+ uint16_t rsvd4;
+};
+
+/* Common service parameters defines */
+
+/* FC Phy version */
+#define FC_PH_VER3 0x20
+
+/* WORD1 (31:16) flags: shift & mask bit defines */
+/* NPIV support */
+#define MULTIPLE_NPORT_ID_SUPPORT_EN 1
+#define S_MULTIPLE_NPORT_ID_SUPPORT 15
+#define M_MULTIPLE_NPORT_ID_SUPPORT 1
+#define V_MULTIPLE_NPORT_ID_SUPPORT(x) ((x) << S_MULTIPLE_NPORT_ID_SUPPORT)
+#define G_MULTIPLE_NPORT_ID_SUPPORT(x) (((x) >> S_MULTIPLE_NPORT_ID_SUPPORT) \
+ & M_MULTIPLE_NPORT_ID_SUPPORT)
+
+/* Continuously increasing relative offset */
+#define CONTI_INCR_OFFSET_SUPPORT_EN 1
+#define S_CONTI_INCR_OFFSET_SUPPORT 15
+#define M_CONTI_INCR_OFFSET_SUPPORT 1
+#define V_CONTI_INCR_OFFSET_SUPPORT(x) ((x) << S_CONTI_INCR_OFFSET_SUPPORT)
+#define G_CONTI_INCR_OFFSET_SUPPORT(x) (((x) >> S_CONTI_INCR_OFFSET_SUPPORT) \
+ & M_CONTI_INCR_OFFSET_SUPPORT)
+/* Continuously increasing relative offset */
+#define CLEAN_ADDR_EN 1
+#define S_CLEAN_ADDR 15
+#define M_CLEAN_ADDR 1
+#define V_CLEAN_ADDR(x) ((x) << S_CLEAN_ADDR)
+#define G_CLEAN_ADDR(x) (((x) >> S_CLEAN_ADDR) & M_CLEAN_ADDR)
+
+/* NPIV supported by Fabric */
+#define NPIV_SUPPORTED_EN 1
+#define S_NPIV_SUPPORTED 13
+#define M_NPIV_SUPPORTED 1
+#define V_NPIV_SUPPORTED(x) ((x) << S_NPIV_SUPPORTED)
+#define G_NPIV_SUPPORTED(x) (((x) >> S_NPIV_SUPPORTED) & M_NPIV_SUPPORTED)
+
+/* N_Port or F_Port */
+#define FABRIC_PORT 1
+#define S_FABRIC_PORT 12
+#define M_FABRIC_PORT 1
+#define V_FABRIC_PORT(x) ((x) << S_FABRIC_PORT)
+#define G_FABRIC_PORT(x) (((x) >> S_FABRIC_PORT) & M_FABRIC_PORT)
+
+/* Alternate B2B credit management support */
+#define ALT_B2B_CREDIT_MGMT_SUPPORT_EN 1
+#define S_ALT_B2B_CREDIT_MGMT_SUPPORT 11
+#define M_ALT_B2B_CREDIT_MGMT_SUPPORT 1
+#define V_ALT_B2B_CREDIT_MGMT_SUPPORT(x) \
+ ((x) << S_ALT_B2B_CREDIT_MGMT_SUPPORT)
+#define G_ALT_B2B_CREDIT_MGMT_SUPPORT(x) \
+ (((x) >> S_ALT_B2B_CREDIT_MGMT_SUPPORT) & M_ALT_B2B_CREDIT_MGMT_SUPPORT)
+
+
+/* WORD2 (31: 0) : shift and mask bit defines */
+#define S_MAX_SEQ_CNT 16
+#define M_MAX_SEQ_CNT 0xFFFF
+#define V_MAX_SEQ_CNT(x) ((x) << S_MAX_SEQ_CNT)
+#define G_MAX_SEQ_CNT(x) (((x) >> S_MAX_SEQ_CNT) & M_MAX_SEQ_CNT)
+
+#define S_REL_OFFSET_BY_CATEGORY 0
+#define M_REL_OFFSET_BY_CATEGORY 0xFFFF
+#define V_REL_OFFSET_BY_CATEGORY(x) ((x) << S_REL_OFFSET_BY_CATEGORY)
+#define G_REL_OFFSET_BY_CATEGORY(x) \
+ (((x) >> S_REL_OFFSET_BY_CATEGORY) & M_REL_OFFSET_BY_CATEGORY)
+
+/* Common service parameters */
+struct csio_cmn_sp {
+ uint8_t hi_ver; /* High PH version */
+ uint8_t lo_ver; /* low PH version */
+ uint16_t bb_credit; /* B2B credit */
+ uint16_t word1_flags; /* Word1 Flags (31:16)*/
+ uint16_t rcv_sz; /* Receive data size */
+ union {
+ uint32_t maxsq_reloff; /* Max seq / Relative offset */
+ uint32_t r_a_tov; /* R_A_TOV */
+ } un1;
+ uint32_t e_d_tov; /*E_D_TOV */
+};
+
+struct csio_service_parms {
+ struct csio_cmn_sp csp; /* Common service parms */
+ uint8_t wwpn[8]; /* WWPN */
+ uint8_t wwnn[8]; /* WWNN */
+ struct csio_class_sp clsp[4]; /* Class service params */
+ uint8_t vvl[16]; /* Vendor version level */
+};
+
+/* Common Transport (CT) defines */
+#define CT_BASIC_IU_LEN 0x10
+#define CT_REVISION 0x1
+
+/* GS Types */
+#define CT_GS_MGMT_SERVICE 0xFA
+#define CT_GS_TIME_SERVICE 0xFB
+#define CT_GS_DIR_SERVICE 0xFC
+#define CT_GS_FABRIC_CNTL_SERVICE 0xFD
+
+/* Directory service Subtypes */
+#define CT_DIR_SERVICE_NAME_SERVER 0x02
+
+/* FDMI MGMT service Subtypes */
+#define CT_FDMI_HBA_MGMT_SERVER 0x10
+
+/* CT Response code */
+#define CT_RESPONSE_FS_RJT 0x8001
+#define CT_RESPONSE_FS_ACC 0x8002
+
+/* CT Reason code */
+#define CT_NO_ADDITIONAL_EXPLANATION 0x00
+#define CT_INVALID_COMMAND 0x01
+#define CT_INVALID_VERSION_LEVEL 0x02
+#define CT_LOGICAL_ERROR 0x03
+#define CT_INVALID_IU_SIZE 0x04
+#define CT_LOGICAL_BUSY 0x05
+#define CT_PROTOCOL_ERROR 0x07
+#define CT_UNABLE_TO_PERFORM_CMD_REQ 0x09
+#define CT_CMD_NOT_SUPPORTED 0x0B
+#define CT_VENDOR_UNIQUE 0xff
+
+/* Name Server explanation for Reason code CT_UNABLE_TO_PERFORM_CMD_REQ */
+#define CT_NS_PORT_ID_NOT_REG 0x01
+#define CT_NS_PORT_NAME_NOT_REG 0x02
+#define CT_NS_NODE_NAME_NOT_REG 0x03
+#define CT_NS_CLASS_OF_SERVICE_NOT_REG 0x04
+#define CT_NS_IP_ADDRESS_NOT_REG 0x05
+#define CT_NS_IPA_NOT_REG 0x06
+#define CT_NS_FC4_TYPES_NOT_REG 0x07
+#define CT_NS_SYMBOLIC_PORT_NAME_NOT_REG 0x08
+#define CT_NS_SYMBOLIC_NODE_NAME_NOT_REG 0x09
+#define CT_NS_PORT_TYPE_NOT_REG 0x0A
+#define CT_NS_ACCESS_DENIED 0x10
+#define CT_NS_INVALID_PORT_ID 0x11
+#define CT_NS_DATABASE_EMPTY 0x12
+
+/* Name Server Command Codes */
+#define CT_NS_GA_NXT 0x0100
+#define CT_NS_GPN_ID 0x0112
+#define CT_NS_GNN_ID 0x0113
+#define CT_NS_GCS_ID 0x0114
+#define CT_NS_GFT_ID 0x0117
+#define CT_NS_GSPN_ID 0x0118
+#define CT_NS_GPT_ID 0x011A
+#define CT_NS_GFF_ID 0x011F
+#define CT_NS_GID_PN 0x0121
+#define CT_NS_GID_NN 0x0131
+#define CT_NS_GIP_NN 0x0135
+#define CT_NS_GIPA_NN 0x0136
+#define CT_NS_GSNN_NN 0x0139
+#define CT_NS_GNN_IP 0x0153
+#define CT_NS_GIPA_IP 0x0156
+#define CT_NS_GID_FT 0x0171
+#define CT_NS_GPN_FT 0x0172
+#define CT_NS_GID_PT 0x01A1
+#define CT_NS_RPN_ID 0x0212
+#define CT_NS_RNN_ID 0x0213
+#define CT_NS_RCS_ID 0x0214
+#define CT_NS_RFT_ID 0x0217
+#define CT_NS_RSPN_ID 0x0218
+#define CT_NS_RPT_ID 0x021A
+#define CT_NS_RFF_ID 0x021F
+#define CT_NS_RIP_NN 0x0235
+#define CT_NS_RIPA_NN 0x0236
+#define CT_NS_RSNN_NN 0x0239
+#define CT_NS_DA_ID 0x0300
+
+/* FDMI HBA management Server Command Codes */
+#define CT_FDMI_HBA_GRHL 0x100 /* Get registered HBA list */
+#define CT_FDMI_HBA_GHAT 0x101 /* Get HBA attributes */
+#define CT_FDMI_HBA_GRPL 0x102 /* Get registered Port list */
+#define CT_FDMI_HBA_GPAT 0x110 /* Get Port attributes */
+#define CT_FDMI_HBA_RHBA 0x200 /* Register HBA */
+#define CT_FDMI_HBA_RHAT 0x201 /* Register HBA atttributes */
+#define CT_FDMI_HBA_RPRT 0x210 /* Register Port */
+#define CT_FDMI_HBA_RPA 0x211 /* Register Port attributes */
+#define CT_FDMI_HBA_DHBA 0x300 /* De-register HBA */
+#define CT_FDMI_HBA_DPRT 0x310 /* De-register Port */
+
+/* HBA Attribute Types */
+#define NODE_NAME 0x1
+#define MANUFACTURER 0x2
+#define SERIAL_NUMBER 0x3
+#define MODEL 0x4
+#define MODEL_DESCRIPTION 0x5
+#define HARDWARE_VERSION 0x6
+#define DRIVER_VERSION 0x7
+#define OPTION_ROM_VERSION 0x8
+#define FIRMWARE_VERSION 0x9
+#define OS_NAME_VERSION 0xa
+#define MAX_CT_PAYLOAD_LEN 0xb
+
+/* Port Attrubute Types */
+#define SUPPORTED_FC4_TYPES 0x1
+#define SUPPORTED_SPEED 0x2
+#define PORT_SPEED 0x3
+#define MAX_FRAME_LEN 0x4
+#define OS_DEVICE_NAME 0x5
+#define HOST_NAME 0x6
+
+#define CSIO_HBA_PORTSPEED_1GBIT 0x0001 /* 1 GBit/sec */
+#define CSIO_HBA_PORTSPEED_2GBIT 0x0002 /* 2 GBit/sec */
+#define CSIO_HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */
+#define CSIO_HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */
+#define CSIO_HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
+#define CSIO_HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
+#define CSIO_HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */
+
+/* Port Types */
+#define CT_PORT_TYPE_N_PORT 0x01
+#define CT_PORT_TYPE_NL_PORT 0x02
+#define CT_PORT_TYPE_FNL_PORT 0x03
+#define CT_PORT_TYPE_IP 0x04
+#define CT_PORT_TYPE_FCP 0x08
+#define CT_PORT_TYPE_NX_PORT 0x7F
+#define CT_PORT_TYPE_F_PORT 0x81
+#define CT_PORT_TYPE_FL_PORT 0x82
+#define CT_PORT_TYPE_E_PORT 0x84
+
+/* FC4 Feature bit defination */
+#define FC4_FEATURE_TARGET_EN 1
+#define S_FC4_FEATURE_TARGET 0
+#define M_FC4_FEATURE_TARGET 1
+#define V_FC4_FEATURE_TARGET(x) ((x) << S_FC4_FEATURE_TARGET)
+#define G_FC4_FEATURE_TARGET(x) \
+ (((x) >> S_FC4_FEATURE_TARGET) & M_FC4_FEATURE_TARGET)
+
+#define FC4_FEATURE_INITIATOR_EN 1
+#define S_FC4_FEATURE_INITIATOR 1
+#define M_FC4_FEATURE_INITIATOR 1
+#define V_FC4_FEATURE_INITIATOR(x) ((x) << S_FC4_FEATURE_INITIATOR)
+#define G_FC4_FEATURE_INITIATOR(x) \
+ (((x) >> S_FC4_FEATURE_INITIATOR) & M_FC4_FEATURE_INITIATOR)
+
+/* GPN_FT ACC Control bit defination */
+#define GPN_FT_ACC_CONTROL_EN 1
+#define S_GPN_FT_ACC_CONTROL 31
+#define M_GPN_FT_ACC_CONTROL 1
+#define V_GPN_FT_ACC_CONTROL(x) ((x) << S_GPN_FT_ACC_CONTROL)
+#define G_GPN_FT_ACC_CONTROL(x) \
+ (((x) >> S_GPN_FT_ACC_CONTROL) & M_GPN_FT_ACC_CONTROL)
+
+/* CT command */
+struct csio_ct_cmd {
+ uint8_t rev; /* Revision */
+ uint8_t in_id[3]; /* Unused */
+ uint8_t gs_type; /* Type of service */
+ uint8_t gs_subtype; /* Sub type */
+ uint8_t opt; /* Options */
+ uint8_t rsvd1;
+ uint16_t op; /* Command or response code */
+ uint16_t size; /* Maximum or Residual size */
+ uint8_t rsvd2;
+ uint8_t reason_code; /* Reason code */
+ uint8_t explanation; /* Explanation code */
+ uint8_t vendor_unique; /* Vendor specific reason code */
+
+ union {
+ uint32_t port_id; /* Port_id list for GID_FT ACC */
+
+ struct gid_ft {
+ uint8_t port_type; /* Port Type */
+ uint8_t domain_scope; /* Domain scope */
+ uint8_t area_scope; /* Area scope */
+ uint8_t fc4_type; /* FC4 Type = FCP(0x8) */
+ } gid_ft;
+
+ struct gpn_ft {
+ uint8_t rsvd;
+ uint8_t domain_scope; /* Domain scope */
+ uint8_t area_scope; /* Area scope */
+ uint8_t fc4_type; /* FC4 Type = FCP(0x8) */
+ } gpn_ft;
+
+ /* Port_id & Port name list for GPN_FT ACC */
+ struct gpn_ft_acc {
+ uint32_t port_id; /* port id */
+ uint32_t rsvd;
+ uint8_t wwpn[8]; /* Port name */
+ } gpn_ft_acc;
+
+ struct rft_id {
+ uint32_t port_id; /* port id */
+ uint16_t rsvd1;
+ uint8_t fcp; /* FCP Type */
+ uint8_t rsvd2;
+ uint8_t rsvd3[28];
+ } rft_id;
+
+ struct rnn_id {
+ uint32_t port_id; /* Port id */
+ uint8_t wwnn[8]; /* Node name */
+ } rnn_id;
+
+ struct da_id {
+ uint32_t port_id; /* Port id */
+ } da_id;
+
+ struct rff_id {
+ uint32_t port_id; /* Port id */
+ uint8_t rsvd1[2];
+ uint8_t fc4_fbits; /* FC4 feature bits */
+ uint8_t fc4_type; /* FC4 Type = FCP(0x8) */
+ } rff_id;
+ } un;
+};
+
+#define csio_ct_rsp(cp) (((struct csio_ct_cmd *) cp)->op)
+#define csio_ct_reason(cp) (((struct csio_ct_cmd *) cp)->reason_code)
+#define csio_ct_expl(cp) (((struct csio_ct_cmd *) cp)->explanation)
+#define csio_ct_get_pld(cp) ((void *)(((uint8_t *)cp) + CT_BASIC_IU_LEN))
+
+static inline void
+csio_fill_ct_iu(void *buf, uint8_t type, uint8_t sub_type,
+ uint16_t op)
+{
+ struct csio_ct_cmd *cmd = (struct csio_ct_cmd *) buf;
+ cmd->rev = CT_REVISION;
+ cmd->gs_type = type;
+ cmd->gs_subtype = sub_type;
+ cmd->op = op;
+}
+
+/* FDMI HBA cmd */
+
+/* Attribute entry */
+struct csio_attrib_entry {
+ uint16_t type; /* Entry type */
+ uint16_t len; /* Entry length */
+ union {
+ uint8_t string[256]; /* Attribute value in string */
+ uint32_t integer; /* Attribute value in integer */
+ } val;
+};
+
+
+/* attribute block */
+struct csio_attrib_block {
+ uint32_t entry_count; /* Entry count */
+ struct csio_attrib_entry entry; /* list of attributes */
+};
+
+/* HBA identifier */
+struct csio_hba_identifier {
+ uint8_t wwpn[8]; /* Port name */
+};
+
+/* Port entry */
+struct csio_port_entry {
+ uint8_t wwpn[8]; /* Port name */
+};
+
+/* register port list */
+struct csio_reg_port_list {
+ uint32_t entry_count; /* Entry count */
+ struct csio_port_entry entry; /* list of port entry */
+};
+
+/* register HBA */
+struct csio_reg_hba {
+ struct csio_hba_identifier id; /* HBA identifier */
+ struct csio_reg_port_list port_list; /* port entry list */
+};
+
+/* register HBA attributes */
+struct csio_reg_hba_attrib {
+ struct csio_hba_identifier id; /* HBA identifier */
+ struct csio_attrib_block attrib_list; /* Attribute list */
+};
+
+/* register Port attributes */
+struct csio_reg_port_attrib {
+ uint8_t wwpn[8]; /* Port name */
+ struct csio_attrib_block attrib_list; /* Attribute list */
+};
+
+/* Get register hba list(GRHL) accept payload */
+struct csio_grhl_acc_pld {
+ uint32_t entry_count; /* Entry count */
+ struct csio_hba_identifier id; /* HBA identifier list */
+};
+
+/* Get register port list(GRPL) accept payload */
+struct csio_grpl_acc_pld {
+ uint32_t entry_count; /* Entry count */
+ struct csio_port_entry entry; /* port entry list */
+};
+
+/* Get port attributes (GPAT) accept payload */
+struct csio_gpat_acc_pld {
+ struct csio_attrib_block attrib_list; /* Attribute list */
+};
+
+/* ELS CMD HDR length */
+#define ELS_CMD_HDR_LEN 0x4
+
+/* ELS COMMAND CODES */
+#define ELS_CMD_CODE_MASK 0xff
+#define ELS_CMD_CODE_LS_RJT 0x01
+#define ELS_CMD_CODE_ACC 0x02
+#define ELS_CMD_CODE_PLOGI 0x03
+#define ELS_CMD_CODE_FLOGI 0x04
+#define ELS_CMD_CODE_LOGO 0x05
+#define ELS_CMD_CODE_RES 0x08
+#define ELS_CMD_CODE_RSS 0x09
+#define ELS_CMD_CODE_RSI 0x0A
+#define ELS_CMD_CODE_ESTS 0x0B
+#define ELS_CMD_CODE_ESTC 0x0C
+#define ELS_CMD_CODE_ADVC 0x0D
+#define ELS_CMD_CODE_RTV 0x0E
+#define ELS_CMD_CODE_RLS 0x0F
+#define ELS_CMD_CODE_ECHO 0x10
+#define ELS_CMD_CODE_TEST 0x11
+#define ELS_CMD_CODE_PRLI 0x20
+#define ELS_CMD_CODE_PRLO 0x21
+#define ELS_CMD_CODE_PDISC 0x50
+#define ELS_CMD_CODE_FDISC 0x51
+#define ELS_CMD_CODE_ADISC 0x52
+#define ELS_CMD_CODE_RPS 0x56
+#define ELS_CMD_CODE_RPL 0x57
+#define ELS_CMD_CODE_RSCN 0x61
+#define ELS_CMD_CODE_SCR 0x62
+#define ELS_CMD_CODE_RNID 0x78
+#define ELS_CMD_CODE_LIRR 0x7A
+
+/* LS_RJT reason codes */
+#define LS_RJT_INVALID_CMD 0x01
+#define LS_RJT_LOGICAL_ERR 0x03
+#define LS_RJT_LOGICAL_BSY 0x05
+#define LS_RJT_PROTOCOL_ERR 0x07
+#define LS_RJT_UNABLE_TPC 0x09
+#define LS_RJT_CMD_UNSUPPORTED 0x0B
+#define LS_RJT_VENDOR_UNIQUE 0xFF
+
+/* LS_RJT reason explanation */
+#define LS_RJT_EXPL_NONE 0x00
+#define LS_RJT_EXPL_SPARM_OPTIONS 0x01
+#define LS_RJT_EXPL_SPARM_ICTL 0x03
+#define LS_RJT_EXPL_SPARM_RCTL 0x05
+#define LS_RJT_EXPL_SPARM_RCV_SIZE 0x07
+#define LS_RJT_EXPL_SPARM_CONCUR_SEQ 0x09
+#define LS_RJT_EXPL_SPARM_CREDIT 0x0B
+#define LS_RJT_EXPL_INVALID_PNAME 0x0D
+#define LS_RJT_EXPL_INVALID_NNAME 0x0E
+#define LS_RJT_EXPL_INVALID_CSP 0x0F
+#define LS_RJT_EXPL_INVALID_ASSOC_HDR 0x11
+#define LS_RJT_EXPL_ASSOC_HDR_REQ 0x13
+#define LS_RJT_EXPL_INVALID_O_SID 0x15
+#define LS_RJT_EXPL_INVALID_OX_RX 0x17
+#define LS_RJT_EXPL_CMD_IN_PROGRESS 0x19
+#define LS_RJT_EXPL_PORT_LOGIN_REQ 0x1E
+#define LS_RJT_EXPL_INVALID_NPORT_ID 0x1F
+#define LS_RJT_EXPL_INVALID_SEQ_ID 0x21
+#define LS_RJT_EXPL_INVALID_XCHG 0x23
+#define LS_RJT_EXPL_INACTIVE_XCHG 0x25
+#define LS_RJT_EXPL_RQ_REQUIRED 0x27
+#define LS_RJT_EXPL_OUT_OF_RESOURCE 0x29
+#define LS_RJT_EXPL_CANT_GIVE_DATA 0x2A
+#define LS_RJT_EXPL_REQ_UNSUPPORTED 0x2C
+
+/* PRLI Page and Payload length */
+#define PRLI_PAGE_LEN 0x10
+#define PRLI_PAYLOAD_LEN 0x14
+
+/* PRLI/PRLO PROCESS FLAGS */
+/* Originator Proc Associator valid */
+#define PRLILO_ORG_PA_VALID 1
+#define S_PRLILO_ORG_PA_VALID 7
+#define M_PRLILO_ORG_PA_VALID 1
+#define V_PRLILO_ORG_PA_VALID(x) ((x) << S_PRLILO_ORG_PA_VALID)
+#define G_PRLILO_ORG_PA_VALID(x) \
+ (((x) >> S_PRLILO_ORG_PA_VALID) & M_PRLILO_ORG_PA_VALID)
+
+/* Responder Proc Associator valid */
+#define PRLILO_RSP_PA_VALID 1
+#define S_PRLILO_RSP_PA_VALID 6
+#define M_PRLILO_RSP_PA_VALID 1
+#define V_PRLILO_RSP_PA_VALID(x) ((x) << S_PRLILO_RSP_PA_VALID)
+#define G_PRLILO_RSP_PA_VALID(x) \
+ (((x) >> S_PRLILO_RSP_PA_VALID) & M_PRLILO_RSP_PA_VALID)
+
+/* Image pair established */
+#define PRLILO_IMG_PAIR_ESTB 1
+#define S_PRLILO_IMG_PAIR_ESTB 5
+#define M_PRLILO_IMG_PAIR_ESTB 1
+#define V_PRLILO_IMG_PAIR_ESTB(x) ((x) << S_PRLILO_IMG_PAIR_ESTB)
+#define G_PRLILO_IMG_PAIR_ESTB(x) \
+ (((x) >> S_PRLILO_IMG_PAIR_ESTB) & M_PRLILO_IMG_PAIR_ESTB)
+
+/* PRLI Response code */
+#define PRLI_RSP_CODE
+#define S_PRLI_RSP 0
+#define M_PRLI_RSP 0xf
+#define V_PRLI_RSP(x) ((x) << S_PRLI_RSP)
+#define G_PRLI_RSP(x) \
+ (((x) >> S_PRLI_RSP) & M_PRLI_RSP)
+
+/* PRLI Service Parameter flags */
+/* FCP Write xfer ready disabled */
+#define PRLI_FCP_WRITE_XFER_RD_DIS 1
+#define S_PRLI_FCP_WRITE_XFER_RD_DIS 0
+#define M_PRLI_FCP_WRITE_XFER_RD_DIS 1
+#define V_PRLI_FCP_WRITE_XFER_RD_DIS(x) ((x) << S_PRLI_FCP_WRITE_XFER_RD_DIS)
+#define G_PRLI_FCP_WRITE_XFER_RD_DIS(x) \
+ (((x) >> S_PRLI_FCP_WRITE_XFER_RD_DIS) & M_PRLI_FCP_WRITE_XFER_RD_DIS)
+
+/* FCP read xfer ready disabled */
+#define PRLI_FCP_READ_XFER_RD_DIS 1
+#define S_PRLI_FCP_READ_XFER_RD_DIS 1
+#define M_PRLI_FCP_READ_XFER_RD_DIS 1
+#define V_PRLI_FCP_READ_XFER_RD_DIS(x) ((x) << S_PRLI_FCP_READ_XFER_RD_DIS)
+#define G_PRLI_FCP_READ_XFER_RD_DIS(x) \
+ (((x) >> S_PRLI_FCP_READ_XFER_RD_DIS) & M_PRLI_FCP_READ_XFER_RD_DIS)
+
+/* FCP data response mix disabled */
+#define PRLI_FCP_DATA_RSP_MIX_DIS 1
+#define S_PRLI_FCP_DATA_RSP_MIX_DIS 2
+#define M_PRLI_FCP_DATA_RSP_MIX_DIS 1
+#define V_PRLI_FCP_DATA_RSP_MIX_DIS(x) ((x) << S_PRLI_FCP_DATA_RSP_MIX_DIS)
+#define G_PRLI_FCP_DATA_RSP_MIX_DIS(x) \
+ (((x) >> S_PRLI_FCP_DATA_RSP_MIX_DIS) & M_PRLI_FCP_DATA_RSP_MIX_DIS)
+
+/* FCP cmd data mix disabled */
+#define PRLI_FCP_CMD_DATA_MIX_DIS 1
+#define S_PRLI_FCP_CMD_DATA_MIX_DIS 3
+#define M_PRLI_FCP_CMD_DATA_MIX_DIS 1
+#define V_PRLI_FCP_CMD_DATA_MIX_DIS(x) ((x) << S_PRLI_FCP_CMD_DATA_MIX_DIS)
+#define G_PRLI_FCP_CMD_DATA_MIX_DIS(x) \
+ (((x) >> S_PRLI_FCP_CMD_DATA_MIX_DIS) & M_PRLI_FCP_CMD_DATA_MIX_DIS)
+
+/* FCP Target function */
+#define PRLI_FCP_TARGET_FUNC 1
+#define S_PRLI_FCP_TARGET_FUNC 4
+#define M_PRLI_FCP_TARGET_FUNC 1
+#define V_PRLI_FCP_TARGET_FUNC(x) ((x) << S_PRLI_FCP_TARGET_FUNC)
+#define G_PRLI_FCP_TARGET_FUNC(x) \
+ (((x) >> S_PRLI_FCP_TARGET_FUNC) & M_PRLI_FCP_TARGET_FUNC)
+
+/* FCP Initiator function */
+#define PRLI_FCP_INITIATOR_FUNC 1
+#define S_PRLI_FCP_INITIATOR_FUNC 5
+#define M_PRLI_FCP_INITIATOR_FUNC 1
+#define V_PRLI_FCP_INITIATOR_FUNC(x) ((x) << S_PRLI_FCP_INITIATOR_FUNC)
+#define G_PRLI_FCP_INITIATOR_FUNC(x) \
+ (((x) >> S_PRLI_FCP_INITIATOR_FUNC) & M_PRLI_FCP_INITIATOR_FUNC)
+
+/* FCP Data overlay */
+#define PRLI_FCP_DATA_OVERLAY 1
+#define S_PRLI_FCP_DATA_OVERLAY 6
+#define M_PRLI_FCP_DATA_OVERLAY 1
+#define V_PRLI_FCP_DATA_OVERLAY(x) ((x) << S_PRLI_FCP_DATA_OVERLAY)
+#define G_PRLI_FCP_DATA_OVERLAY(x) \
+ (((x) >> S_PRLI_FCP_DATA_OVERLAY) & M_PRLI_FCP_DATA_OVERLAY)
+
+/* FCP confirmed completion */
+#define PRLI_FCP_CONF_COMPL_ALLOWED 1
+#define S_PRLI_FCP_CONF_COMPL_ALLOWED 7
+#define M_PRLI_FCP_CONF_COMPL_ALLOWED 1
+#define V_PRLI_FCP_CONF_COMPL_ALLOWED(x) ((x) << S_PRLI_FCP_CONF_COMPL_ALLOWED)
+#define G_PRLI_FCP_CONF_COMPL_ALLOWED(x) \
+ (((x) >> S_PRLI_FCP_CONF_COMPL_ALLOWED) & M_PRLI_FCP_CONF_COMPL_ALLOWED)
+
+/* FCP retry */
+#define PRLI_FCP_RETRY 1
+#define S_PRLI_FCP_RETRY 8
+#define M_PRLI_FCP_RETRY 1
+#define V_PRLI_FCP_RETRY(x) ((x) << S_PRLI_FCP_RETRY)
+#define G_PRLI_FCP_RETRY(x) (((x) >> S_PRLI_FCP_RETRY) & M_PRLI_FCP_RETRY)
+
+/* FCP Task retry id request */
+#define PRLI_FCP_TASK_ID_REQ 1
+#define S_PRLI_FCP_TASK_ID_REQ 9
+#define M_PRLI_FCP_TASK_ID_REQ 1
+#define V_PRLI_FCP_TASK_ID_REQ(x) ((x) << S_PRLI_FCP_TASK_ID_REQ)
+#define G_PRLI_FCP_TASK_ID_REQ(x) \
+ (((x) >> S_PRLI_FCP_TASK_ID_REQ) & M_PRLI_FCP_TASK_ID_REQ)
+
+/* SCR Function */
+#define SCR_FUNCTION_FABRIC 0x01
+#define SCR_FUNCTION_NPORT 0x02
+#define SCR_FUNCTION_FULL 0x03
+#define SCR_FUNCTION_CLEAR 0xFF
+
+/* PRLI accept response code */
+#define PRLI_REQ_COMPLETED 0x1
+#define PRLI_RES_UNAVAIL 0x2
+#define PRLI_INIT_NOT_COMPLETE 0x3
+#define PRLI_RESP_PA_NO_FOUND 0x4
+#define PRLI_REQ_CONDITIONAL 0x5
+#define PRLI_RECP_PRECONFIG 0x6
+#define PRLI_MULTIPAGE_REQ_FAILED 0x7
+#define PRLI_INVALID_SP 0x8
+
+
+/* MAX RETIRES */
+#define MAX_ELS_RETRY 3
+#define ECM_MIN_TMO 1000 /* Minimum timeout value for req */
+
+/* ELS request */
+struct csio_els_cmd {
+ uint8_t op; /* ELS command code*/
+ uint8_t byte1;
+ uint8_t byte2;
+ uint8_t byte3;
+
+ union {
+ struct ls_rjt {
+ uint8_t rsvd1;
+ uint8_t reason_code; /* Reason code */
+ uint8_t reason_exp; /* Explanation */
+ uint8_t vendor_unique; /* Vendor unique code */
+ } ls_rjt;
+
+ struct ls_logi {
+ /* Service Parameters */
+ struct csio_service_parms sp;
+ } ls_logi;
+
+ struct logo {
+ uint32_t nport_id; /* NPort Id */
+ uint8_t wwpn[8]; /* Port name */
+ } logo;
+
+ struct prli {
+ uint8_t type; /* Type code */
+ uint8_t rsvd1;
+ uint8_t proc_flags; /* Process Flags */
+ uint8_t rsvd2;
+
+ /* Originator Process Associator */
+ uint32_t ori_proc_assoc;
+
+ /* Responder Process Associator */
+ uint32_t rsp_proc_assoc;
+
+ /* Service parameter flags */
+ uint32_t serv_parms_flags;
+ } prli;
+
+ struct prlo {
+ uint8_t type; /* Type code */
+ uint8_t rsvd1;
+ uint8_t proc_flags; /* Process flags */
+ uint8_t rsvd2;
+
+ /* Originator Process Associator */
+ uint32_t ori_proc_assoc;
+
+ /* Responder Process Associator */
+ uint32_t rsp_proc_assoc;
+ uint32_t rsvd3;
+ } prlo;
+
+ struct adisc {
+ uint32_t hard_addr; /* Hard address of originator */
+ uint8_t wwpn[8]; /* Port name */
+ uint8_t wwnn[8]; /* Node name */
+ uint32_t nport_id; /* Nport id */
+ } adisc;
+
+ struct scr {
+ uint8_t rsvd[3];
+ uint8_t func; /* SCR Function */
+ } scr;
+
+ struct rscn {
+ uint32_t nport_id; /* Nport id list */
+ } rscn;
+ } un;
+};
+
+/* FCP defines */
+/*
+ * pri_ta.
+ */
+#define FCP_PTA_SIMPLE 0x0 /* simple queue tag */
+#define FCP_PTA_HEADQ 0x1 /* head of queue tag */
+#define FCP_PTA_ORDERED 0x2 /* ordered task attribute */
+#define FCP_PTA_ACA 0x4 /* auto. contigent allegiance */
+#define FCP_PTA_UNTAGGED 0x5
+
+#define FCP_PRI_SHIFT 3 /* priority field starts
+ * in bit 3
+ */
+#define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority
+ * field
+ */
+
+/*
+ * tm_flags - task management flags field.
+ */
+#define FCP_TMF_ABT_TASK_SET 0x02 /* abort task set */
+#define FCP_TMF_CLR_TASK_SET 0x04 /* clear task set */
+#define FCP_TMF_BUS_RESET 0x08 /* bus reset */
+#define FCP_TMF_LUN_RESET 0x10 /* LUN reset */
+#define FCP_TMF_TGT_RESET 0x20 /* Target reset */
+#define FCP_TMF_CLR_ACA 0x40 /* clear ACA condition */
+#define FCP_TMF_TERM_TASK 0x80 /* Terminate task */
+
+/*
+ * flags.
+ * Bits 7:2 are the additional FCP_CDB length / 4.
+ */
+#define FCP_CFL_LEN_MASK 0xfc /* mask for additional length */
+#define FCP_CFL_LEN_SHIFT 2 /* shift bits for additional length */
+#define FCP_CFL_RDDATA 0x02 /* read data */
+#define FCP_CFL_WRDATA 0x01 /* write data */
+
+struct csio_fcp_cmnd {
+ uint8_t lun[8]; /* logical unit number */
+ uint8_t cmdref; /* commmand reference number */
+ uint8_t pri_ta; /* priority and task
+ * attribute
+ */
+ uint8_t tm_flags; /* task management flags */
+ uint8_t flags; /* additional len & flags */
+ uint8_t cdb[16]; /* CDB */
+ uint32_t dl; /* data length */
+};
+
+/* Response Flags */
+#define FCP_BIDI_RSP 0x80 /* bidirectional read rsp */
+#define FCP_BIDI_READ_UNDER 0x40 /* bidi read underrun */
+#define FCP_BIDI_READ_OVER 0x20 /* bidi read overrun */
+#define FCP_CONF_REQ 0x10 /* confirmation requested */
+#define FCP_RESID_UNDER 0x08 /* transfer shorter than
+ * expected
+ */
+#define FCP_RESID_OVER 0x04 /* DL insufficient for
+ * full transfer
+ */
+#define FCP_SNS_LEN_VAL 0x02 /* SNS_LEN field is valid */
+#define FCP_RSP_LEN_VAL 0x01 /* RSP_LEN field is valid */
+
+/* Response codes */
+#define FCP_TMF_CMPL 0x00
+#define FCP_DATA_LEN_INVALID 0x01
+#define FCP_CMND_FIELDS_INVALID 0x02
+#define FCP_DATA_PARAM_MISMATCH 0x03
+#define FCP_TMF_REJECTED 0x04
+#define FCP_TMF_FAILED 0x05
+#define FCP_TMF_SUCCEEDED 0x05
+#define FCP_TMF_INVALID_LUN 0x09
+
+struct csio_fcp_resp {
+ uint8_t rsvd0[8];
+ uint16_t retry_delay; /* retry delay timer */
+ uint8_t flags; /* flags */
+ uint8_t scsi_status; /* SCSI status code */
+ uint32_t resid; /* Residual bytes */
+ uint32_t sns_len; /* Length of sense data */
+ uint32_t rsp_len; /* Length of response */
+ uint8_t rsvd1;
+ uint8_t rsvd2;
+ uint8_t rsvd3;
+ uint8_t rsp_code; /* Response code */
+ uint8_t sns_data[128];
+};
+
+#endif /* __CSIO_FCOE_PROTO_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h
new file mode 100644
index 0000000..00b78db
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw.h
@@ -0,0 +1,668 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_HW_H__
+#define __CSIO_HW_H__
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/compiler.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_wr.h"
+#include "csio_mb.h"
+#include "csio_scsi.h"
+#include "csio_defs.h"
+#include "t4_regs.h"
+#include "t4_msg.h"
+
+/*
+ * An error value used by host. Should not clash with FW defined return values.
+ */
+#define FW_HOSTERROR 255
+
+#define CSIO_FW_FNAME "cxgb4/t4fw.bin"
+#define CSIO_CF_FNAME "cxgb4/t4-config.txt"
+
+#define FW_VERSION_MAJOR 1
+#define FW_VERSION_MINOR 2
+#define FW_VERSION_MICRO 8
+
+#define CSIO_HW_NAME "Chelsio FCoE Adapter"
+#define CSIO_MAX_PFN 8
+#define CSIO_MAX_PPORTS 4
+
+#define CSIO_MAX_LUN 0xFFFF
+#define CSIO_MAX_QUEUE 2048
+#define CSIO_MAX_CMD_PER_LUN 32
+#define CSIO_MAX_DDP_BUF_SIZE (1024 * 1024)
+#define CSIO_MAX_SECTOR_SIZE 128
+
+/* Interrupts */
+#define CSIO_EXTRA_MSI_IQS 2 /* Extra iqs for INTX/MSI mode
+ * (Forward intr iq + fw iq) */
+#define CSIO_EXTRA_VECS 2 /* non-data + FW evt */
+#define CSIO_MAX_SCSI_CPU 128
+#define CSIO_MAX_SCSI_QSETS (CSIO_MAX_SCSI_CPU * CSIO_MAX_PPORTS)
+#define CSIO_MAX_MSIX_VECS (CSIO_MAX_SCSI_QSETS + CSIO_EXTRA_VECS)
+
+/* Queues */
+enum {
+ CSIO_INTR_WRSIZE = 128,
+ CSIO_INTR_IQSIZE = ((CSIO_MAX_MSIX_VECS + 1) * CSIO_INTR_WRSIZE),
+ CSIO_FWEVT_WRSIZE = 128,
+ CSIO_FWEVT_IQLEN = 128,
+ CSIO_FWEVT_FLBUFS = 64,
+ CSIO_FWEVT_IQSIZE = (CSIO_FWEVT_WRSIZE * CSIO_FWEVT_IQLEN),
+ CSIO_HW_NIQ = 1,
+ CSIO_HW_NFLQ = 1,
+ CSIO_HW_NEQ = 1,
+ CSIO_HW_NINTXQ = 1,
+};
+
+struct csio_msix_entries {
+ unsigned short vector; /* Vector assigned by pci_enable_msix */
+ void *dev_id; /* Priv object associated w/ this msix*/
+ char desc[24]; /* Description of this vector */
+};
+
+struct csio_scsi_qset {
+ int iq_idx; /* Ingress index */
+ int eq_idx; /* Egress index */
+ uint32_t intr_idx; /* MSIX Vector index */
+};
+
+struct csio_scsi_cpu_info {
+ int16_t max_cpus;
+};
+
+extern int csio_dbg_level;
+extern int csio_force_master;
+extern unsigned int csio_port_mask;
+extern int csio_msi;
+
+#define CSIO_VENDOR_ID 0x1425
+#define CSIO_ASIC_DEVID_PROTO_MASK 0xFF00
+#define CSIO_ASIC_DEVID_TYPE_MASK 0x00FF
+#define CSIO_FPGA 0xA000
+#define CSIO_T4_FCOE_ASIC 0x4600
+
+#define CSIO_GLBL_INTR_MASK (CIM | MPS | PL | PCIE | MC | EDC0 | \
+ EDC1 | LE | TP | MA | PM_TX | PM_RX | \
+ ULP_RX | CPL_SWITCH | SGE | \
+ ULP_TX | SF)
+
+/*
+ * Hard parameters used to initialize the card in the absence of a
+ * configuration file.
+ */
+enum {
+ /* General */
+ CSIO_SGE_DBFIFO_INT_THRESH = 10,
+
+ CSIO_SGE_RX_DMA_OFFSET = 2,
+
+ CSIO_SGE_FLBUF_SIZE1 = 65536,
+ CSIO_SGE_FLBUF_SIZE2 = 1536,
+ CSIO_SGE_FLBUF_SIZE3 = 9024,
+ CSIO_SGE_FLBUF_SIZE4 = 9216,
+ CSIO_SGE_FLBUF_SIZE5 = 2048,
+ CSIO_SGE_FLBUF_SIZE6 = 128,
+ CSIO_SGE_FLBUF_SIZE7 = 8192,
+ CSIO_SGE_FLBUF_SIZE8 = 16384,
+
+ CSIO_SGE_TIMER_VAL_0 = 5,
+ CSIO_SGE_TIMER_VAL_1 = 10,
+ CSIO_SGE_TIMER_VAL_2 = 20,
+ CSIO_SGE_TIMER_VAL_3 = 50,
+ CSIO_SGE_TIMER_VAL_4 = 100,
+ CSIO_SGE_TIMER_VAL_5 = 200,
+
+ CSIO_SGE_INT_CNT_VAL_0 = 1,
+ CSIO_SGE_INT_CNT_VAL_1 = 4,
+ CSIO_SGE_INT_CNT_VAL_2 = 8,
+ CSIO_SGE_INT_CNT_VAL_3 = 16,
+
+ /* Storage specific - used by FW_PFVF_CMD */
+ CSIO_WX_CAPS = FW_CMD_CAP_PF, /* w/x all */
+ CSIO_R_CAPS = FW_CMD_CAP_PF, /* r all */
+ CSIO_NVI = 4,
+ CSIO_NIQ_FLINT = 34,
+ CSIO_NETH_CTRL = 32,
+ CSIO_NEQ = 66,
+ CSIO_NEXACTF = 32,
+ CSIO_CMASK = FW_PFVF_CMD_CMASK_MASK,
+ CSIO_PMASK = FW_PFVF_CMD_PMASK_MASK,
+};
+
+/* Slowpath events */
+enum csio_evt {
+ CSIO_EVT_FW = 0, /* FW event */
+ CSIO_EVT_MBX, /* MBX event */
+ CSIO_EVT_SCN, /* State change notification */
+ CSIO_EVT_DEV_LOSS, /* Device loss event */
+ CSIO_EVT_MAX, /* Max supported event */
+};
+
+#define CSIO_EVT_MSG_SIZE 512
+#define CSIO_EVTQ_SIZE 512
+
+/* Event msg */
+struct csio_evt_msg {
+ struct list_head list; /* evt queue*/
+ enum csio_evt type;
+ uint8_t data[CSIO_EVT_MSG_SIZE];
+};
+
+enum {
+ EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */
+ SERNUM_LEN = 16, /* Serial # length */
+ EC_LEN = 16, /* E/C length */
+ ID_LEN = 16, /* ID length */
+ TRACE_LEN = 112, /* length of trace data and mask */
+};
+
+enum {
+ SF_PAGE_SIZE = 256, /* serial flash page size */
+ SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */
+ SF_SIZE = SF_SEC_SIZE * 16, /* serial flash size */
+};
+
+enum { MEM_EDC0, MEM_EDC1, MEM_MC };
+
+enum {
+ MEMWIN0_APERTURE = 2048,
+ MEMWIN0_BASE = 0x1b800,
+ MEMWIN1_APERTURE = 32768,
+ MEMWIN1_BASE = 0x28000,
+ MEMWIN2_APERTURE = 65536,
+ MEMWIN2_BASE = 0x30000,
+};
+
+/* serial flash and firmware constants */
+enum {
+ SF_ATTEMPTS = 10, /* max retries for SF operations */
+
+ /* flash command opcodes */
+ SF_PROG_PAGE = 2, /* program page */
+ SF_WR_DISABLE = 4, /* disable writes */
+ SF_RD_STATUS = 5, /* read status register */
+ SF_WR_ENABLE = 6, /* enable writes */
+ SF_RD_DATA_FAST = 0xb, /* read flash */
+ SF_RD_ID = 0x9f, /* read ID */
+ SF_ERASE_SECTOR = 0xd8, /* erase sector */
+
+ FW_START_SEC = 8, /* first flash sector for FW */
+ FW_END_SEC = 15, /* last flash sector for FW */
+ FW_IMG_START = FW_START_SEC * SF_SEC_SIZE,
+ FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE,
+
+ FLASH_CFG_MAX_SIZE = 0x10000 , /* max size of the flash config file*/
+ FLASH_CFG_OFFSET = 0x1f0000,
+ FLASH_CFG_START_SEC = FLASH_CFG_OFFSET / SF_SEC_SIZE,
+ FPGA_FLASH_CFG_OFFSET = 0xf0000 , /* if FPGA mode, then cfg file is
+ * at 1MB - 64KB */
+ FPGA_FLASH_CFG_START_SEC = FPGA_FLASH_CFG_OFFSET / SF_SEC_SIZE,
+};
+
+/*
+ * Flash layout.
+ */
+#define FLASH_START(start) ((start) * SF_SEC_SIZE)
+#define FLASH_MAX_SIZE(nsecs) ((nsecs) * SF_SEC_SIZE)
+
+enum {
+ /*
+ * Location of firmware image in FLASH.
+ */
+ FLASH_FW_START_SEC = 8,
+ FLASH_FW_NSECS = 8,
+ FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
+ FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
+
+};
+
+#undef FLASH_START
+#undef FLASH_MAX_SIZE
+
+/* Management module */
+enum {
+ CSIO_MGMT_EQ_WRSIZE = 512,
+ CSIO_MGMT_IQ_WRSIZE = 128,
+ CSIO_MGMT_EQLEN = 64,
+ CSIO_MGMT_IQLEN = 64,
+};
+
+#define CSIO_MGMT_EQSIZE (CSIO_MGMT_EQLEN * CSIO_MGMT_EQ_WRSIZE)
+#define CSIO_MGMT_IQSIZE (CSIO_MGMT_IQLEN * CSIO_MGMT_IQ_WRSIZE)
+
+/* mgmt module stats */
+struct csio_mgmtm_stats {
+ uint32_t n_abort_req; /* Total abort request */
+ uint32_t n_abort_rsp; /* Total abort response */
+ uint32_t n_close_req; /* Total close request */
+ uint32_t n_close_rsp; /* Total close response */
+ uint32_t n_err; /* Total Errors */
+ uint32_t n_drop; /* Total request dropped */
+ uint32_t n_active; /* Count of active_q */
+ uint32_t n_cbfn; /* Count of cbfn_q */
+};
+
+/* MGMT module */
+struct csio_mgmtm {
+ struct csio_hw *hw; /* Pointer to HW moduel */
+ int eq_idx; /* Egress queue index */
+ int iq_idx; /* Ingress queue index */
+ int msi_vec; /* MSI vector */
+ struct list_head active_q; /* Outstanding ELS/CT */
+ struct list_head abort_q; /* Outstanding abort req */
+ struct list_head cbfn_q; /* Completion queue */
+ struct list_head mgmt_req_freelist; /* Free poll of reqs */
+ /* ELSCT request freelist*/
+ struct timer_list mgmt_timer; /* MGMT timer */
+ struct csio_mgmtm_stats stats; /* ELS/CT stats */
+};
+
+struct csio_adap_desc {
+ char model_no[16];
+ char description[32];
+};
+
+struct pci_params {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint32_t vpd_cap_addr;
+ uint16_t speed;
+ uint8_t width;
+};
+
+/* User configurable hw parameters */
+struct csio_hw_params {
+ uint32_t sf_size; /* serial flash
+ * size in bytes
+ */
+ uint32_t sf_nsec; /* # of flash sectors */
+ struct pci_params pci;
+ uint32_t log_level; /* Module-level for
+ * debug log.
+ */
+};
+
+struct csio_vpd {
+ uint32_t cclk;
+ uint8_t ec[EC_LEN + 1];
+ uint8_t sn[SERNUM_LEN + 1];
+ uint8_t id[ID_LEN + 1];
+};
+
+struct csio_pport {
+ uint16_t pcap;
+ uint8_t portid;
+ uint8_t link_status;
+ uint16_t link_speed;
+ uint8_t mac[6];
+ uint8_t mod_type;
+ uint8_t rsvd1;
+ uint8_t rsvd2;
+ uint8_t rsvd3;
+};
+
+/* fcoe resource information */
+struct csio_fcoe_res_info {
+ uint16_t e_d_tov;
+ uint16_t r_a_tov_seq;
+ uint16_t r_a_tov_els;
+ uint16_t r_r_tov;
+ uint32_t max_xchgs;
+ uint32_t max_ssns;
+ uint32_t used_xchgs;
+ uint32_t used_ssns;
+ uint32_t max_fcfs;
+ uint32_t max_vnps;
+ uint32_t used_fcfs;
+ uint32_t used_vnps;
+};
+
+/* HW State machine Events */
+enum csio_hw_ev {
+ CSIO_HWE_CFG = (uint32_t)1, /* Starts off the State machine */
+ CSIO_HWE_INIT, /* Config done, start Init */
+ CSIO_HWE_INIT_DONE, /* Init Mailboxes sent, HW ready */
+ CSIO_HWE_FATAL, /* Fatal error during initialization */
+ CSIO_HWE_PCIERR_DETECTED,/* PCI error recovery detetced */
+ CSIO_HWE_PCIERR_SLOT_RESET, /* Slot reset after PCI recoviery */
+ CSIO_HWE_PCIERR_RESUME, /* Resume after PCI error recovery */
+ CSIO_HWE_QUIESCED, /* HBA quiesced */
+ CSIO_HWE_HBA_RESET, /* HBA reset requested */
+ CSIO_HWE_HBA_RESET_DONE, /* HBA reset completed */
+ CSIO_HWE_FW_DLOAD, /* FW download requested */
+ CSIO_HWE_PCI_REMOVE, /* PCI de-instantiation */
+ CSIO_HWE_SUSPEND, /* HW suspend for Online(hot) replacement */
+ CSIO_HWE_RESUME, /* HW resume for Online(hot) replacement */
+ CSIO_HWE_MAX, /* Max HW event */
+};
+
+/* hw stats */
+struct csio_hw_stats {
+ uint32_t n_evt_activeq; /* Number of event in active Q */
+ uint32_t n_evt_freeq; /* Number of event in free Q */
+ uint32_t n_evt_drop; /* Number of event droped */
+ uint32_t n_evt_unexp; /* Number of unexpected events */
+ uint32_t n_pcich_offline;/* Number of pci channel offline */
+ uint32_t n_lnlkup_miss; /* Number of lnode lookup miss */
+ uint32_t n_cpl_fw6_msg; /* Number of cpl fw6 message*/
+ uint32_t n_cpl_fw6_pld; /* Number of cpl fw6 payload*/
+ uint32_t n_cpl_unexp; /* Number of unexpected cpl */
+ uint32_t n_mbint_unexp; /* Number of unexpected mbox */
+ /* interrupt */
+ uint32_t n_plint_unexp; /* Number of unexpected PL */
+ /* interrupt */
+ uint32_t n_plint_cnt; /* Number of PL interrupt */
+ uint32_t n_int_stray; /* Number of stray interrupt */
+ uint32_t n_err; /* Number of hw errors */
+ uint32_t n_err_fatal; /* Number of fatal errors */
+ uint32_t n_err_nomem; /* Number of memory alloc failure */
+ uint32_t n_err_io; /* Number of IO failure */
+ enum csio_hw_ev n_evt_sm[CSIO_HWE_MAX]; /* Number of sm events */
+ uint64_t n_reset_start; /* Start time after the reset */
+ uint32_t rsvd1;
+};
+
+/* Defines for hw->flags */
+#define CSIO_HWF_MASTER 0x00000001 /* This is the Master
+ * function for the
+ * card.
+ */
+#define CSIO_HWF_HW_INTR_ENABLED 0x00000002 /* Are HW Interrupt
+ * enable bit set?
+ */
+#define CSIO_HWF_FWEVT_PENDING 0x00000004 /* FW events pending */
+#define CSIO_HWF_Q_MEM_ALLOCED 0x00000008 /* Queues have been
+ * allocated memory.
+ */
+#define CSIO_HWF_Q_FW_ALLOCED 0x00000010 /* Queues have been
+ * allocated in FW.
+ */
+#define CSIO_HWF_VPD_VALID 0x00000020 /* Valid VPD copied */
+#define CSIO_HWF_DEVID_CACHED 0X00000040 /* PCI vendor & device
+ * id cached */
+#define CSIO_HWF_FWEVT_STOP 0x00000080 /* Stop processing
+ * FW events
+ */
+#define CSIO_HWF_USING_SOFT_PARAMS 0x00000100 /* Using FW config
+ * params
+ */
+#define CSIO_HWF_HOST_INTR_ENABLED 0x00000200 /* Are host interrupts
+ * enabled?
+ */
+
+#define csio_is_hw_intr_enabled(__hw) \
+ ((__hw)->flags & CSIO_HWF_HW_INTR_ENABLED)
+#define csio_is_host_intr_enabled(__hw) \
+ ((__hw)->flags & CSIO_HWF_HOST_INTR_ENABLED)
+#define csio_is_hw_master(__hw) ((__hw)->flags & CSIO_HWF_MASTER)
+#define csio_is_valid_vpd(__hw) ((__hw)->flags & CSIO_HWF_VPD_VALID)
+#define csio_is_dev_id_cached(__hw) ((__hw)->flags & CSIO_HWF_DEVID_CACHED)
+#define csio_valid_vpd_copied(__hw) ((__hw)->flags |= CSIO_HWF_VPD_VALID)
+#define csio_dev_id_cached(__hw) ((__hw)->flags |= CSIO_HWF_DEVID_CACHED)
+
+/* Defines for intr_mode */
+enum csio_intr_mode {
+ CSIO_IM_NONE = 0,
+ CSIO_IM_INTX = 1,
+ CSIO_IM_MSI = 2,
+ CSIO_IM_MSIX = 3,
+};
+
+/* Master HW structure: One per function */
+struct csio_hw {
+ struct csio_sm sm; /* State machine: should
+ * be the 1st member.
+ */
+ spinlock_t lock; /* Lock for hw */
+
+ struct csio_scsim scsim; /* SCSI module*/
+ struct csio_wrm wrm; /* Work request module*/
+ struct pci_dev *pdev; /* PCI device */
+
+ void __iomem *regstart; /* Virtual address of
+ * register map
+ */
+ /* SCSI queue sets */
+ uint32_t num_sqsets; /* Number of SCSI
+ * queue sets */
+ uint32_t num_scsi_msix_cpus; /* Number of CPUs that
+ * will be used
+ * for ingress
+ * processing.
+ */
+
+ struct csio_scsi_qset sqset[CSIO_MAX_PPORTS][CSIO_MAX_SCSI_CPU];
+ struct csio_scsi_cpu_info scsi_cpu_info[CSIO_MAX_PPORTS];
+
+ uint32_t evtflag; /* Event flag */
+ uint32_t flags; /* HW flags */
+
+ struct csio_mgmtm mgmtm; /* management module */
+ struct csio_mbm mbm; /* Mailbox module */
+
+ /* Lnodes */
+ uint32_t num_lns; /* Number of lnodes */
+ struct csio_lnode *rln; /* Root lnode */
+ struct list_head sln_head; /* Sibling node list
+ * list
+ */
+ int intr_iq_idx; /* Forward interrupt
+ * queue.
+ */
+ int fwevt_iq_idx; /* FW evt queue */
+ struct work_struct evtq_work; /* Worker thread for
+ * HW events.
+ */
+ struct list_head evt_free_q; /* freelist of evt
+ * elements
+ */
+ struct list_head evt_active_q; /* active evt queue*/
+
+ /* board related info */
+ char name[32];
+ char hw_ver[16];
+ char model_desc[32];
+ char drv_version[32];
+ char fwrev_str[32];
+ uint32_t optrom_ver;
+ uint32_t fwrev;
+ uint32_t tp_vers;
+ char chip_ver;
+ uint32_t cfg_finiver;
+ uint32_t cfg_finicsum;
+ uint32_t cfg_cfcsum;
+ uint8_t cfg_csum_status;
+ uint8_t cfg_store;
+ enum csio_dev_state fw_state;
+ struct csio_vpd vpd;
+
+ uint8_t pfn; /* Physical Function
+ * number
+ */
+ uint32_t port_vec; /* Port vector */
+ uint8_t num_pports; /* Number of physical
+ * ports.
+ */
+ uint8_t rst_retries; /* Reset retries */
+ uint8_t cur_evt; /* current s/m evt */
+ uint8_t prev_evt; /* Previous s/m evt */
+ uint32_t dev_num; /* device number */
+ struct csio_pport pport[CSIO_MAX_PPORTS]; /* Ports (XGMACs) */
+ struct csio_hw_params params; /* Hw parameters */
+
+ struct pci_pool *scsi_pci_pool; /* PCI pool for SCSI */
+ mempool_t *mb_mempool; /* Mailbox memory pool*/
+ mempool_t *rnode_mempool; /* rnode memory pool */
+
+ /* Interrupt */
+ enum csio_intr_mode intr_mode; /* INTx, MSI, MSIX */
+ uint32_t fwevt_intr_idx; /* FW evt MSIX/interrupt
+ * index
+ */
+ uint32_t nondata_intr_idx; /* nondata MSIX/intr
+ * idx
+ */
+
+ uint8_t cfg_neq; /* FW configured no of
+ * egress queues
+ */
+ uint8_t cfg_niq; /* FW configured no of
+ * iq queues.
+ */
+
+ struct csio_fcoe_res_info fres_info; /* Fcoe resource info */
+
+ /* MSIX vectors */
+ struct csio_msix_entries msix_entries[CSIO_MAX_MSIX_VECS];
+
+ struct dentry *debugfs_root; /* Debug FS */
+ struct csio_hw_stats stats; /* Hw statistics */
+};
+
+/* Register access macros */
+#define csio_reg(_b, _r) ((_b) + (_r))
+
+#define csio_rd_reg8(_h, _r) readb(csio_reg((_h)->regstart, (_r)))
+#define csio_rd_reg16(_h, _r) readw(csio_reg((_h)->regstart, (_r)))
+#define csio_rd_reg32(_h, _r) readl(csio_reg((_h)->regstart, (_r)))
+#define csio_rd_reg64(_h, _r) readq(csio_reg((_h)->regstart, (_r)))
+
+#define csio_wr_reg8(_h, _v, _r) writeb((_v), \
+ csio_reg((_h)->regstart, (_r)))
+#define csio_wr_reg16(_h, _v, _r) writew((_v), \
+ csio_reg((_h)->regstart, (_r)))
+#define csio_wr_reg32(_h, _v, _r) writel((_v), \
+ csio_reg((_h)->regstart, (_r)))
+#define csio_wr_reg64(_h, _v, _r) writeq((_v), \
+ csio_reg((_h)->regstart, (_r)))
+
+void csio_set_reg_field(struct csio_hw *, uint32_t, uint32_t, uint32_t);
+
+/* Core clocks <==> uSecs */
+static inline uint32_t
+csio_core_ticks_to_us(struct csio_hw *hw, uint32_t ticks)
+{
+ /* add Core Clock / 2 to round ticks to nearest uS */
+ return (ticks * 1000 + hw->vpd.cclk/2) / hw->vpd.cclk;
+}
+
+static inline uint32_t
+csio_us_to_core_ticks(struct csio_hw *hw, uint32_t us)
+{
+ return (us * hw->vpd.cclk) / 1000;
+}
+
+/* Easy access macros */
+#define csio_hw_to_wrm(hw) ((struct csio_wrm *)(&(hw)->wrm))
+#define csio_hw_to_mbm(hw) ((struct csio_mbm *)(&(hw)->mbm))
+#define csio_hw_to_scsim(hw) ((struct csio_scsim *)(&(hw)->scsim))
+#define csio_hw_to_mgmtm(hw) ((struct csio_mgmtm *)(&(hw)->mgmtm))
+
+#define csio_md(hw, idx) (&(hw)->mem_descs[(idx)])
+
+#define CSIO_PCI_BUS(hw) ((hw)->pdev->bus->number)
+#define CSIO_PCI_DEV(hw) (PCI_SLOT((hw)->pdev->devfn))
+#define CSIO_PCI_FUNC(hw) (PCI_FUNC((hw)->pdev->devfn))
+
+#define csio_set_fwevt_intr_idx(_h, _i) ((_h)->fwevt_intr_idx = (_i))
+#define csio_get_fwevt_intr_idx(_h) ((_h)->fwevt_intr_idx)
+#define csio_set_nondata_intr_idx(_h, _i) ((_h)->nondata_intr_idx = (_i))
+#define csio_get_nondata_intr_idx(_h) ((_h)->nondata_intr_idx)
+
+/* Printing/logging */
+#define CSIO_DEVID(__dev) ((__dev)->dev_num)
+#define CSIO_DEVID_LO(__dev) (CSIO_DEVID((__dev)) & 0xFFFF)
+#define CSIO_DEVID_HI(__dev) ((CSIO_DEVID((__dev)) >> 16) & 0xFFFF)
+
+#define csio_info(__hw, __fmt, ...) \
+ dev_info(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_fatal(__hw, __fmt, ...) \
+ dev_crit(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_err(__hw, __fmt, ...) \
+ dev_err(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_warn(__hw, __fmt, ...) \
+ dev_warn(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#ifdef __CSIO_DEBUG__
+#define csio_dbg(__hw, __fmt, ...) \
+ csio_info((__hw), __fmt, ##__VA_ARGS__);
+#else
+#define csio_dbg(__hw, __fmt, ...)
+#endif
+
+csio_retval_t csio_mgmt_req_lookup(struct csio_mgmtm *, struct csio_ioreq *);
+void csio_hw_intr_disable(struct csio_hw *);
+int csio_hw_slow_intr_handler(struct csio_hw *hw);
+csio_retval_t csio_hw_start(struct csio_hw *);
+csio_retval_t csio_hw_stop(struct csio_hw *);
+csio_retval_t csio_hw_reset(struct csio_hw *);
+int csio_is_hw_ready(struct csio_hw *);
+int csio_is_hw_removing(struct csio_hw *);
+
+csio_retval_t csio_fwevtq_handler(struct csio_hw *);
+void csio_evtq_worker(struct work_struct *);
+csio_retval_t csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type,
+ void *evt_msg, uint16_t len);
+void csio_evtq_flush(struct csio_hw *hw);
+
+csio_retval_t csio_request_irqs(struct csio_hw *);
+void csio_intr_enable(struct csio_hw *);
+void csio_intr_disable(struct csio_hw *, bool);
+
+struct csio_lnode *csio_lnode_alloc(struct csio_hw *);
+csio_retval_t csio_config_queues(struct csio_hw *);
+
+csio_retval_t csio_hw_mc_read(struct csio_hw *, uint32_t,
+ uint32_t *, uint64_t *);
+csio_retval_t csio_hw_edc_read(struct csio_hw *, int, uint32_t, uint32_t *,
+ uint64_t *);
+csio_retval_t csio_hw_init(struct csio_hw *);
+void csio_hw_exit(struct csio_hw *);
+#endif /* ifndef __CSIO_HW_H__ */
diff --git a/drivers/scsi/csiostor/csio_init.h b/drivers/scsi/csiostor/csio_init.h
new file mode 100644
index 0000000..0838fd7
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_init.h
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_INIT_H__
+#define __CSIO_INIT_H__
+
+#include <linux/pci.h>
+#include <linux/if_ether.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_scsi.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_hw.h"
+
+#define CSIO_DRV_AUTHOR "Chelsio Communications"
+#define CSIO_DRV_LICENSE "Dual BSD/GPL"
+#define CSIO_DRV_DESC "Chelsio FCoE driver"
+#define CSIO_DRV_VERSION "1.0.0"
+
+#define CSIO_DEVICE(devid, idx) \
+{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
+
+#define CSIO_IS_T4_FPGA(_dev) (((_dev) == CSIO_DEVID_PE10K) ||\
+ ((_dev) == CSIO_DEVID_PE10K_PF1))
+
+/* FCoE device IDs */
+#define CSIO_DEVID_PE10K 0xA000
+#define CSIO_DEVID_PE10K_PF1 0xA001
+#define CSIO_DEVID_T440DBG_FCOE 0x4600
+#define CSIO_DEVID_T420CR_FCOE 0x4601
+#define CSIO_DEVID_T422CR_FCOE 0x4602
+#define CSIO_DEVID_T440CR_FCOE 0x4603
+#define CSIO_DEVID_T420BCH_FCOE 0x4604
+#define CSIO_DEVID_T440BCH_FCOE 0x4605
+#define CSIO_DEVID_T440CH_FCOE 0x4606
+#define CSIO_DEVID_T420SO_FCOE 0x4607
+#define CSIO_DEVID_T420CX_FCOE 0x4608
+#define CSIO_DEVID_T420BT_FCOE 0x4609
+#define CSIO_DEVID_T404BT_FCOE 0x460A
+#define CSIO_DEVID_B420_FCOE 0x460B
+#define CSIO_DEVID_B404_FCOE 0x460C
+#define CSIO_DEVID_T480CR_FCOE 0x460D
+#define CSIO_DEVID_T440LPCR_FCOE 0x460E
+
+extern struct fc_function_template csio_fc_transport_funcs;
+extern struct fc_function_template csio_fc_transport_vport_funcs;
+
+void csio_fchost_attr_init(struct csio_lnode *);
+
+/* INTx handlers */
+void csio_scsi_intx_handler(struct csio_hw *, void *, uint32_t,
+ struct csio_fl_dma_buf *, void *);
+
+void csio_fwevt_intx_handler(struct csio_hw *, void *, uint32_t,
+ struct csio_fl_dma_buf *, void *);
+
+/* Common os lnode APIs */
+void csio_lnodes_block_request(struct csio_hw *);
+void csio_lnodes_unblock_request(struct csio_hw *);
+void csio_lnodes_block_by_port(struct csio_hw *, uint8_t);
+void csio_lnodes_unblock_by_port(struct csio_hw *, uint8_t);
+
+struct csio_lnode *csio_shost_init(struct csio_hw *, struct device *, bool,
+ struct csio_lnode *);
+void csio_shost_exit(struct csio_lnode *);
+void csio_lnodes_exit(struct csio_hw *, bool);
+
+static inline struct Scsi_Host *
+csio_ln_to_shost(struct csio_lnode *ln)
+{
+ return container_of((void *)ln, struct Scsi_Host, hostdata[0]);
+}
+
+/* SCSI -- locking version of get/put ioreqs */
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim)
+{
+ struct csio_ioreq *ioreq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&scsim->freelist_lock, flags);
+ ioreq = csio_get_scsi_ioreq(scsim);
+ spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+
+ return ioreq;
+}
+
+static inline void
+csio_put_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+ struct csio_ioreq *ioreq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&scsim->freelist_lock, flags);
+ csio_put_scsi_ioreq(scsim, ioreq);
+ spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ioreq_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+ struct list_head *reqlist, int n)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&scsim->freelist_lock, flags);
+ csio_put_scsi_ioreq_list(scsim, reqlist, n);
+ spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ddp_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+ struct list_head *reqlist, int n)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hw->lock, flags);
+ csio_put_scsi_ddp_list(scsim, reqlist, n);
+ spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+#endif /* ifndef __CSIO_INIT_H__ */
--
1.7.1
^ permalink raw reply related
* [PATCH 7/8] csiostor: Chelsio FCoE offload driver submission (headers part 2).
From: Naresh Kumar Inna @ 2012-08-23 22:27 UTC (permalink / raw)
To: JBottomley, linux-scsi, dm; +Cc: netdev, naresh, chethan
In-Reply-To: <1345760873-12101-1-git-send-email-naresh@chelsio.com>
This patch contains the second set of the header files for csiostor driver.
Signed-off-by: Naresh Kumar Inna <naresh@chelsio.com>
---
drivers/scsi/csiostor/csio_lnode.h | 244 ++++++++++++++
drivers/scsi/csiostor/csio_mb.h | 278 ++++++++++++++++
drivers/scsi/csiostor/csio_rnode.h | 142 ++++++++
drivers/scsi/csiostor/csio_scsi.h | 332 +++++++++++++++++++
drivers/scsi/csiostor/csio_wr.h | 519 +++++++++++++++++++++++++++++
drivers/scsi/csiostor/t4fw_api_stor.h | 578 +++++++++++++++++++++++++++++++++
6 files changed, 2093 insertions(+), 0 deletions(-)
create mode 100644 drivers/scsi/csiostor/csio_lnode.h
create mode 100644 drivers/scsi/csiostor/csio_mb.h
create mode 100644 drivers/scsi/csiostor/csio_rnode.h
create mode 100644 drivers/scsi/csiostor/csio_scsi.h
create mode 100644 drivers/scsi/csiostor/csio_wr.h
create mode 100644 drivers/scsi/csiostor/t4fw_api_stor.h
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
new file mode 100644
index 0000000..5845856
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_lnode.h
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_LNODE_H__
+#define __CSIO_LNODE_H__
+
+#include <linux/kref.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+
+#include "csio_defs.h"
+#include "csio_hw.h"
+#include "csio_fcoe_proto.h"
+
+#define CSIO_FCOE_MAX_NPIV 128
+#define CSIO_FCOE_MAX_RNODES 2048
+
+extern int csio_fcoe_rnodes;
+extern int csio_fdmi_enable;
+
+/* State machine evets */
+enum csio_ln_ev {
+ CSIO_LNE_NONE = (uint32_t)0,
+ CSIO_LNE_LINKUP,
+ CSIO_LNE_FAB_INIT_DONE,
+ CSIO_LNE_LINK_DOWN,
+ CSIO_LNE_DOWN_LINK,
+ CSIO_LNE_LOGO,
+ CSIO_LNE_CLOSE,
+ CSIO_LNE_MAX_EVENT,
+};
+
+
+struct csio_fcf_info {
+ struct list_head list;
+ uint8_t priority;
+ uint8_t mac[6];
+ uint8_t name_id[8];
+ uint8_t fabric[8];
+ uint16_t vf_id;
+ uint8_t vlan_id;
+ uint16_t max_fcoe_size;
+ uint8_t fc_map[3];
+ uint32_t fka_adv;
+ uint32_t fcfi;
+ uint8_t get_next:1;
+ uint8_t link_aff:1;
+ uint8_t fpma:1;
+ uint8_t spma:1;
+ uint8_t login:1;
+ uint8_t portid;
+ uint8_t spma_mac[6];
+ struct kref kref;
+};
+
+/* Defines for flags */
+#define CSIO_LNF_FIPSUPP 0x00000001 /* Fip Supported */
+#define CSIO_LNF_NPIVSUPP 0x00000002 /* NPIV supported */
+#define CSIO_LNF_LINK_ENABLE 0x00000004 /* Link enabled */
+#define CSIO_LNF_FDMI_ENABLE 0x00000008 /* FDMI support */
+
+/* Transport events */
+enum csio_ln_fc_evt {
+ CSIO_LN_FC_LINKUP = 1,
+ CSIO_LN_FC_LINKDOWN,
+ CSIO_LN_FC_RSCN,
+ CSIO_LN_FC_ATTRIB_UPDATE,
+};
+
+/* Lnode stats */
+struct csio_lnode_stats {
+ uint32_t n_link_up; /* Link down */
+ uint32_t n_link_down; /* Link up */
+ uint32_t n_err; /* error */
+ uint32_t n_err_nomem; /* memory not available */
+ uint32_t n_inval_parm; /* Invalid parameters */
+ uint32_t n_evt_unexp; /* unexpected event */
+ uint32_t n_evt_drop; /* dropped event */
+ uint32_t n_rnode_match; /* matched rnode */
+ uint32_t n_dev_loss_tmo; /* Device loss timeout */
+ uint32_t n_fdmi_err; /* fdmi err */
+ uint32_t n_evt_fw[RSCN_DEV_LOST]; /* fw events */
+ enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT]; /* State m/c events */
+ uint32_t n_rnode_alloc; /* rnode allocated */
+ uint32_t n_rnode_free; /* rnode freed */
+ uint32_t n_rnode_nomem; /* rnode alloc failure */
+ uint32_t n_input_requests; /* Input Requests */
+ uint32_t n_output_requests; /* Output Requests */
+ uint32_t n_control_requests; /* Control Requests */
+ uint32_t n_input_bytes; /* Input Bytes */
+ uint32_t n_output_bytes; /* Output Bytes */
+ uint32_t rsvd1;
+};
+
+/* Common Lnode params */
+struct csio_lnode_params {
+ uint32_t ra_tov;
+ uint32_t fcfi;
+ uint32_t log_level; /* Module level for debugging */
+};
+
+/* Lnode */
+struct csio_lnode {
+ struct csio_sm sm; /* State machine + sibling
+ * lnode list.
+ */
+ struct csio_hw *hwp; /* Pointer to the HW module */
+ uint8_t portid; /* Port ID */
+ uint8_t rsvd1;
+ uint16_t rsvd2;
+ uint32_t dev_num; /* Device number */
+ uint32_t flags; /* Flags */
+ struct list_head fcf_lsthead; /* FCF entries */
+ struct csio_fcf_info *fcfinfo; /* FCF in use */
+ struct csio_ioreq *mgmt_req; /* MGMT request */
+
+ /* FCoE identifiers */
+ uint8_t mac[6];
+ uint32_t nport_id;
+ struct csio_service_parms ln_sparm; /* Service parms */
+
+ /* Firmware identifiers */
+ uint32_t fcf_flowid; /*fcf flowid */
+ uint32_t vnp_flowid;
+ uint16_t ssn_cnt; /* Registered Session */
+ uint8_t cur_evt; /* Current event */
+ uint8_t prev_evt; /* Previous event */
+
+ /* Children */
+ struct list_head cln_head; /* Head of the children lnode
+ * list.
+ */
+ uint32_t num_vports; /* Total NPIV/children LNodes*/
+ struct csio_lnode *pln; /* Parent lnode of child
+ * lnodes.
+ */
+ struct list_head cmpl_q; /* Pending I/Os on this lnode */
+
+ /* Remote node information */
+ struct list_head rnhead; /* Head of rnode list */
+ uint32_t num_reg_rnodes; /* Number of rnodes registered
+ * with the host.
+ */
+ uint32_t n_scsi_tgts; /* Number of scsi targets
+ * found
+ */
+ uint32_t last_scan_ntgts;/* Number of scsi targets
+ * found per last scan.
+ */
+ uint32_t tgt_scan_tick; /* timer started after
+ * new tgt found
+ */
+ /* FC transport data */
+ struct fc_vport *fc_vport;
+ struct fc_host_statistics fch_stats;
+
+ struct csio_lnode_stats stats; /* Common lnode stats */
+ struct csio_lnode_params params; /* Common lnode params */
+};
+
+#define csio_lnode_to_hw(ln) ((ln)->hwp)
+#define csio_root_lnode(ln) (csio_lnode_to_hw((ln))->rln)
+#define csio_parent_lnode(ln) ((ln)->pln)
+#define csio_ln_flowid(ln) ((ln)->vnp_flowid)
+#define csio_ln_wwpn(ln) ((ln)->ln_sparm.wwpn)
+#define csio_ln_wwnn(ln) ((ln)->ln_sparm.wwnn)
+
+#define csio_is_root_ln(ln) (((ln) == csio_root_lnode((ln))) ? 1 : 0)
+#define csio_is_phys_ln(ln) (((ln)->pln == NULL) ? 1 : 0)
+#define csio_is_npiv_ln(ln) (((ln)->pln != NULL) ? 1 : 0)
+
+
+#define csio_ln_dbg(_ln, _fmt, ...) \
+ csio_dbg(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+ CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_err(_ln, _fmt, ...) \
+ csio_err(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+ CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_warn(_ln, _fmt, ...) \
+ csio_warn(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+ CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+/* HW->Lnode notifications */
+enum csio_ln_notify {
+ CSIO_LN_NOTIFY_HWREADY = 1,
+ CSIO_LN_NOTIFY_HWSTOP,
+ CSIO_LN_NOTIFY_HWREMOVE,
+ CSIO_LN_NOTIFY_HWRESET,
+};
+
+void csio_fcoe_fwevt_handler(struct csio_hw *, __u8 cpl_op, __be64 *);
+int csio_is_lnode_ready(struct csio_lnode *);
+void csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str);
+struct csio_lnode *csio_lnode_lookup_by_wwpn(struct csio_hw *, uint8_t *);
+csio_retval_t csio_get_phy_port_stats(struct csio_hw *, uint8_t ,
+ struct fw_fcoe_port_stats *);
+int csio_scan_done(struct csio_lnode *, unsigned long, unsigned long,
+ unsigned long, unsigned long);
+void csio_notify_lnodes(struct csio_hw *, enum csio_ln_notify);
+void csio_disable_lnodes(struct csio_hw *, uint8_t, bool);
+void csio_lnode_async_event(struct csio_lnode *, enum csio_ln_fc_evt);
+csio_retval_t csio_ln_fdmi_start(struct csio_lnode *, void *);
+csio_retval_t csio_lnode_start(struct csio_lnode *);
+void csio_lnode_stop(struct csio_lnode *);
+void csio_lnode_close(struct csio_lnode *);
+csio_retval_t csio_lnode_init(struct csio_lnode *, struct csio_hw *,
+ struct csio_lnode *);
+void csio_lnode_exit(struct csio_lnode *);
+
+#endif /* ifndef __CSIO_LNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_mb.h b/drivers/scsi/csiostor/csio_mb.h
new file mode 100644
index 0000000..f3e578b
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_mb.h
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_MB_H__
+#define __CSIO_MB_H__
+
+#include <linux/timer.h>
+#include <linux/completion.h>
+
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+#include "csio_defs.h"
+
+#define CSIO_STATS_OFFSET (2)
+#define CSIO_NUM_STATS_PER_MB (6)
+
+struct fw_fcoe_port_cmd_params {
+ uint8_t portid;
+ uint8_t idx;
+ uint8_t nstats;
+};
+
+#define CSIO_DUMP_MB(__hw, __num, __mb) \
+ csio_dbg(__hw, "\t%llx %llx %llx %llx %llx %llx %llx %llx\n", \
+ (unsigned long long)csio_rd_reg64(__hw, __mb), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 8), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 16), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 24), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 32), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 40), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 48), \
+ (unsigned long long)csio_rd_reg64(__hw, __mb + 56))
+
+#define CSIO_MB_MAX_REGS 8
+#define CSIO_MAX_MB_SIZE 64
+#define CSIO_MB_POLL_FREQ 5 /* 5 ms */
+#define CSIO_MB_DEFAULT_TMO FW_CMD_MAX_TIMEOUT
+
+/* Device master in HELLO command */
+enum csio_dev_master { CSIO_MASTER_CANT, CSIO_MASTER_MAY, CSIO_MASTER_MUST };
+
+enum csio_mb_owner { CSIO_MBOWNER_NONE, CSIO_MBOWNER_FW, CSIO_MBOWNER_PL };
+
+enum csio_dev_state {
+ CSIO_DEV_STATE_UNINIT,
+ CSIO_DEV_STATE_INIT,
+ CSIO_DEV_STATE_ERR
+};
+
+#define FW_PARAM_DEV(param) \
+ (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
+ FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
+
+#define FW_PARAM_PFVF(param) \
+ (FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
+ FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)| \
+ FW_PARAMS_PARAM_Y(0) | \
+ FW_PARAMS_PARAM_Z(0))
+
+enum {
+ PAUSE_RX = 1 << 0,
+ PAUSE_TX = 1 << 1,
+ PAUSE_AUTONEG = 1 << 2
+};
+
+#define CSIO_INIT_MBP(__mbp, __cp, __tmo, __priv, __fn, __clear) \
+do { \
+ if (__clear) \
+ memset((__cp), 0, \
+ CSIO_MB_MAX_REGS * sizeof(__be64)); \
+ INIT_LIST_HEAD(&(__mbp)->list); \
+ (__mbp)->tmo = (__tmo); \
+ (__mbp)->priv = (void *)(__priv); \
+ (__mbp)->mb_cbfn = (__fn); \
+ (__mbp)->mb_size = sizeof(*(__cp)); \
+} while (0)
+
+struct csio_mbm_stats {
+ uint32_t n_req; /* number of mbox req */
+ uint32_t n_rsp; /* number of mbox rsp */
+ uint32_t n_activeq; /* number of mbox req active Q */
+ uint32_t n_cbfnq; /* number of mbox req cbfn Q */
+ uint32_t n_tmo; /* number of mbox timeout */
+ uint32_t n_cancel; /* number of mbox cancel */
+ uint32_t n_err; /* number of mbox error */
+};
+
+/* Driver version of Mailbox */
+struct csio_mb {
+ struct list_head list; /* for req/resp */
+ /* queue in driver */
+ __be64 mb[CSIO_MB_MAX_REGS]; /* MB in HW format */
+ int mb_size; /* Size of this
+ * mailbox.
+ */
+ uint32_t tmo; /* Timeout */
+ struct completion cmplobj; /* MB Completion
+ * object
+ */
+ void (*mb_cbfn) (struct csio_hw *, struct csio_mb *);
+ /* Callback fn */
+ void *priv; /* Owner private ptr */
+};
+
+struct csio_mbm {
+ uint32_t a_mbox; /* Async mbox num */
+ uint32_t intr_idx; /* Interrupt index */
+ struct timer_list timer; /* Mbox timer */
+ struct list_head req_q; /* Mbox request queue */
+ struct list_head cbfn_q; /* Mbox completion q */
+ struct csio_mb *mcurrent; /* Current mailbox */
+ uint32_t req_q_cnt; /* Outstanding mbox
+ * cmds
+ */
+ struct csio_mbm_stats stats; /* Statistics */
+};
+
+#define csio_set_mb_intr_idx(_m, _i) ((_m)->intr_idx = (_i))
+#define csio_get_mb_intr_idx(_m) ((_m)->intr_idx)
+
+struct csio_iq_params;
+struct csio_eq_params;
+
+enum fw_retval csio_mb_fw_retval(struct csio_mb *);
+
+/* MB helpers */
+void csio_mb_hello(struct csio_hw *, struct csio_mb *, uint32_t,
+ uint32_t, uint32_t, enum csio_dev_master,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_hello_rsp(struct csio_hw *, struct csio_mb *,
+ enum fw_retval *, enum csio_dev_state *,
+ uint8_t *);
+
+void csio_mb_bye(struct csio_hw *, struct csio_mb *, uint32_t,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_reset(struct csio_hw *, struct csio_mb *, uint32_t, int, int,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_params(struct csio_hw *, struct csio_mb *, uint32_t, unsigned int,
+ unsigned int, unsigned int, const u32 *, u32 *, bool,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_params_rsp(struct csio_hw *, struct csio_mb *,
+ enum fw_retval *, unsigned int , u32 *);
+
+void csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+ int reg);
+
+void csio_mb_caps_config(struct csio_hw *, struct csio_mb *, uint32_t,
+ bool, bool, bool, bool,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_rss_glb_config(struct csio_hw *, struct csio_mb *,
+ uint32_t, uint8_t, unsigned int,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_pfvf(struct csio_hw *, struct csio_mb *, uint32_t,
+ unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int,
+ unsigned int, void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
+ uint8_t, bool, uint32_t, uint16_t,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *,
+ enum fw_retval *, uint16_t *);
+
+void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
+ void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+ uint32_t, struct csio_iq_params *,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+ enum fw_retval *, struct csio_iq_params *);
+
+void csio_mb_iq_free(struct csio_hw *, struct csio_mb *, void *,
+ uint32_t, struct csio_iq_params *,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+ uint32_t, struct csio_eq_params *,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+ enum fw_retval *, struct csio_eq_params *);
+
+void csio_mb_eq_ofld_free(struct csio_hw *, struct csio_mb *, void *,
+ uint32_t , struct csio_eq_params *,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_res_info_init_mb(struct csio_hw *, struct csio_mb *,
+ uint32_t,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_write_fcoe_link_cond_init_mb(struct csio_lnode *, struct csio_mb *,
+ uint32_t, uint8_t, uint32_t, uint8_t, bool, uint32_t,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *, struct csio_mb *,
+ uint32_t, uint32_t , uint32_t , uint16_t,
+ uint8_t [8], uint8_t [8],
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_read_init_mb(struct csio_lnode *, struct csio_mb *,
+ uint32_t, uint32_t , uint32_t ,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_free_init_mb(struct csio_lnode *, struct csio_mb *,
+ uint32_t , uint32_t, uint32_t ,
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_fcf_init_mb(struct csio_lnode *, struct csio_mb *,
+ uint32_t, uint32_t, uint32_t,
+ void (*cbfn) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_portparams_init_mb(struct csio_hw *hw,
+ struct csio_mb *mbp, uint32_t mb_tmo,
+ struct fw_fcoe_port_cmd_params *portparams,
+ void (*cbfn)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_portparams_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+ enum fw_retval *retval,
+ struct fw_fcoe_port_cmd_params *portparams,
+ struct fw_fcoe_port_stats *portstats);
+
+/* MB module functions */
+csio_retval_t csio_mbm_init(struct csio_mbm *, struct csio_hw *,
+ void (*)(uintptr_t));
+void csio_mbm_exit(struct csio_mbm *);
+void csio_mb_intr_enable(struct csio_hw *);
+void csio_mb_intr_disable(struct csio_hw *);
+
+csio_retval_t csio_mb_issue(struct csio_hw *, struct csio_mb *);
+void csio_mb_completions(struct csio_hw *, struct list_head *);
+csio_retval_t csio_mb_fwevt_handler(struct csio_hw *, __be64 *);
+csio_retval_t csio_mb_isr_handler(struct csio_hw *);
+struct csio_mb *csio_mb_tmo_handler(struct csio_hw *);
+void csio_mb_cancel_all(struct csio_hw *, struct list_head *);
+
+#endif /* ifndef __CSIO_MB_H__ */
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h
new file mode 100644
index 0000000..99f0cd1
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_rnode.h
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_RNODE_H__
+#define __CSIO_RNODE_H__
+
+#include "csio_defs.h"
+#include "csio_fcoe_proto.h"
+
+/* State machine evets */
+enum csio_rn_ev {
+ CSIO_RNFE_NONE = (uint32_t)0, /* None */
+ CSIO_RNFE_LOGGED_IN, /* [N/F]Port login
+ * complete.
+ */
+ CSIO_RNFE_PRLI_DONE, /* PRLI completed */
+ CSIO_RNFE_PLOGI_RECV, /* Received PLOGI */
+ CSIO_RNFE_PRLI_RECV, /* Received PLOGI */
+ CSIO_RNFE_LOGO_RECV, /* Received LOGO */
+ CSIO_RNFE_PRLO_RECV, /* Received PRLO */
+ CSIO_RNFE_DOWN, /* Rnode is down */
+ CSIO_RNFE_CLOSE, /* Close rnode */
+ CSIO_RNFE_NAME_MISSING, /* Rnode name missing
+ * in name server.
+ */
+ CSIO_RNFE_MAX_EVENT,
+};
+
+/* rnode stats */
+struct csio_rnode_stats {
+ uint32_t n_err; /* error */
+ uint32_t n_err_inval; /* invalid parameter */
+ uint32_t n_err_nomem; /* error nomem */
+ uint32_t n_evt_unexp; /* unexpected event */
+ uint32_t n_evt_drop; /* unexpected event */
+ uint32_t n_evt_fw[RSCN_DEV_LOST]; /* fw events */
+ enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT]; /* State m/c events */
+ uint32_t n_lun_rst; /* Number of resets of
+ * of LUNs under this
+ * target
+ */
+ uint32_t n_lun_rst_fail; /* Number of LUN reset
+ * failures.
+ */
+ uint32_t n_tgt_rst; /* Number of target resets */
+ uint32_t n_tgt_rst_fail; /* Number of target reset
+ * failures.
+ */
+};
+
+/* Defines for rnode role */
+#define CSIO_RNFR_INITIATOR 0x1
+#define CSIO_RNFR_TARGET 0x2
+#define CSIO_RNFR_FABRIC 0x4
+#define CSIO_RNFR_NS 0x8
+#define CSIO_RNFR_NPORT 0x10
+
+struct csio_rnode {
+ struct csio_sm sm; /* State machine -
+ * should be the
+ * 1st member
+ */
+ struct csio_lnode *lnp; /* Pointer to owning
+ * Lnode */
+ uint32_t flowid; /* Firmware ID */
+ struct list_head host_cmpl_q; /* SCSI IOs
+ * pending to completed
+ * to Mid-layer.
+ */
+ /* FC identifiers for remote node */
+ uint32_t nport_id;
+ uint16_t fcp_flags; /* FCP Flags */
+ uint8_t cur_evt; /* Current event */
+ uint8_t prev_evt; /* Previous event */
+ uint32_t role; /* Fabric/Target/
+ * Initiator/NS
+ */
+ struct fcoe_rdev_entry *rdev_entry; /* Rdev entry */
+ struct csio_service_parms rn_sparm;
+
+ /* FC transport attributes */
+ struct fc_rport *rport; /* FC transport rport */
+ uint32_t supp_classes; /* Supported FC classes */
+ uint32_t maxframe_size; /* Max Frame size */
+ uint32_t scsi_id; /* Transport given SCSI id */
+
+ struct csio_rnode_stats stats; /* Common rnode stats */
+};
+
+#define csio_rn_flowid(rn) ((rn)->flowid)
+#define csio_rn_wwpn(rn) ((rn)->rn_sparm.wwpn)
+#define csio_rn_wwnn(rn) ((rn)->rn_sparm.wwnn)
+#define csio_rnode_to_lnode(rn) ((rn)->lnp)
+
+int csio_is_rnode_ready(struct csio_rnode *rn);
+void csio_rnode_state_to_str(struct csio_rnode *rn, int8_t *str);
+
+struct csio_rnode *csio_rnode_lookup_portid(struct csio_lnode *, uint32_t);
+struct csio_rnode *csio_confirm_rnode(struct csio_lnode *,
+ uint32_t, struct fcoe_rdev_entry *);
+
+void csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt);
+
+void csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn);
+
+void csio_reg_rnode(struct csio_rnode *);
+void csio_unreg_rnode(struct csio_rnode *);
+
+void csio_rnode_devloss_handler(struct csio_rnode *);
+
+#endif /* ifndef __CSIO_RNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_scsi.h b/drivers/scsi/csiostor/csio_scsi.h
new file mode 100644
index 0000000..c0aa2fb
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_scsi.h
@@ -0,0 +1,332 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_SCSI_H__
+#define __CSIO_SCSI_H__
+
+#include <linux/spinlock_types.h>
+#include <linux/completion.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+
+#include "csio_defs.h"
+#include "csio_wr.h"
+
+extern struct scsi_host_template csio_fcoe_shost_template;
+extern struct scsi_host_template csio_fcoe_shost_vport_template;
+
+extern int csio_scsi_eqsize;
+extern int csio_scsi_iqlen;
+extern int csio_scsi_ioreqs;
+extern uint32_t csio_max_scan_tmo;
+extern uint32_t csio_delta_scan_tmo;
+extern int csio_lun_qdepth;
+
+/*
+ **************************** NOTE *******************************
+ * How do we calculate MAX FCoE SCSI SGEs? Here is the math:
+ * Max Egress WR size = 512 bytes
+ * One SCSI egress WR has the following fixed no of bytes:
+ * 48 (sizeof(struct fw_scsi_write[read]_wr)) - FW WR
+ * + 32 (sizeof(struct csio_fcp_cmnd)) - Immediate FCP_CMD
+ * ------
+ * 80
+ * ------
+ * That leaves us with 512 - 96 = 432 bytes for data SGE. Using
+ * struct ulptx_sgl header for the SGE consumes:
+ * - 4 bytes for cmnd_sge.
+ * - 12 bytes for the first SGL.
+ * That leaves us with 416 bytes for the remaining SGE pairs. Which is
+ * is 416 / 24 (size(struct ulptx_sge_pair)) = 17 SGE pairs,
+ * or 34 SGEs. Adding the first SGE fetches us 35 SGEs.
+ */
+#define CSIO_SCSI_MAX_SGE 35
+#define CSIO_SCSI_ABRT_TMO_MS 60000
+#define CSIO_SCSI_LUNRST_TMO_MS 60000
+#define CSIO_SCSI_TM_POLL_MS 2000 /* should be less than
+ * all TM timeouts.
+ */
+#define CSIO_SCSI_IQ_WRSZ 128
+#define CSIO_SCSI_IQSIZE (csio_scsi_iqlen * CSIO_SCSI_IQ_WRSZ)
+
+/* Reference to scsi_cmnd */
+#define csio_scsi_cmnd(req) ((req)->scratch1)
+
+struct csio_scsi_stats {
+ uint64_t n_tot_success; /* Total number of good I/Os */
+ uint32_t n_rn_nr_error; /* No. of remote-node-not-
+ * ready errors
+ */
+ uint32_t n_hw_nr_error; /* No. of hw-module-not-
+ * ready errors
+ */
+ uint32_t n_dmamap_error; /* No. of DMA map erros */
+ uint32_t n_unsupp_sge_error; /* No. of too-many-SGes
+ * errors.
+ */
+ uint32_t n_no_req_error; /* No. of Out-of-ioreqs error */
+ uint32_t n_busy_error; /* No. of CSIO_BUSY errors */
+ uint32_t n_hosterror; /* No. of FW_HOSTERROR I/O */
+ uint32_t n_rsperror; /* No. of response errors */
+ uint32_t n_autosense; /* No. of auto sense replies */
+ uint32_t n_ovflerror; /* No. of overflow errors */
+ uint32_t n_unflerror; /* No. of underflow errors */
+ uint32_t n_rdev_nr_error;/* No. of rdev not
+ * ready errors
+ */
+ uint32_t n_rdev_lost_error;/* No. of rdev lost errors */
+ uint32_t n_rdev_logo_error;/* No. of rdev logo errors */
+ uint32_t n_link_down_error;/* No. of link down errors */
+ uint32_t n_no_xchg_error; /* No. no exchange error */
+ uint32_t n_unknown_error;/* No. of unhandled errors */
+ uint32_t n_aborted; /* No. of aborted I/Os */
+ uint32_t n_abrt_timedout; /* No. of abort timedouts */
+ uint32_t n_abrt_fail; /* No. of abort failures */
+ uint32_t n_abrt_dups; /* No. of duplicate aborts */
+ uint32_t n_abrt_race_comp; /* No. of aborts that raced
+ * with completions.
+ */
+ uint32_t n_abrt_busy_error;/* No. of abort failures
+ * due to CSIO_BUSY.
+ */
+ uint32_t n_closed; /* No. of closed I/Os */
+ uint32_t n_cls_busy_error; /* No. of close failures
+ * due to CSIO_BUSY.
+ */
+ uint32_t n_active; /* No. of IOs in active_q */
+ uint32_t n_tm_active; /* No. of TMs in active_q */
+ uint32_t n_wcbfn; /* No. of I/Os in worker
+ * cbfn q
+ */
+ uint32_t n_free_ioreq; /* No. of freelist entries */
+ uint32_t n_free_ddp; /* No. of DDP freelist */
+ uint32_t n_unaligned; /* No. of Unaligned SGls */
+ uint32_t n_inval_cplop; /* No. invalid CPL op's in IQ */
+ uint32_t n_inval_scsiop; /* No. invalid scsi op's in IQ*/
+};
+
+struct csio_scsim {
+ struct csio_hw *hw; /* Pointer to HW moduel */
+ uint8_t max_sge; /* Max SGE */
+ uint8_t proto_cmd_len; /* Proto specific SCSI
+ * cmd length
+ */
+ uint16_t proto_rsp_len; /* Proto specific SCSI
+ * response length
+ */
+ spinlock_t freelist_lock; /* Lock for ioreq freelist */
+ struct list_head active_q; /* Outstanding SCSI I/Os */
+ struct list_head ioreq_freelist; /* Free list of ioreq's */
+ struct list_head ddp_freelist; /* DDP descriptor freelist */
+ struct csio_scsi_stats stats; /* This module's statistics */
+};
+
+/* State machine defines */
+enum csio_scsi_ev {
+ CSIO_SCSIE_START_IO = 1, /* Start a regular SCSI IO */
+ CSIO_SCSIE_START_TM, /* Start a TM IO */
+ CSIO_SCSIE_COMPLETED, /* IO Completed */
+ CSIO_SCSIE_ABORT, /* Abort IO */
+ CSIO_SCSIE_ABORTED, /* IO Aborted */
+ CSIO_SCSIE_CLOSE, /* Close exchange */
+ CSIO_SCSIE_CLOSED, /* Exchange closed */
+ CSIO_SCSIE_DRVCLEANUP, /* Driver wants to manually
+ * cleanup this I/O.
+ */
+};
+
+enum csio_scsi_lev {
+ CSIO_LEV_ALL = 1,
+ CSIO_LEV_LNODE,
+ CSIO_LEV_RNODE,
+ CSIO_LEV_LUN,
+};
+
+struct csio_scsi_level_data {
+ enum csio_scsi_lev level;
+ struct csio_rnode *rnode;
+ struct csio_lnode *lnode;
+ uint64_t oslun;
+};
+
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq(struct csio_scsim *scm)
+{
+ struct csio_ioreq *ioreq = NULL;
+
+ csio_deq_from_head(&scm->ioreq_freelist, &ioreq);
+ if (ioreq)
+ csio_dec_stats(scm, n_free_ioreq);
+
+ return ioreq;
+}
+
+static inline void
+csio_put_scsi_ioreq(struct csio_scsim *scm, struct csio_ioreq *ioreq)
+{
+ list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist);
+ csio_inc_stats(scm, n_free_ioreq);
+}
+
+static inline void
+csio_put_scsi_ioreq_list(struct csio_scsim *scm, struct list_head *reqlist,
+ int n)
+{
+ list_splice_init(reqlist, &scm->ioreq_freelist);
+ scm->stats.n_free_ioreq += n;
+}
+
+static inline struct csio_dma_buf *
+csio_get_scsi_ddp(struct csio_scsim *scm)
+{
+ struct csio_dma_buf *ddp = NULL;
+
+ csio_deq_from_head(&scm->ddp_freelist, &ddp);
+ if (ddp)
+ csio_dec_stats(scm, n_free_ddp);
+
+ return ddp;
+}
+
+static inline void
+csio_put_scsi_ddp(struct csio_scsim *scm, struct csio_dma_buf *ddp)
+{
+ list_add_tail(&ddp->list, &scm->ddp_freelist);
+ csio_inc_stats(scm, n_free_ddp);
+}
+
+static inline void
+csio_put_scsi_ddp_list(struct csio_scsim *scm, struct list_head *reqlist,
+ int n)
+{
+ list_splice_tail_init(reqlist, &scm->ddp_freelist);
+ scm->stats.n_free_ddp += n;
+}
+
+static inline void
+csio_scsi_completed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_COMPLETED);
+ if (csio_list_deleted(&ioreq->sm.sm_list))
+ list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_aborted(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORTED);
+ list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_closed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSED);
+ list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_drvcleanup(struct csio_ioreq *ioreq)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_DRVCLEANUP);
+}
+
+/*
+ * csio_scsi_start_io - Kick starts the IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline csio_retval_t
+csio_scsi_start_io(struct csio_ioreq *ioreq)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_START_IO);
+ return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_start_tm - Kicks off the Task management IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline csio_retval_t
+csio_scsi_start_tm(struct csio_ioreq *ioreq)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_START_TM);
+ return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_abort - Abort an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline csio_retval_t
+csio_scsi_abort(struct csio_ioreq *ioreq)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORT);
+ return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_close - Close an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline csio_retval_t
+csio_scsi_close(struct csio_ioreq *ioreq)
+{
+ csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSE);
+ return ioreq->drv_status;
+}
+
+void csio_scsi_cleanup_io_q(struct csio_scsim *, struct list_head *);
+csio_retval_t csio_scsim_cleanup_io(struct csio_scsim *, bool abort);
+csio_retval_t csio_scsim_cleanup_io_lnode(struct csio_scsim *,
+ struct csio_lnode *);
+struct csio_ioreq *csio_scsi_cmpl_handler(struct csio_hw *, void *, uint32_t,
+ struct csio_fl_dma_buf *,
+ void *, uint8_t **);
+csio_retval_t csio_scsi_qconfig(struct csio_hw *);
+csio_retval_t csio_scsim_init(struct csio_scsim *, struct csio_hw *);
+void csio_scsim_exit(struct csio_scsim *);
+
+#endif /* __CSIO_SCSI_H__ */
diff --git a/drivers/scsi/csiostor/csio_wr.h b/drivers/scsi/csiostor/csio_wr.h
new file mode 100644
index 0000000..004a914
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_wr.h
@@ -0,0 +1,519 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_WR_H__
+#define __CSIO_WR_H__
+
+#include <linux/cache.h>
+
+#include "csio_defs.h"
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+
+/*
+ * SGE register field values.
+ */
+#define X_INGPCIEBOUNDARY_32B 0
+#define X_INGPCIEBOUNDARY_64B 1
+#define X_INGPCIEBOUNDARY_128B 2
+#define X_INGPCIEBOUNDARY_256B 3
+#define X_INGPCIEBOUNDARY_512B 4
+#define X_INGPCIEBOUNDARY_1024B 5
+#define X_INGPCIEBOUNDARY_2048B 6
+#define X_INGPCIEBOUNDARY_4096B 7
+
+/* GTS register */
+#define X_TIMERREG_COUNTER0 0
+#define X_TIMERREG_COUNTER1 1
+#define X_TIMERREG_COUNTER2 2
+#define X_TIMERREG_COUNTER3 3
+#define X_TIMERREG_COUNTER4 4
+#define X_TIMERREG_COUNTER5 5
+#define X_TIMERREG_RESTART_COUNTER 6
+#define X_TIMERREG_UPDATE_CIDX 7
+
+/*
+ * Egress Context field values
+ */
+#define X_FETCHBURSTMIN_16B 0
+#define X_FETCHBURSTMIN_32B 1
+#define X_FETCHBURSTMIN_64B 2
+#define X_FETCHBURSTMIN_128B 3
+
+#define X_FETCHBURSTMAX_64B 0
+#define X_FETCHBURSTMAX_128B 1
+#define X_FETCHBURSTMAX_256B 2
+#define X_FETCHBURSTMAX_512B 3
+
+#define X_HOSTFCMODE_NONE 0
+#define X_HOSTFCMODE_INGRESS_QUEUE 1
+#define X_HOSTFCMODE_STATUS_PAGE 2
+#define X_HOSTFCMODE_BOTH 3
+
+/*
+ * Ingress Context field values
+ */
+#define X_UPDATESCHEDULING_TIMER 0
+#define X_UPDATESCHEDULING_COUNTER_OPTTIMER 1
+
+#define X_UPDATEDELIVERY_NONE 0
+#define X_UPDATEDELIVERY_INTERRUPT 1
+#define X_UPDATEDELIVERY_STATUS_PAGE 2
+#define X_UPDATEDELIVERY_BOTH 3
+
+#define X_INTERRUPTDESTINATION_PCIE 0
+#define X_INTERRUPTDESTINATION_IQ 1
+
+#define X_RSPD_TYPE_FLBUF 0
+#define X_RSPD_TYPE_CPL 1
+#define X_RSPD_TYPE_INTR 2
+
+/* WR status is at the same position as retval in a CMD header */
+#define csio_wr_status(_wr) \
+ (FW_CMD_RETVAL_GET(ntohl(((struct fw_cmd_hdr *)(_wr))->lo)))
+
+struct csio_hw;
+
+extern int csio_intr_coalesce_cnt;
+extern int csio_intr_coalesce_time;
+
+/* Ingress queue params */
+struct csio_iq_params {
+
+ uint8_t iq_start:1;
+ uint8_t iq_stop:1;
+ uint8_t pfn:3;
+
+ uint8_t vfn;
+
+ uint16_t physiqid;
+ uint16_t iqid;
+
+ uint16_t fl0id;
+ uint16_t fl1id;
+
+ uint8_t viid;
+
+ uint8_t type;
+ uint8_t iqasynch;
+ uint8_t reserved4;
+
+ uint8_t iqandst;
+ uint8_t iqanus;
+ uint8_t iqanud;
+
+ uint16_t iqandstindex;
+
+ uint8_t iqdroprss;
+ uint8_t iqpciech;
+ uint8_t iqdcaen;
+
+ uint8_t iqdcacpu;
+ uint8_t iqintcntthresh;
+ uint8_t iqo;
+
+ uint8_t iqcprio;
+ uint8_t iqesize;
+
+ uint16_t iqsize;
+
+ uint64_t iqaddr;
+
+ uint8_t iqflintiqhsen;
+ uint8_t reserved5;
+ uint8_t iqflintcongen;
+ uint8_t iqflintcngchmap;
+
+ uint32_t reserved6;
+
+ uint8_t fl0hostfcmode;
+ uint8_t fl0cprio;
+ uint8_t fl0paden;
+ uint8_t fl0packen;
+ uint8_t fl0congen;
+ uint8_t fl0dcaen;
+
+ uint8_t fl0dcacpu;
+ uint8_t fl0fbmin;
+
+ uint8_t fl0fbmax;
+ uint8_t fl0cidxfthresho;
+ uint8_t fl0cidxfthresh;
+
+ uint16_t fl0size;
+
+ uint64_t fl0addr;
+
+ uint64_t reserved7;
+
+ uint8_t fl1hostfcmode;
+ uint8_t fl1cprio;
+ uint8_t fl1paden;
+ uint8_t fl1packen;
+ uint8_t fl1congen;
+ uint8_t fl1dcaen;
+
+ uint8_t fl1dcacpu;
+ uint8_t fl1fbmin;
+
+ uint8_t fl1fbmax;
+ uint8_t fl1cidxfthresho;
+ uint8_t fl1cidxfthresh;
+
+ uint16_t fl1size;
+
+ uint64_t fl1addr;
+};
+
+/* Egress queue params */
+struct csio_eq_params {
+
+ uint8_t pfn;
+ uint8_t vfn;
+
+ uint8_t eqstart:1;
+ uint8_t eqstop:1;
+
+ uint16_t physeqid;
+ uint32_t eqid;
+
+ uint8_t hostfcmode:2;
+ uint8_t cprio:1;
+ uint8_t pciechn:3;
+
+ uint16_t iqid;
+
+ uint8_t dcaen:1;
+ uint8_t dcacpu:5;
+
+ uint8_t fbmin:3;
+ uint8_t fbmax:3;
+
+ uint8_t cidxfthresho:1;
+ uint8_t cidxfthresh:3;
+
+ uint16_t eqsize;
+
+ uint64_t eqaddr;
+};
+
+struct csio_dma_buf {
+ struct list_head list;
+ void *vaddr; /* Virtual address */
+ dma_addr_t paddr; /* Physical address */
+ uint32_t len; /* Buffer size */
+};
+
+/* Defines for csio_ioreq->datadir */
+enum {
+ CSIO_IOREQF_DMA_BIDI = 0x0,
+ CSIO_IOREQF_DMA_WRITE = 0x1,
+ CSIO_IOREQF_DMA_READ = 0x2,
+ CSIO_IOREQF_DMA_NONE = 0x4,
+};
+
+/* Generic I/O request structure */
+struct csio_ioreq {
+ struct csio_sm sm; /* SM, List
+ * should be the first member
+ */
+ int iq_idx; /* Ingress queue index */
+ int eq_idx; /* Egress queue index */
+ uint32_t nsge; /* Number of SG elements */
+ uint32_t tmo; /* Driver timeout */
+ uint32_t datadir; /* Data direction */
+ struct csio_dma_buf dma_buf; /* Req/resp DMA buffers */
+ uint16_t wr_status; /* WR completion status */
+ uint16_t drv_status; /* Driver internal status */
+ struct csio_lnode *lnode; /* Owner lnode */
+ struct csio_rnode *rnode; /* Src/destination rnode */
+ void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *);
+ /* completion callback */
+ void *scratch1; /* Scratch area 1.
+ */
+ void *scratch2; /* Scratch area 2. */
+ struct list_head gen_list; /* Any list associated with
+ * this ioreq.
+ */
+ uint64_t fw_handle; /* Unique handle passed
+ * to FW
+ */
+ uint8_t dcopy; /* Data copy required */
+ uint8_t reserved1;
+ uint16_t reserved2;
+ struct completion cmplobj; /* ioreq completion object */
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Egress status page for egress cidx updates
+ */
+struct csio_qstatus_page {
+ __be32 qid;
+ __be16 cidx;
+ __be16 pidx;
+};
+
+
+enum {
+ CSIO_MAX_FLBUF_PER_IQWR = 4,
+ CSIO_QCREDIT_SZ = 64, /* pidx/cidx increments
+ * in bytes
+ */
+ CSIO_MAX_QID = 0xFFFF,
+ CSIO_MAX_IQ = 128,
+
+ CSIO_SGE_NTIMERS = 6,
+ CSIO_SGE_NCOUNTERS = 4,
+ CSIO_SGE_FL_SIZE_REGS = 16,
+};
+
+/* Defines for type */
+enum {
+ CSIO_EGRESS = 1,
+ CSIO_INGRESS = 2,
+ CSIO_FREELIST = 3,
+};
+
+/*
+ * Structure for footer (last 2 flits) of Ingress Queue Entry.
+ */
+struct csio_iqwr_footer {
+ __be32 hdrbuflen_pidx;
+ __be32 pldbuflen_qid;
+ union {
+ u8 type_gen;
+ __be64 last_flit;
+ } u;
+};
+
+#define IQWRF_NEWBUF (1 << 31)
+#define IQWRF_LEN_GET(x) (((x) >> 0) & 0x7fffffffU)
+#define IQWRF_GEN_SHIFT 7
+#define IQWRF_TYPE_GET(x) (((x) >> 4) & 0x3U)
+
+
+/*
+ * WR pair:
+ * ========
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/len to be passed back to the caller -
+ * hence the Work request pair structure.
+ */
+struct csio_wr_pair {
+ void *addr1;
+ uint32_t size1;
+ void *addr2;
+ uint32_t size2;
+};
+
+/*
+ * The following structure is used by ingress processing to return the
+ * free list buffers to consumers.
+ */
+struct csio_fl_dma_buf {
+ struct csio_dma_buf flbufs[CSIO_MAX_FLBUF_PER_IQWR];
+ /* Freelist DMA buffers */
+ int offset; /* Offset within the
+ * first FL buf.
+ */
+ uint32_t totlen; /* Total length */
+ uint8_t defer_free; /* Free of buffer can
+ * deferred
+ */
+};
+
+/* Data-types */
+typedef void (*iq_handler_t)(struct csio_hw *, void *, uint32_t,
+ struct csio_fl_dma_buf *, void *);
+
+struct csio_iq {
+ uint16_t iqid; /* Queue ID */
+ uint16_t physiqid; /* Physical Queue ID */
+ uint16_t genbit; /* Generation bit,
+ * initially set to 1
+ */
+ int flq_idx; /* Freelist queue index */
+ iq_handler_t iq_intx_handler; /* IQ INTx handler routine */
+};
+
+struct csio_eq {
+ uint16_t eqid; /* Qid */
+ uint16_t physeqid; /* Physical Queue ID */
+};
+
+struct csio_fl {
+ uint16_t flid; /* Qid */
+ uint16_t packen; /* Packing enabled? */
+ int offset; /* Offset within FL buf */
+ int sreg; /* Size register */
+ struct csio_dma_buf *bufs; /* Free list buffer ptr array
+ * indexed using flq->cidx/pidx
+ */
+};
+
+struct csio_qstats {
+ uint32_t n_tot_reqs; /* Total no. of Requests */
+ uint32_t n_tot_rsps; /* Total no. of responses */
+ uint32_t n_qwrap; /* Queue wraps */
+ uint32_t n_eq_wr_split; /* Number of split EQ WRs */
+ uint32_t n_qentry; /* Queue entry */
+ uint32_t n_qempty; /* Queue empty */
+ uint32_t n_qfull; /* Queue fulls */
+ uint32_t n_rsp_unknown; /* Unknown response type */
+ uint32_t n_stray_comp; /* Stray completion intr */
+ uint32_t n_flq_refill; /* Number of FL refills */
+};
+
+/* Queue metadata */
+struct csio_q {
+ uint16_t type; /* Type: Ingress/Egress/FL */
+ uint16_t pidx; /* producer index */
+ uint16_t cidx; /* consumer index */
+ uint16_t inc_idx; /* Incremental index */
+ uint32_t wr_sz; /* Size of all WRs in this q
+ * if fixed
+ */
+ void *vstart; /* Base virtual address
+ * of queue
+ */
+ void *vwrap; /* Virtual end address to
+ * wrap around at
+ */
+ uint32_t credits; /* Size of queue in credits */
+ void *owner; /* Owner */
+ union { /* Queue contexts */
+ struct csio_iq iq;
+ struct csio_eq eq;
+ struct csio_fl fl;
+ } un;
+
+ dma_addr_t pstart; /* Base physical address of
+ * queue
+ */
+ uint32_t portid; /* PCIE Channel */
+ uint32_t size; /* Size of queue in bytes */
+ struct csio_qstats stats; /* Statistics */
+} ____cacheline_aligned_in_smp;
+
+struct csio_sge {
+ uint32_t csio_fl_align; /* Calculated and cached
+ * for fast path
+ */
+ uint32_t sge_control; /* padding, boundaries,
+ * lengths, etc.
+ */
+ uint32_t sge_host_page_size; /* Host page size */
+ uint32_t sge_fl_buf_size[CSIO_SGE_FL_SIZE_REGS];
+ /* free list buffer sizes */
+ uint16_t timer_val[CSIO_SGE_NTIMERS];
+ uint8_t counter_val[CSIO_SGE_NCOUNTERS];
+};
+
+/* Work request module */
+struct csio_wrm {
+ int num_q; /* Number of queues */
+ struct csio_q **q_arr; /* Array of queue pointers
+ * allocated dynamically
+ * based on configured values
+ */
+ uint32_t fw_iq_start; /* Start ID of IQ for this fn*/
+ uint32_t fw_eq_start; /* Start ID of EQ for this fn*/
+ struct csio_q *intr_map[CSIO_MAX_IQ];
+ /* IQ-id to IQ map table. */
+ int free_qidx; /* queue idx of free queue */
+ struct csio_sge sge; /* SGE params */
+};
+
+#define csio_get_q(__hw, __idx) ((__hw)->wrm.q_arr[__idx])
+#define csio_q_type(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->type)
+#define csio_q_pidx(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->pidx)
+#define csio_q_cidx(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->cidx)
+#define csio_q_inc_idx(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->inc_idx)
+#define csio_q_vstart(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->vstart)
+#define csio_q_pstart(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->pstart)
+#define csio_q_size(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->size)
+#define csio_q_credits(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->credits)
+#define csio_q_portid(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->portid)
+#define csio_q_wr_sz(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->wr_sz)
+#define csio_q_iqid(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->un.iq.iqid)
+#define csio_q_physiqid(__hw, __idx) \
+ ((__hw)->wrm.q_arr[(__idx)]->un.iq.physiqid)
+#define csio_q_iq_flq_idx(__hw, __idx) \
+ ((__hw)->wrm.q_arr[(__idx)]->un.iq.flq_idx)
+#define csio_q_eqid(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->un.eq.eqid)
+#define csio_q_flid(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->un.fl.flid)
+
+#define csio_q_physeqid(__hw, __idx) \
+ ((__hw)->wrm.q_arr[(__idx)]->un.eq.physeqid)
+#define csio_iq_has_fl(__iq) ((__iq)->un.iq.flq_idx != -1)
+#define csio_q_owner(__hw, __idx) ((__hw)->wrm.q_arr[(__idx)]->owner)
+
+#define csio_q_iq_to_flid(__hw, __iq_idx) \
+ csio_q_flid((__hw), (__hw)->wrm.q_arr[(__iq_qidx)]->un.iq.flq_idx)
+#define csio_q_set_intr_map(__hw, __iq_idx, __rel_iq_id) \
+ (__hw)->wrm.intr_map[__rel_iq_id] = csio_get_q(__hw, __iq_idx)
+
+struct csio_mb;
+
+int csio_wr_alloc_q(struct csio_hw *, uint32_t, uint32_t,
+ uint16_t, void *, uint32_t, int, iq_handler_t);
+csio_retval_t csio_wr_iq_create(struct csio_hw *, void *, int,
+ uint32_t, uint8_t, bool,
+ void (*)(struct csio_hw *, struct csio_mb *));
+csio_retval_t csio_wr_eq_create(struct csio_hw *, void *, int, int, uint8_t,
+ void (*)(struct csio_hw *, struct csio_mb *));
+csio_retval_t csio_wr_destroy_queues(struct csio_hw *, bool cmd);
+
+
+csio_retval_t csio_wr_get(struct csio_hw *, int, uint32_t,
+ struct csio_wr_pair *);
+void csio_wr_copy_to_wrp(void *, struct csio_wr_pair *, uint32_t, uint32_t);
+csio_retval_t csio_wr_issue(struct csio_hw *, int, bool);
+csio_retval_t csio_wr_process_iq(struct csio_hw *, struct csio_q *,
+ void (*)(struct csio_hw *, void *,
+ uint32_t, struct csio_fl_dma_buf *,
+ void *),
+ void *);
+csio_retval_t csio_wr_process_iq_idx(struct csio_hw *, int,
+ void (*)(struct csio_hw *, void *,
+ uint32_t, struct csio_fl_dma_buf *,
+ void *),
+ void *);
+
+void csio_wr_sge_init(struct csio_hw *);
+csio_retval_t csio_wrm_init(struct csio_wrm *, struct csio_hw *);
+void csio_wrm_exit(struct csio_wrm *, struct csio_hw *);
+
+#endif /* ifndef __CSIO_WR_H__ */
diff --git a/drivers/scsi/csiostor/t4fw_api_stor.h b/drivers/scsi/csiostor/t4fw_api_stor.h
new file mode 100644
index 0000000..b96903a
--- /dev/null
+++ b/drivers/scsi/csiostor/t4fw_api_stor.h
@@ -0,0 +1,578 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _T4FW_API_STOR_H_
+#define _T4FW_API_STOR_H_
+
+
+/******************************************************************************
+ * R E T U R N V A L U E S
+ ********************************/
+
+enum fw_retval {
+ FW_SUCCESS = 0, /* completed sucessfully */
+ FW_EPERM = 1, /* operation not permitted */
+ FW_ENOENT = 2, /* no such file or directory */
+ FW_EIO = 5, /* input/output error; hw bad */
+ FW_ENOEXEC = 8, /* exec format error; inv microcode */
+ FW_EAGAIN = 11, /* try again */
+ FW_ENOMEM = 12, /* out of memory */
+ FW_EFAULT = 14, /* bad address; fw bad */
+ FW_EBUSY = 16, /* resource busy */
+ FW_EEXIST = 17, /* file exists */
+ FW_EINVAL = 22, /* invalid argument */
+ FW_ENOSPC = 28, /* no space left on device */
+ FW_ENOSYS = 38, /* functionality not implemented */
+ FW_EPROTO = 71, /* protocol error */
+ FW_EADDRINUSE = 98, /* address already in use */
+ FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */
+ FW_ENETDOWN = 100, /* network is down */
+ FW_ENETUNREACH = 101, /* network is unreachable */
+ FW_ENOBUFS = 105, /* no buffer space available */
+ FW_ETIMEDOUT = 110, /* timeout */
+ FW_EINPROGRESS = 115, /* fw internal */
+ FW_SCSI_ABORT_REQUESTED = 128, /* */
+ FW_SCSI_ABORT_TIMEDOUT = 129, /* */
+ FW_SCSI_ABORTED = 130, /* */
+ FW_SCSI_CLOSE_REQUESTED = 131, /* */
+ FW_ERR_LINK_DOWN = 132, /* */
+ FW_RDEV_NOT_READY = 133, /* */
+ FW_ERR_RDEV_LOST = 134, /* */
+ FW_ERR_RDEV_LOGO = 135, /* */
+ FW_FCOE_NO_XCHG = 136, /* */
+ FW_SCSI_RSP_ERR = 137, /* */
+ FW_ERR_RDEV_IMPL_LOGO = 138, /* */
+ FW_SCSI_UNDER_FLOW_ERR = 139, /* */
+ FW_SCSI_OVER_FLOW_ERR = 140, /* */
+ FW_SCSI_DDP_ERR = 141, /* DDP error*/
+ FW_SCSI_TASK_ERR = 142, /* No SCSI tasks available */
+};
+
+enum fw_fcoe_link_sub_op {
+ FCOE_LINK_DOWN = 0x0,
+ FCOE_LINK_UP = 0x1,
+ FCOE_LINK_COND = 0x2,
+};
+
+enum fw_fcoe_link_status {
+ FCOE_LINKDOWN = 0x0,
+ FCOE_LINKUP = 0x1,
+};
+
+enum fw_ofld_prot {
+ PROT_FCOE = 0x1,
+ PROT_ISCSI = 0x2,
+};
+
+enum rport_type_fcoe {
+ FLOGI_VFPORT = 0x1, /* 0xfffffe */
+ FDISC_VFPORT = 0x2, /* 0xfffffe */
+ NS_VNPORT = 0x3, /* 0xfffffc */
+ REG_FC4_VNPORT = 0x4, /* any FC4 type VN_PORT */
+ REG_VNPORT = 0x5, /* 0xfffxxx - non FC4 port in switch */
+ FDMI_VNPORT = 0x6, /* 0xfffffa */
+ FAB_CTLR_VNPORT = 0x7, /* 0xfffffd */
+};
+
+enum event_cause_fcoe {
+ PLOGI_ACC_RCVD = 0x01,
+ PLOGI_RJT_RCVD = 0x02,
+ PLOGI_RCVD = 0x03,
+ PLOGO_RCVD = 0x04,
+ PRLI_ACC_RCVD = 0x05,
+ PRLI_RJT_RCVD = 0x06,
+ PRLI_RCVD = 0x07,
+ PRLO_RCVD = 0x08,
+ NPORT_ID_CHGD = 0x09,
+ FLOGO_RCVD = 0x0a,
+ CLR_VIRT_LNK_RCVD = 0x0b,
+ FLOGI_ACC_RCVD = 0x0c,
+ FLOGI_RJT_RCVD = 0x0d,
+ FDISC_ACC_RCVD = 0x0e,
+ FDISC_RJT_RCVD = 0x0f,
+ FLOGI_TMO_MAX_RETRY = 0x10,
+ IMPL_LOGO_ADISC_ACC = 0x11,
+ IMPL_LOGO_ADISC_RJT = 0x12,
+ IMPL_LOGO_ADISC_CNFLT = 0x13,
+ PRLI_TMO = 0x14,
+ ADISC_TMO = 0x15,
+ RSCN_DEV_LOST = 0x16,
+ SCR_ACC_RCVD = 0x17,
+ ADISC_RJT_RCVD = 0x18,
+ LOGO_SNT = 0x19,
+ PROTO_ERR_IMPL_LOGO = 0x1a,
+};
+
+enum fcoe_cmn_type {
+ FCOE_ELS,
+ FCOE_CT,
+ FCOE_SCSI_CMD,
+ FCOE_UNSOL_ELS,
+};
+
+enum fw_wr_stor_opcodes {
+ FW_RDEV_WR = 0x38,
+ FW_FCOE_ELS_CT_WR = 0x30,
+ FW_SCSI_WRITE_WR = 0x31,
+ FW_SCSI_READ_WR = 0x32,
+ FW_SCSI_CMD_WR = 0x33,
+ FW_SCSI_ABRT_CLS_WR = 0x34,
+};
+
+struct fw_rdev_wr {
+ __be32 op_to_immdlen;
+ __be32 alloc_to_len16;
+ __be64 cookie;
+ u8 protocol;
+ u8 event_cause;
+ u8 cur_state;
+ u8 prev_state;
+ __be32 flags_to_assoc_flowid;
+ union rdev_entry {
+ struct fcoe_rdev_entry {
+ __be32 flowid;
+ u8 protocol;
+ u8 event_cause;
+ u8 flags;
+ u8 rjt_reason;
+ u8 cur_login_st;
+ u8 prev_login_st;
+ __be16 rcv_fr_sz;
+ u8 rd_xfer_rdy_to_rport_type;
+ u8 vft_to_qos;
+ u8 org_proc_assoc_to_acc_rsp_code;
+ u8 enh_disc_to_tgt;
+ u8 wwnn[8];
+ u8 wwpn[8];
+ __be16 iqid;
+ u8 fc_oui[3];
+ u8 r_id[3];
+ } fcoe_rdev;
+ struct iscsi_rdev_entry {
+ __be32 flowid;
+ u8 protocol;
+ u8 event_cause;
+ u8 flags;
+ u8 r3;
+ __be16 iscsi_opts;
+ __be16 tcp_opts;
+ __be16 ip_opts;
+ __be16 max_rcv_len;
+ __be16 max_snd_len;
+ __be16 first_brst_len;
+ __be16 max_brst_len;
+ __be16 r4;
+ __be16 def_time2wait;
+ __be16 def_time2ret;
+ __be16 nop_out_intrvl;
+ __be16 non_scsi_to;
+ __be16 isid;
+ __be16 tsid;
+ __be16 port;
+ __be16 tpgt;
+ u8 r5[6];
+ __be16 iqid;
+ } iscsi_rdev;
+ } u;
+};
+
+#define FW_RDEV_WR_FLOWID_GET(x) (((x) >> 8) & 0xfffff)
+#define FW_RDEV_WR_ASSOC_FLOWID_GET(x) (((x) >> 0) & 0xfffff)
+#define FW_RDEV_WR_RPORT_TYPE_GET(x) (((x) >> 0) & 0x1f)
+#define FW_RDEV_WR_NPIV_GET(x) (((x) >> 6) & 0x1)
+#define FW_RDEV_WR_CLASS_GET(x) (((x) >> 4) & 0x3)
+#define FW_RDEV_WR_TASK_RETRY_ID_GET(x) (((x) >> 5) & 0x1)
+#define FW_RDEV_WR_RETRY_GET(x) (((x) >> 4) & 0x1)
+#define FW_RDEV_WR_CONF_CMPL_GET(x) (((x) >> 3) & 0x1)
+#define FW_RDEV_WR_INI_GET(x) (((x) >> 1) & 0x1)
+#define FW_RDEV_WR_TGT_GET(x) (((x) >> 0) & 0x1)
+
+struct fw_fcoe_els_ct_wr {
+ __be32 op_immdlen;
+ __be32 flowid_len16;
+ __be64 cookie;
+ __be16 iqid;
+ u8 tmo_val;
+ u8 els_ct_type;
+ u8 ctl_pri;
+ u8 cp_en_class;
+ __be16 xfer_cnt;
+ u8 fl_to_sp;
+ u8 l_id[3];
+ u8 r5;
+ u8 r_id[3];
+ __be64 rsp_dmaaddr;
+ __be32 rsp_dmalen;
+ __be32 r6;
+};
+
+#define FW_FCOE_ELS_CT_WR_OPCODE(x) ((x) << 24)
+#define FW_FCOE_ELS_CT_WR_OPCODE_GET(x) (((x) >> 24) & 0xff)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN(x) ((x) << 0)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN_GET(x) (((x) >> 0) & 0xff)
+#define FW_FCOE_ELS_CT_WR_SP(x) ((x) << 0)
+
+struct fw_scsi_write_wr {
+ __be32 op_immdlen;
+ __be32 flowid_len16;
+ __be64 cookie;
+ __be16 iqid;
+ u8 tmo_val;
+ u8 use_xfer_cnt;
+ union fw_scsi_write_priv {
+ struct fcoe_write_priv {
+ u8 ctl_pri;
+ u8 cp_en_class;
+ u8 r3_lo[2];
+ } fcoe;
+ struct iscsi_write_priv {
+ u8 r3[4];
+ } iscsi;
+ } u;
+ __be32 xfer_cnt;
+ __be32 ini_xfer_cnt;
+ __be64 rsp_dmaaddr;
+ __be32 rsp_dmalen;
+ __be32 r4;
+};
+
+#define FW_SCSI_WRITE_WR_IMMDLEN(x) ((x) << 0)
+
+struct fw_scsi_read_wr {
+ __be32 op_immdlen;
+ __be32 flowid_len16;
+ __be64 cookie;
+ __be16 iqid;
+ u8 tmo_val;
+ u8 use_xfer_cnt;
+ union fw_scsi_read_priv {
+ struct fcoe_read_priv {
+ u8 ctl_pri;
+ u8 cp_en_class;
+ u8 r3_lo[2];
+ } fcoe;
+ struct iscsi_read_priv {
+ u8 r3[4];
+ } iscsi;
+ } u;
+ __be32 xfer_cnt;
+ __be32 ini_xfer_cnt;
+ __be64 rsp_dmaaddr;
+ __be32 rsp_dmalen;
+ __be32 r4;
+};
+
+#define FW_SCSI_READ_WR_IMMDLEN(x) ((x) << 0)
+
+struct fw_scsi_cmd_wr {
+ __be32 op_immdlen;
+ __be32 flowid_len16;
+ __be64 cookie;
+ __be16 iqid;
+ u8 tmo_val;
+ u8 r3;
+ union fw_scsi_cmd_priv {
+ struct fcoe_cmd_priv {
+ u8 ctl_pri;
+ u8 cp_en_class;
+ u8 r4_lo[2];
+ } fcoe;
+ struct iscsi_cmd_priv {
+ u8 r4[4];
+ } iscsi;
+ } u;
+ u8 r5[8];
+ __be64 rsp_dmaaddr;
+ __be32 rsp_dmalen;
+ __be32 r6;
+};
+
+#define FW_SCSI_CMD_WR_IMMDLEN(x) ((x) << 0)
+
+#define SCSI_ABORT 0
+#define SCSI_CLOSE 1
+
+struct fw_scsi_abrt_cls_wr {
+ __be32 op_immdlen;
+ __be32 flowid_len16;
+ __be64 cookie;
+ __be16 iqid;
+ u8 tmo_val;
+ u8 sub_opcode_to_chk_all_io;
+ u8 r3[4];
+ __be64 t_cookie;
+};
+
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE(x) ((x) << 2)
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE_GET(x) (((x) >> 2) & 0x3f)
+#define FW_SCSI_ABRT_CLS_WR_CHK_ALL_IO(x) ((x) << 0)
+
+enum fw_cmd_stor_opcodes {
+ FW_FCOE_RES_INFO_CMD = 0x31,
+ FW_FCOE_LINK_CMD = 0x32,
+ FW_FCOE_VNP_CMD = 0x33,
+ FW_FCOE_SPARAMS_CMD = 0x35,
+ FW_FCOE_STATS_CMD = 0x37,
+ FW_FCOE_FCF_CMD = 0x38,
+};
+
+struct fw_fcoe_res_info_cmd {
+ __be32 op_to_read;
+ __be32 retval_len16;
+ __be16 e_d_tov;
+ __be16 r_a_tov_seq;
+ __be16 r_a_tov_els;
+ __be16 r_r_tov;
+ __be32 max_xchgs;
+ __be32 max_ssns;
+ __be32 used_xchgs;
+ __be32 used_ssns;
+ __be32 max_fcfs;
+ __be32 max_vnps;
+ __be32 used_fcfs;
+ __be32 used_vnps;
+};
+
+struct fw_fcoe_link_cmd {
+ __be32 op_to_portid;
+ __be32 retval_len16;
+ __be32 sub_opcode_fcfi;
+ u8 r3;
+ u8 lstatus;
+ __be16 flags;
+ u8 r4;
+ u8 set_vlan;
+ __be16 vlan_id;
+ __be32 vnpi_pkd;
+ __be16 r6;
+ u8 phy_mac[6];
+ u8 vnport_wwnn[8];
+ u8 vnport_wwpn[8];
+};
+
+#define FW_FCOE_LINK_CMD_PORTID(x) ((x) << 0)
+#define FW_FCOE_LINK_CMD_PORTID_GET(x) (((x) >> 0) & 0xf)
+#define FW_FCOE_LINK_CMD_SUB_OPCODE(x) ((x) << 24U)
+#define FW_FCOE_LINK_CMD_FCFI(x) ((x) << 0)
+#define FW_FCOE_LINK_CMD_FCFI_GET(x) (((x) >> 0) & 0xffffff)
+#define FW_FCOE_LINK_CMD_VNPI_GET(x) (((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_vnp_cmd {
+ __be32 op_to_fcfi;
+ __be32 alloc_to_len16;
+ __be32 gen_wwn_to_vnpi;
+ __be32 vf_id;
+ __be16 iqid;
+ u8 vnport_mac[6];
+ u8 vnport_wwnn[8];
+ u8 vnport_wwpn[8];
+ u8 cmn_srv_parms[16];
+ u8 clsp_word_0_1[8];
+};
+
+#define FW_FCOE_VNP_CMD_FCFI(x) ((x) << 0)
+#define FW_FCOE_VNP_CMD_ALLOC (1U << 31)
+#define FW_FCOE_VNP_CMD_FREE (1U << 30)
+#define FW_FCOE_VNP_CMD_MODIFY (1U << 29)
+#define FW_FCOE_VNP_CMD_GEN_WWN (1U << 22)
+#define FW_FCOE_VNP_CMD_VFID_EN (1U << 20)
+#define FW_FCOE_VNP_CMD_VNPI(x) ((x) << 0)
+#define FW_FCOE_VNP_CMD_VNPI_GET(x) (((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_sparams_cmd {
+ __be32 op_to_portid;
+ __be32 retval_len16;
+ u8 r3[7];
+ u8 cos;
+ u8 lport_wwnn[8];
+ u8 lport_wwpn[8];
+ u8 cmn_srv_parms[16];
+ u8 cls_srv_parms[16];
+};
+
+#define FW_FCOE_SPARAMS_CMD_PORTID(x) ((x) << 0)
+
+struct fw_fcoe_stats_cmd {
+ __be32 op_to_flowid;
+ __be32 free_to_len16;
+ union fw_fcoe_stats {
+ struct fw_fcoe_stats_ctl {
+ u8 nstats_port;
+ u8 port_valid_ix;
+ __be16 r6;
+ __be32 r7;
+ __be64 stat0;
+ __be64 stat1;
+ __be64 stat2;
+ __be64 stat3;
+ __be64 stat4;
+ __be64 stat5;
+ } ctl;
+ struct fw_fcoe_port_stats {
+ __be64 tx_bcast_bytes;
+ __be64 tx_bcast_frames;
+ __be64 tx_mcast_bytes;
+ __be64 tx_mcast_frames;
+ __be64 tx_ucast_bytes;
+ __be64 tx_ucast_frames;
+ __be64 tx_drop_frames;
+ __be64 tx_offload_bytes;
+ __be64 tx_offload_frames;
+ __be64 rx_bcast_bytes;
+ __be64 rx_bcast_frames;
+ __be64 rx_mcast_bytes;
+ __be64 rx_mcast_frames;
+ __be64 rx_ucast_bytes;
+ __be64 rx_ucast_frames;
+ __be64 rx_err_frames;
+ } port_stats;
+ struct fw_fcoe_fcf_stats {
+ __be32 fip_tx_bytes;
+ __be32 fip_tx_fr;
+ __be64 fcf_ka;
+ __be64 mcast_adv_rcvd;
+ __be16 ucast_adv_rcvd;
+ __be16 sol_sent;
+ __be16 vlan_req;
+ __be16 vlan_rpl;
+ __be16 clr_vlink;
+ __be16 link_down;
+ __be16 link_up;
+ __be16 logo;
+ __be16 flogi_req;
+ __be16 flogi_rpl;
+ __be16 fdisc_req;
+ __be16 fdisc_rpl;
+ __be16 fka_prd_chg;
+ __be16 fc_map_chg;
+ __be16 vfid_chg;
+ u8 no_fka_req;
+ u8 no_vnp;
+ } fcf_stats;
+ struct fw_fcoe_pcb_stats {
+ __be64 tx_bytes;
+ __be64 tx_frames;
+ __be64 rx_bytes;
+ __be64 rx_frames;
+ __be32 vnp_ka;
+ __be32 unsol_els_rcvd;
+ __be64 unsol_cmd_rcvd;
+ __be16 implicit_logo;
+ __be16 flogi_inv_sparm;
+ __be16 fdisc_inv_sparm;
+ __be16 flogi_rjt;
+ __be16 fdisc_rjt;
+ __be16 no_ssn;
+ __be16 mac_flt_fail;
+ __be16 inv_fr_rcvd;
+ } pcb_stats;
+ struct fw_fcoe_scb_stats {
+ __be64 tx_bytes;
+ __be64 tx_frames;
+ __be64 rx_bytes;
+ __be64 rx_frames;
+ __be32 host_abrt_req;
+ __be32 adap_auto_abrt;
+ __be32 adap_abrt_rsp;
+ __be32 host_ios_req;
+ __be16 ssn_offl_ios;
+ __be16 ssn_not_rdy_ios;
+ u8 rx_data_ddp_err;
+ u8 ddp_flt_set_err;
+ __be16 rx_data_fr_err;
+ u8 bad_st_abrt_req;
+ u8 no_io_abrt_req;
+ u8 abort_tmo;
+ u8 abort_tmo_2;
+ __be32 abort_req;
+ u8 no_ppod_res_tmo;
+ u8 bp_tmo;
+ u8 adap_auto_cls;
+ u8 no_io_cls_req;
+ __be32 host_cls_req;
+ __be64 unsol_cmd_rcvd;
+ __be32 plogi_req_rcvd;
+ __be32 prli_req_rcvd;
+ __be16 logo_req_rcvd;
+ __be16 prlo_req_rcvd;
+ __be16 plogi_rjt_rcvd;
+ __be16 prli_rjt_rcvd;
+ __be32 adisc_req_rcvd;
+ __be32 rscn_rcvd;
+ __be32 rrq_req_rcvd;
+ __be32 unsol_els_rcvd;
+ u8 adisc_rjt_rcvd;
+ u8 scr_rjt;
+ u8 ct_rjt;
+ u8 inval_bls_rcvd;
+ __be32 ba_rjt_rcvd;
+ } scb_stats;
+ } u;
+};
+
+#define FW_FCOE_STATS_CMD_FLOWID(x) ((x) << 0)
+#define FW_FCOE_STATS_CMD_FREE (1U << 30)
+#define FW_FCOE_STATS_CMD_NSTATS(x) ((x) << 4)
+#define FW_FCOE_STATS_CMD_PORT(x) ((x) << 0)
+#define FW_FCOE_STATS_CMD_PORT_VALID (1U << 7)
+#define FW_FCOE_STATS_CMD_IX(x) ((x) << 0)
+
+struct fw_fcoe_fcf_cmd {
+ __be32 op_to_fcfi;
+ __be32 retval_len16;
+ __be16 priority_pkd;
+ u8 mac[6];
+ u8 name_id[8];
+ u8 fabric[8];
+ __be16 vf_id;
+ __be16 max_fcoe_size;
+ u8 vlan_id;
+ u8 fc_map[3];
+ __be32 fka_adv;
+ __be32 r6;
+ u8 r7_hi;
+ u8 fpma_to_portid;
+ u8 spma_mac[6];
+ __be64 r8;
+};
+
+#define FW_FCOE_FCF_CMD_FCFI(x) ((x) << 0)
+#define FW_FCOE_FCF_CMD_FCFI_GET(x) (((x) >> 0) & 0xfffff)
+#define FW_FCOE_FCF_CMD_PRIORITY_GET(x) (((x) >> 0) & 0xff)
+#define FW_FCOE_FCF_CMD_FPMA_GET(x) (((x) >> 6) & 0x1)
+#define FW_FCOE_FCF_CMD_SPMA_GET(x) (((x) >> 5) & 0x1)
+#define FW_FCOE_FCF_CMD_LOGIN_GET(x) (((x) >> 4) & 0x1)
+#define FW_FCOE_FCF_CMD_PORTID_GET(x) (((x) >> 0) & 0xf)
+
+#endif /* _T4FW_API_STOR_H_ */
--
1.7.1
^ permalink raw reply related
* [PATCH 8/8] cxgb4: Chelsio FCoE offload driver submission (cxgb4 common header updates).
From: Naresh Kumar Inna @ 2012-08-23 22:27 UTC (permalink / raw)
To: JBottomley, linux-scsi, dm; +Cc: netdev, naresh, chethan
In-Reply-To: <1345760873-12101-1-git-send-email-naresh@chelsio.com>
This patch contains updates to firmware/hardware header files shared
between csiostor and cxgb4, and the resulting changes to the cxgb4 files.
Signed-off-by: Naresh Kumar Inna <naresh@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +-
drivers/net/ethernet/chelsio/cxgb4/sge.c | 10 +-
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 16 ++--
drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 69 ++++++++++++++-
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 104 +++++++++++++++++++---
6 files changed, 170 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 5ed49af..b56d96c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3102,7 +3102,7 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
memset(c, 0, sizeof(*c));
c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
FW_CMD_REQUEST | FW_CMD_READ);
- c->retval_len16 = htonl(FW_LEN16(*c));
+ c->cfvalid_to_len16 = htonl(FW_LEN16(*c));
ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
if (ret < 0)
return ret;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 8596aca..6109982 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -455,7 +455,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
{
if (q->pend_cred >= 8) {
wmb();
- t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO |
+ t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
QID(q->cntxt_id) | PIDX(q->pend_cred / 8));
q->pend_cred &= 7;
}
@@ -2020,10 +2020,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
goto fl_nomem;
flsz = fl->size / 8 + STAT_LEN / sizeof(struct tx_desc);
- c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN |
+ c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN(1) |
FW_IQ_CMD_FL0FETCHRO(1) |
FW_IQ_CMD_FL0DATARO(1) |
- FW_IQ_CMD_FL0PADEN);
+ FW_IQ_CMD_FL0PADEN(1));
c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) |
FW_IQ_CMD_FL0FBMAX(3));
c.fl0size = htons(flsz);
@@ -2416,10 +2416,10 @@ void t4_sge_init(struct adapter *adap)
unsigned int fl_align_log = ilog2(FL_ALIGN);
t4_set_reg_field(adap, SGE_CONTROL, PKTSHIFT_MASK |
- INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE,
+ INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE(1),
INGPADBOUNDARY(fl_align_log - 5) | PKTSHIFT(2) |
RXPKTCPLMODE |
- (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
+ (STAT_LEN == 128 ? EGRSTATUSPAGESIZE(1) : 0));
/*
* Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index fa947df..a943faa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -456,12 +456,12 @@ static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
if (!byte_cnt || byte_cnt > 4)
return -EINVAL;
- if (t4_read_reg(adapter, SF_OP) & BUSY)
+ if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
return -EBUSY;
cont = cont ? SF_CONT : 0;
lock = lock ? SF_LOCK : 0;
t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1));
- ret = t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+ ret = t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
if (!ret)
*valp = t4_read_reg(adapter, SF_DATA);
return ret;
@@ -484,14 +484,14 @@ static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
{
if (!byte_cnt || byte_cnt > 4)
return -EINVAL;
- if (t4_read_reg(adapter, SF_OP) & BUSY)
+ if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
return -EBUSY;
cont = cont ? SF_CONT : 0;
lock = lock ? SF_LOCK : 0;
t4_write_reg(adapter, SF_DATA, val);
t4_write_reg(adapter, SF_OP, lock |
cont | BYTECNT(byte_cnt - 1) | OP_WR);
- return t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+ return t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
}
/**
@@ -1972,14 +1972,14 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
t4_write_reg(adap, EPIO_REG(DATA0), mask0);
t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i) | EPIOWR);
t4_read_reg(adap, EPIO_REG(OP)); /* flush */
- if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+ if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
return -ETIMEDOUT;
/* write CRC */
t4_write_reg(adap, EPIO_REG(DATA0), crc);
t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i + 32) | EPIOWR);
t4_read_reg(adap, EPIO_REG(OP)); /* flush */
- if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+ if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
return -ETIMEDOUT;
}
#undef EPIO_REG
@@ -2118,7 +2118,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
struct fw_hello_cmd c;
INIT_CMD(c, HELLO, WRITE);
- c.err_to_mbasyncnot = htonl(
+ c.err_to_clearinit = htonl(
FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : 0xff) |
@@ -2126,7 +2126,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret == 0 && state) {
- u32 v = ntohl(c.err_to_mbasyncnot);
+ u32 v = ntohl(c.err_to_clearinit);
if (v & FW_HELLO_CMD_INIT)
*state = DEV_STATE_INIT;
else if (v & FW_HELLO_CMD_ERR)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index eb71b82..b760808 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -658,6 +658,7 @@ struct ulptx_sgl {
__be32 cmd_nsge;
#define ULPTX_CMD(x) ((x) << 24)
#define ULPTX_NSGE(x) ((x) << 0)
+#define ULPTX_MORE (1U << 23)
__be32 len0;
__be64 addr0;
struct ulptx_sge_pair sge[0];
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 111fc32..6bace75 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -67,7 +67,7 @@
#define QID_MASK 0xffff8000U
#define QID_SHIFT 15
#define QID(x) ((x) << QID_SHIFT)
-#define DBPRIO 0x00004000U
+#define DBPRIO(x) ((x) << 14)
#define PIDX_MASK 0x00003fffU
#define PIDX_SHIFT 0
#define PIDX(x) ((x) << PIDX_SHIFT)
@@ -89,7 +89,7 @@
#define SGE_CONTROL 0x1008
#define DCASYSTYPE 0x00080000U
#define RXPKTCPLMODE 0x00040000U
-#define EGRSTATUSPAGESIZE 0x00020000U
+#define EGRSTATUSPAGESIZE(x) ((x) << 17)
#define PKTSHIFT_MASK 0x00001c00U
#define PKTSHIFT_SHIFT 10
#define PKTSHIFT(x) ((x) << PKTSHIFT_SHIFT)
@@ -111,6 +111,13 @@
#define HOSTPAGESIZEPF0_MASK 0x0000000fU
#define HOSTPAGESIZEPF0_SHIFT 0
#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_SHIFT)
+#define HOSTPAGESIZEPF1(x) ((x) << 4)
+#define HOSTPAGESIZEPF2(x) ((x) << 8)
+#define HOSTPAGESIZEPF3(x) ((x) << 12)
+#define HOSTPAGESIZEPF4(x) ((x) << 16)
+#define HOSTPAGESIZEPF5(x) ((x) << 20)
+#define HOSTPAGESIZEPF6(x) ((x) << 24)
+#define HOSTPAGESIZEPF7(x) ((x) << 28)
#define SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010
#define QUEUESPERPAGEPF0_MASK 0x0000000fU
@@ -155,6 +162,14 @@
#define SGE_INT_ENABLE3 0x1040
#define SGE_FL_BUFFER_SIZE0 0x1044
#define SGE_FL_BUFFER_SIZE1 0x1048
+#define SGE_FL_BUFFER_SIZE2 0x104c
+#define SGE_FL_BUFFER_SIZE3 0x1050
+#define SGE_FL_BUFFER_SIZE4 0x1054
+#define SGE_FL_BUFFER_SIZE5 0x1058
+#define SGE_FL_BUFFER_SIZE6 0x105c
+#define SGE_FL_BUFFER_SIZE7 0x1060
+#define SGE_FL_BUFFER_SIZE8 0x1064
+
#define SGE_INGRESS_RX_THRESHOLD 0x10a0
#define THRESHOLD_0_MASK 0x3f000000U
#define THRESHOLD_0_SHIFT 24
@@ -173,6 +188,17 @@
#define THRESHOLD_3(x) ((x) << THRESHOLD_3_SHIFT)
#define THRESHOLD_3_GET(x) (((x) & THRESHOLD_3_MASK) >> THRESHOLD_3_SHIFT)
+#define SGE_DBFIFO_STATUS 0x10a4
+#define HP_INT_THRESH_SHIFT 28
+#define HP_INT_THRESH_MASK 0xfU
+#define HP_INT_THRESH(x) ((x) << HP_INT_THRESH_SHIFT)
+#define LP_INT_THRESH_SHIFT 12
+#define LP_INT_THRESH_MASK 0xfU
+#define LP_INT_THRESH(x) ((x) << LP_INT_THRESH_SHIFT)
+
+#define SGE_DOORBELL_CONTROL 0x10a8
+#define ENABLE_DROP (1 << 13)
+
#define SGE_TIMER_VALUE_0_AND_1 0x10b8
#define TIMERVALUE0_MASK 0xffff0000U
#define TIMERVALUE0_SHIFT 16
@@ -184,7 +210,25 @@
#define TIMERVALUE1_GET(x) (((x) & TIMERVALUE1_MASK) >> TIMERVALUE1_SHIFT)
#define SGE_TIMER_VALUE_2_AND_3 0x10bc
+#define TIMERVALUE2_MASK 0xffff0000U
+#define TIMERVALUE2_SHIFT 16
+#define TIMERVALUE2(x) ((x) << TIMERVALUE0_SHIFT)
+#define TIMERVALUE2_GET(x) (((x) & TIMERVALUE0_MASK) >> TIMERVALUE0_SHIFT)
+#define TIMERVALUE3_MASK 0x0000ffffU
+#define TIMERVALUE3_SHIFT 0
+#define TIMERVALUE3(x) ((x) << TIMERVALUE1_SHIFT)
+#define TIMERVALUE3_GET(x) (((x) & TIMERVALUE1_MASK) >> TIMERVALUE1_SHIFT)
+
#define SGE_TIMER_VALUE_4_AND_5 0x10c0
+#define TIMERVALUE4_MASK 0xffff0000U
+#define TIMERVALUE4_SHIFT 16
+#define TIMERVALUE4(x) ((x) << TIMERVALUE0_SHIFT)
+#define TIMERVALUE4_GET(x) (((x) & TIMERVALUE0_MASK) >> TIMERVALUE0_SHIFT)
+#define TIMERVALUE5_MASK 0x0000ffffU
+#define TIMERVALUE5_SHIFT 0
+#define TIMERVALUE5(x) ((x) << TIMERVALUE1_SHIFT)
+#define TIMERVALUE5_GET(x) (((x) & TIMERVALUE1_MASK) >> TIMERVALUE1_SHIFT)
+
#define SGE_DEBUG_INDEX 0x10cc
#define SGE_DEBUG_DATA_HIGH 0x10d0
#define SGE_DEBUG_DATA_LOW 0x10d4
@@ -243,6 +287,10 @@
#define M_HP_INT_THRESH 0xfU
#define M_LP_INT_THRESH 0xfU
+#define PCIE_PF_CFG 0x40
+#define AIVEC(x) ((x) << 4)
+#define AIVEC_MASK 0x3ffU
+
#define PCIE_PF_CLI 0x44
#define PCIE_INT_CAUSE 0x3004
#define UNXSPLCPLERR 0x20000000U
@@ -287,6 +335,15 @@
#define WINDOW(x) ((x) << WINDOW_SHIFT)
#define PCIE_MEM_ACCESS_OFFSET 0x306c
+#define PCIE_FW 0x30b8
+#define PCIE_FW_ERR 0x80000000U
+#define PCIE_FW_INIT 0x40000000U
+#define PCIE_FW_HALT 0x20000000U
+#define PCIE_FW_MASTER_VLD 0x00008000U
+#define PCIE_FW_MASTER(x) ((x) << 12)
+#define PCIE_FW_MASTER_MASK 0x7
+#define PCIE_FW_MASTER_GET(x) (((x) >> 12) & PCIE_FW_MASTER_MASK)
+
#define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908
#define RNPP 0x80000000U
#define RPCP 0x20000000U
@@ -384,6 +441,8 @@
#define EDC_1_BASE_ADDR 0x7980
#define CIM_BOOT_CFG 0x7b00
+#define UPCRST 0x00000001U
+
#define BOOTADDR_MASK 0xffffff00U
#define CIM_PF_MAILBOX_DATA 0x240
@@ -395,6 +454,9 @@
#define MBOWNER(x) ((x) << MBOWNER_SHIFT)
#define MBOWNER_GET(x) (((x) & MBOWNER_MASK) >> MBOWNER_SHIFT)
+#define CIM_PF_HOST_INT_ENABLE 0x288
+#define MBMSGRDYINTEN(x) ((x) << 19)
+
#define CIM_PF_HOST_INT_CAUSE 0x28c
#define MBMSGRDYINT 0x00080000U
@@ -825,7 +887,7 @@
#define SF_DATA 0x193f8
#define SF_OP 0x193fc
-#define BUSY 0x80000000U
+#define SF_BUSY 0x80000000U
#define SF_LOCK 0x00000010U
#define SF_CONT 0x00000008U
#define BYTECNT_MASK 0x00000006U
@@ -884,6 +946,7 @@
#define I2CM 0x00000002U
#define CIM 0x00000001U
+#define PL_INT_ENABLE 0x19410
#define PL_INT_MAP0 0x19414
#define PL_RST 0x19428
#define PIORST 0x00000002U
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index ad53f79..034ca39 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -68,6 +68,7 @@ struct fw_wr_hdr {
};
#define FW_WR_OP(x) ((x) << 24)
+#define FW_WR_OP_GET(x) (((x) >> 24) & 0xff)
#define FW_WR_ATOMIC(x) ((x) << 23)
#define FW_WR_FLUSH(x) ((x) << 22)
#define FW_WR_COMPL(x) ((x) << 21)
@@ -155,6 +156,9 @@ struct fw_eth_tx_pkt_vm_wr {
#define FW_CMD_MAX_TIMEOUT 3000
+#define FW_CMD_HELLO_TIMEOUT (3 * FW_CMD_MAX_TIMEOUT)
+#define FW_CMD_HELLO_RETRIES 3
+
enum fw_cmd_opcodes {
FW_LDST_CMD = 0x01,
FW_RESET_CMD = 0x03,
@@ -209,6 +213,7 @@ struct fw_cmd_hdr {
#define FW_CMD_OP(x) ((x) << 24)
#define FW_CMD_OP_GET(x) (((x) >> 24) & 0xff)
#define FW_CMD_REQUEST (1U << 23)
+#define FW_CMD_REQUEST_GET(x) (((x) >> 23) & 0x1)
#define FW_CMD_READ (1U << 22)
#define FW_CMD_WRITE (1U << 21)
#define FW_CMD_EXEC (1U << 20)
@@ -216,6 +221,7 @@ struct fw_cmd_hdr {
#define FW_CMD_RETVAL(x) ((x) << 8)
#define FW_CMD_RETVAL_GET(x) (((x) >> 8) & 0xff)
#define FW_CMD_LEN16(x) ((x) << 0)
+#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16)
enum fw_ldst_addrspc {
FW_LDST_ADDRSPC_FIRMWARE = 0x0001,
@@ -228,7 +234,8 @@ enum fw_ldst_addrspc {
FW_LDST_ADDRSPC_TP_MIB = 0x0012,
FW_LDST_ADDRSPC_MDIO = 0x0018,
FW_LDST_ADDRSPC_MPS = 0x0020,
- FW_LDST_ADDRSPC_FUNC = 0x0028
+ FW_LDST_ADDRSPC_FUNC = 0x0028,
+ FW_LDST_ADDRSPC_FUNC_PCIE = 0x0029,
};
enum fw_ldst_mps_fid {
@@ -290,6 +297,16 @@ struct fw_ldst_cmd {
__be64 data0;
__be64 data1;
} func;
+ struct fw_ldst_pcie {
+ u8 ctrl_to_fn;
+ u8 bnum;
+ u8 r;
+ u8 ext_r;
+ u8 select_naccess;
+ u8 pcie_fn;
+ __be16 nset_pkd;
+ __be32 data[12];
+ } pcie;
} u;
};
@@ -299,24 +316,42 @@ struct fw_ldst_cmd {
#define FW_LDST_CMD_FID(x) ((x) << 15)
#define FW_LDST_CMD_CTL(x) ((x) << 0)
#define FW_LDST_CMD_RPLCPF(x) ((x) << 0)
+#define FW_LDST_CMD_LC (1U << 4)
+#define FW_LDST_CMD_NACCESS(x) ((x) << 0)
+#define FW_LDST_CMD_FN(x) ((x) << 0)
struct fw_reset_cmd {
__be32 op_to_write;
__be32 retval_len16;
__be32 val;
- __be32 r3;
+ __be32 halt_pkd;
+};
+
+#define FW_RESET_CMD_HALT (1U << 31)
+
+enum {
+ FW_HELLO_CMD_STAGE_OS = 0,
+ FW_HELLO_CMD_STAGE_PREOS0 = 1,
+ FW_HELLO_CMD_STAGE_PREOS1 = 2,
+ FW_HELLO_CMD_STAGE_POSTOS = 3,
};
struct fw_hello_cmd {
__be32 op_to_write;
__be32 retval_len16;
- __be32 err_to_mbasyncnot;
-#define FW_HELLO_CMD_ERR (1U << 31)
-#define FW_HELLO_CMD_INIT (1U << 30)
-#define FW_HELLO_CMD_MASTERDIS(x) ((x) << 29)
-#define FW_HELLO_CMD_MASTERFORCE(x) ((x) << 28)
-#define FW_HELLO_CMD_MBMASTER(x) ((x) << 24)
-#define FW_HELLO_CMD_MBASYNCNOT(x) ((x) << 20)
+ __be32 err_to_clearinit;
+#define FW_HELLO_CMD_ERR (1U << 31)
+#define FW_HELLO_CMD_INIT (1U << 30)
+#define FW_HELLO_CMD_MASTERDIS(x) ((x) << 29)
+#define FW_HELLO_CMD_MASTERFORCE(x) ((x) << 28)
+#define FW_HELLO_CMD_MBMASTER_MASK 0xf
+#define FW_HELLO_CMD_MBMASTER(x) ((x) << 24)
+#define FW_HELLO_CMD_MBMASTER_GET(x) \
+ (((x) >> 24) & FW_HELLO_CMD_MBMASTER_MASK)
+#define FW_HELLO_CMD_MBASYNCNOTINT(x) ((x) << 23)
+#define FW_HELLO_CMD_MBASYNCNOT(x) ((x) << 20)
+#define FW_HELLO_CMD_STAGE(x) ((x) << 17)
+#define FW_HELLO_CMD_CLEARINIT (1U << 16)
__be32 fwrev;
};
@@ -399,11 +434,20 @@ enum fw_caps_config_iscsi {
enum fw_caps_config_fcoe {
FW_CAPS_CONFIG_FCOE_INITIATOR = 0x00000001,
FW_CAPS_CONFIG_FCOE_TARGET = 0x00000002,
+ FW_CAPS_CONFIG_FCOE_CTRL_OFLD = 0x00000004,
+};
+
+enum fw_memtype_cf {
+ FW_MEMTYPE_CF_EDC0 = 0x0,
+ FW_MEMTYPE_CF_EDC1 = 0x1,
+ FW_MEMTYPE_CF_EXTMEM = 0x2,
+ FW_MEMTYPE_CF_FLASH = 0x4,
+ FW_MEMTYPE_CF_INTERNAL = 0x5,
};
struct fw_caps_config_cmd {
__be32 op_to_write;
- __be32 retval_len16;
+ __be32 cfvalid_to_len16;
__be32 r2;
__be32 hwmbitmap;
__be16 nbmcaps;
@@ -416,10 +460,15 @@ struct fw_caps_config_cmd {
__be16 r4;
__be16 iscsicaps;
__be16 fcoecaps;
- __be32 r5;
- __be64 r6;
+ __be32 cfcsum;
+ __be32 finiver;
+ __be32 finicsum;
};
+#define FW_CAPS_CONFIG_CMD_CFVALID (1U << 27)
+#define FW_CAPS_CONFIG_CMD_MEMTYPE_CF(x) ((x) << 24)
+#define FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(x) ((x) << 16)
+
/*
* params command mnemonics
*/
@@ -451,6 +500,7 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_INTVER_FCOE = 0x0A,
FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
+ FW_PARAMS_PARAM_DEV_CF = 0x0D,
};
/*
@@ -511,6 +561,9 @@ enum fw_params_param_dmaq {
#define FW_PARAMS_PARAM_Z(x) ((x) << 0)
#define FW_PARAMS_PARAM_XYZ(x) ((x) << 0)
#define FW_PARAMS_PARAM_YZ(x) ((x) << 0)
+#define FW_PARAMS_PARAM_X_GET(x) (((x) >> 16) & 0xff)
+#define FW_PARAMS_PARAM_Y_GET(x) (((x) >> 8) & 0xff)
+#define FW_PARAMS_PARAM_Z_GET(x) (((x) >> 0) & 0xff)
struct fw_params_cmd {
__be32 op_to_vfn;
@@ -648,8 +701,8 @@ struct fw_iq_cmd {
#define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6)
#define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4)
#define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3)
-#define FW_IQ_CMD_FL0PADEN (1U << 2)
-#define FW_IQ_CMD_FL0PACKEN (1U << 1)
+#define FW_IQ_CMD_FL0PADEN(x) ((x) << 2)
+#define FW_IQ_CMD_FL0PACKEN(x) ((x) << 1)
#define FW_IQ_CMD_FL0CONGEN (1U << 0)
#define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15)
@@ -1137,6 +1190,14 @@ enum fw_port_dcb_cfg_rc {
FW_PORT_DCB_CFG_ERROR = 0x1
};
+enum fw_port_dcb_type {
+ FW_PORT_DCB_TYPE_PGID = 0x00,
+ FW_PORT_DCB_TYPE_PGRATE = 0x01,
+ FW_PORT_DCB_TYPE_PRIORATE = 0x02,
+ FW_PORT_DCB_TYPE_PFC = 0x03,
+ FW_PORT_DCB_TYPE_APP_ID = 0x04,
+};
+
struct fw_port_cmd {
__be32 op_to_portid;
__be32 action_to_len16;
@@ -1204,6 +1265,7 @@ struct fw_port_cmd {
#define FW_PORT_CMD_TXIPG(x) ((x) << 19)
#define FW_PORT_CMD_LSTATUS (1U << 31)
+#define FW_PORT_CMD_LSTATUS_GET(x) (((x) >> 31) & 0x1)
#define FW_PORT_CMD_LSPEED(x) ((x) << 24)
#define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f)
#define FW_PORT_CMD_TXPAUSE (1U << 23)
@@ -1252,6 +1314,9 @@ enum fw_port_module_type {
FW_PORT_MOD_TYPE_TWINAX_PASSIVE,
FW_PORT_MOD_TYPE_TWINAX_ACTIVE,
FW_PORT_MOD_TYPE_LRM,
+ FW_PORT_MOD_TYPE_ERROR = FW_PORT_CMD_MODTYPE_MASK - 3,
+ FW_PORT_MOD_TYPE_UNKNOWN = FW_PORT_CMD_MODTYPE_MASK - 2,
+ FW_PORT_MOD_TYPE_NOTSUPPORTED = FW_PORT_CMD_MODTYPE_MASK - 1,
FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK
};
@@ -1613,7 +1678,11 @@ struct fw_hdr {
u8 intfver_iscsi;
u8 intfver_fcoe;
u8 reserved2;
- __be32 reserved3[27];
+ __u32 reserved3;
+ __u32 reserved4;
+ __u32 reserved5;
+ __be32 flags;
+ __be32 reserved6[23];
};
#define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
@@ -1621,6 +1690,11 @@ struct fw_hdr {
#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
#define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff)
+enum fw_hdr_flags {
+ FW_HDR_FLAGS_RESET_HALT = 0x00000001,
+};
+
+
#define S_FW_CMD_OP 24
#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] [v2] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped device
From: Stephen Warren @ 2012-08-23 22:54 UTC (permalink / raw)
To: Timur Tabi
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Andy Fleming,
David Miller
In-Reply-To: <1345751071-23128-1-git-send-email-timur-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
On 08/23/2012 01:44 PM, Timur Tabi wrote:
> Add support for an MDIO bus multiplexer controlled by a simple memory-mapped
> device, like an FPGA. The device must be memory-mapped and contain only
> 8-bit registers (which keeps things simple).
> +++ b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
> + /* The FPGA node */
> + fpga: board-control@3,0 {
> + compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
> + reg = <3 0 0x30>;
Why not add the following here:
#address-cells = <1>:
#size-cells = <1>;
ranges = <...>;
> +
> + mdio-mux-emi2 {
> + compatible = "mdio-mux-mmioreg", "mdio-mux";
> + mdio-parent-bus = <&xmdio0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <9>; // BRDCFG1
Then, that'd have to be <9 1>;
That way, ...
> diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
> +static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
> + /* The MMIO device is the parent of this device */
> + np2 = of_get_parent(np);
> + if (!np2) {
> + dev_err(&pdev->dev, "could not find parent MMIO device\n");
> + return -ENODEV;
> + }
> +
> + ret = of_address_to_resource(np2, 0, &res);
> + if (ret) {
> + dev_err(&pdev->dev, "could not obtain memory map for node %s\n",
> + np2->full_name);
> + return ret;
> + }
> + s->phys = res.start;
You could simplify all that into just "of_iomap(np, 0)", and all the
address translation etc. happens entirely automatically, in the standard
fashion for DT.
The advantage here is that it completely decouples the mdio-mux-mmioreg
driver from any knowledge of its parent; you could just as easily use
this driver/binding as a device directly on some SoC bus, rather than
requiring there to be a parent device above it. After all, the mux
register might be some random standalone on-SoC register (although I
wonder if that case might not be better covered by a mdio-mux-pinctrl
driver instead; I guess it depends on how special-purpose the mux
register is).
^ permalink raw reply
* Re: [PATCH] e1000: add byte queue limits
From: Jeff Kirsher @ 2012-08-24 0:00 UTC (permalink / raw)
To: Otto Estuardo Solares Cabrera; +Cc: netdev
In-Reply-To: <1345714098-2644-1-git-send-email-solca@galileo.edu>
On 08/23/2012 02:28 AM, Otto Estuardo Solares Cabrera wrote:
> Signed-off-by: Otto Estuardo Solares Cabrera<solca@galileo.edu>
> ---
> Copied from e1000e.
> Cc me please.
>
> drivers/net/ethernet/intel/e1000/e1000_main.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
Added to my queue of patches, thanks!
^ permalink raw reply
* Proposal.
From: Tai Bei @ 2012-08-23 22:55 UTC (permalink / raw)
Good-day To You,
It is understandable that you might be a little bit apprehensive
because you do not know me but I have a lucrative business proposal of
mutual interest to share with you. I got your reference in my search for
someone who suits my proposed business relationship. I am Mr. Tai Bei,
officer with the International bank of Taipei (Bank SinoPac). I will
need you to assist me in executing a business project from Taiwan to
your country. It involves the transfer of money, Everything concerning
this transaction shall be legally done without hitch.
Once the funds have been successfully transferred into your account, we
shall share in the ratio to be agreed by both of us. I shall furnish you
with more information about this operation immediately I receive a
positive response from you.
Kind Regards,
Tai Bei
^ permalink raw reply
* [RFC] How should the device tree represent multiple Ethernet PHYs in a single package?
From: David Daney @ 2012-08-24 0:21 UTC (permalink / raw)
To: Netdev,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
Grant Likely, Rob Herring
We are working with a Dual 10G Ethernet PHY Device (Vitesse vcs8488) and
would like to represent it in the device tree for several of our boards.
This device has some registers and pins that are common to both of the
PHY units on the die. Other registers are standard IEEE803.3-C45.
Here is my first (hand-waving) take at how it should look:
ethernet-phy-nexus@0 {
reg = <0x00>;
/* The Vitesse VSC8488 is a dual-PHY where
* some of the configuration is common across
* both of the phy devices such as the reset
* line and the base MDIO address.
*/
compatible = "vitesse,vsc8488-nexus", "ethernet-phy-nexus";
#address-cells = <1>;
#size-cells = <0>;
ranges;
/* Hardware reset signal */
reset = <&gpio 17 0>;
/* Other common initialization (laser power, etc. )*/
phy30: ethernet-phy@0 {
/* Absolute address */
reg = <0x0>;
compatible = "vitesse,vsc8488", "ethernet-phy-ieee802.3-c45";
interrupt-parent = <&gpio>;
interrupts = <13 8>;
/* TX Fault GPIO line */
tx_fault = <1>;
/* GPIO that enables output */
txon = <4>;
/* INT A GPIO output */
inta = <5>;
};
phy31: ethernet-phy@1 {
/* Absolute address */
reg = <0x1>;
compatible = "vitesse,vsc8488", "ethernet-phy-ieee802.3-c45";
interrupt-parent = <&gpio>;
interrupts = <13 8>;
/* TX Fault GPIO line */
tx_fault = <8>;
/* GPIO that enables output */
txon = <10>;
/* INT A GPIO output */
inta = <5>;
};
};
We would then modify of_mdio.c so that when it encountered an
"ethernet-phy-nexus", it would add all the children of the nexus.
Comments? Objections?
Thanks, and let me know what you think,
David Daney
^ permalink raw reply
* Re: [PATCH] [v2] netdev/phy: add MDIO bus multiplexer driven by a memory-mapped device
From: Tabi Timur-B04825 @ 2012-08-24 0:28 UTC (permalink / raw)
To: Stephen Warren
Cc: Fleming Andy-AFLEMING, David Miller, ddaney.cavm@gmail.com,
netdev@vger.kernel.org, devicetree-discuss@lists.ozlabs.org
In-Reply-To: <5036B4BD.70208@wwwdotorg.org>
Stephen Warren wrote:
> On 08/23/2012 01:44 PM, Timur Tabi wrote:
>> Add support for an MDIO bus multiplexer controlled by a simple memory-mapped
>> device, like an FPGA. The device must be memory-mapped and contain only
>> 8-bit registers (which keeps things simple).
>
>> +++ b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
>
>> + /* The FPGA node */
>> + fpga: board-control@3,0 {
>> + compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
>> + reg = <3 0 0x30>;
>
> Why not add the following here:
>
> #address-cells = <1>:
> #size-cells = <1>;
> ranges = <...>;
I forgot to add them in the txt file. They are in the real device tree.
>
>> +
>> + mdio-mux-emi2 {
>> + compatible = "mdio-mux-mmioreg", "mdio-mux";
>> + mdio-parent-bus = <&xmdio0>;
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <9>; // BRDCFG1
>
> Then, that'd have to be <9 1>;
Actually, I had #size-cells = <0>.
>
> That way, ...
>
>> diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
>
>> +static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
>
>> + /* The MMIO device is the parent of this device */
>> + np2 = of_get_parent(np);
>> + if (!np2) {
>> + dev_err(&pdev->dev, "could not find parent MMIO device\n");
>> + return -ENODEV;
>> + }
>> +
>> + ret = of_address_to_resource(np2, 0, &res);
>> + if (ret) {
>> + dev_err(&pdev->dev, "could not obtain memory map for node %s\n",
>> + np2->full_name);
>> + return ret;
>> + }
>> + s->phys = res.start;
>
> You could simplify all that into just "of_iomap(np, 0)", and all the
> address translation etc. happens entirely automatically, in the standard
> fashion for DT.
Ah! You're right. I don't need to look for the parent node. Duh.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* [PATCH net-next 0/15] qlcnic: patches for new adapter - Qlogic 83XX CNA
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
From: Sony Chacko <sony.chacko@qlogic.com>
Patch series will restructure the existing 82XX adapter driver to create
a common driver for Qlogic 82XX and 83XX adapters.
Please apply it to net-next.
Thanks,
Sony
^ permalink raw reply
* [PATCH net-next 03/15] qlcnic: Refactoring - Move sysfs code
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Anirban Chakraborty
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Create seperate file for sysfs code
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 3 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 10 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 926 +--------------------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 896 ++++++++++++++++++++
4 files changed, 911 insertions(+), 924 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index a26ee17..34db053 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
- qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o
+ qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
+ qlcnic_sysfs.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 53ccbf9..7f1a3e1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1559,6 +1559,16 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
int qlcnic_setup_intr(struct qlcnic_adapter *);
int qlcnic_poll(struct napi_struct *, int);
int qlcnic_rx_poll(struct napi_struct *, int);
+void qlcnic_set_vlan_config(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
+/* functions in qlcnic_sysfs.c */
+int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *);
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *);
+void qlcnic_create_diag_entries(struct qlcnic_adapter *);
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index a5941c4..b4edf75 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -17,7 +17,6 @@
#include <net/ip.h>
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
-#include <linux/sysfs.h>
#include <linux/aer.h>
#include <linux/log2.h>
@@ -71,11 +70,6 @@ static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
static void qlcnic_poll_controller(struct net_device *netdev);
#endif
-static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
-
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
@@ -692,7 +686,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
return err;
}
-static void
+void
qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
@@ -725,8 +719,7 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
return 0;
}
-static void
-qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
@@ -744,8 +737,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
qlcnic_set_netdev_features(adapter, esw_cfg);
}
-static int
-qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
{
struct qlcnic_esw_func_cfg esw_cfg;
@@ -2812,81 +2804,6 @@ qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return -EOPNOTSUPP;
}
-static ssize_t
-qlcnic_store_bridged_mode(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- unsigned long new;
- int ret = -EINVAL;
-
- if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
- goto err_out;
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
- goto err_out;
-
- if (strict_strtoul(buf, 2, &new))
- goto err_out;
-
- if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
- ret = len;
-
-err_out:
- return ret;
-}
-
-static ssize_t
-qlcnic_show_bridged_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int bridged_mode = 0;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
-
- return sprintf(buf, "%d\n", bridged_mode);
-}
-
-static struct device_attribute dev_attr_bridged_mode = {
- .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_bridged_mode,
- .store = qlcnic_store_bridged_mode,
-};
-
-static ssize_t
-qlcnic_store_diag_mode(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- unsigned long new;
-
- if (strict_strtoul(buf, 2, &new))
- return -EINVAL;
-
- if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
- adapter->flags ^= QLCNIC_DIAG_ENABLED;
-
- return len;
-}
-
-static ssize_t
-qlcnic_show_diag_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n",
- !!(adapter->flags & QLCNIC_DIAG_ENABLED));
-}
-
-static struct device_attribute dev_attr_diag_mode = {
- .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_diag_mode,
- .store = qlcnic_store_diag_mode,
-};
-
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
{
if (!use_msi_x && !use_msi) {
@@ -2939,843 +2856,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
return err;
}
-static int
-qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
- u8 *rate)
-{
- *rate = LSB(beacon);
- *state = MSB(beacon);
-
- QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
-
- if (!*state) {
- *rate = __QLCNIC_MAX_LED_RATE;
- return 0;
- } else if (*state > __QLCNIC_MAX_LED_STATE)
- return -EINVAL;
-
- if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
- return -EINVAL;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_store_beacon(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int max_sds_rings = adapter->max_sds_rings;
- u16 beacon;
- u8 b_state, b_rate;
- int err;
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
- dev_warn(dev, "LED test not supported for non "
- "privilege function\n");
- return -EOPNOTSUPP;
- }
-
- if (len != sizeof(u16))
- return QL_STATUS_INVALID_PARAM;
-
- memcpy(&beacon, buf, sizeof(u16));
- err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
- if (err)
- return err;
-
- if (adapter->ahw->beacon_state == b_state)
- return len;
-
- rtnl_lock();
-
- if (!adapter->ahw->beacon_state)
- if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
- rtnl_unlock();
- return -EBUSY;
- }
-
- if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
- err = -EIO;
- goto out;
- }
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
- if (err)
- goto out;
- set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
- }
-
- err = qlcnic_config_led(adapter, b_state, b_rate);
-
- if (!err) {
- err = len;
- adapter->ahw->beacon_state = b_state;
- }
-
- if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
- qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
-
- out:
- if (!adapter->ahw->beacon_state)
- clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
- rtnl_unlock();
-
- return err;
-}
-
-static ssize_t
-qlcnic_show_beacon(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
-}
-
-static struct device_attribute dev_attr_beacon = {
- .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
- .show = qlcnic_show_beacon,
- .store = qlcnic_store_beacon,
-};
-
-static int
-qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
- loff_t offset, size_t size)
-{
- size_t crb_size = 4;
-
- if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
- return -EIO;
-
- if (offset < QLCNIC_PCI_CRBSPACE) {
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
- QLCNIC_PCI_CAMQM_END))
- crb_size = 8;
- else
- return -EINVAL;
- }
-
- if ((size != crb_size) || (offset & (crb_size-1)))
- return -EINVAL;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- adapter->ahw->hw_ops->read_crb(adapter, buf, offset, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size);
- return size;
-}
-
-static int
-qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
- loff_t offset, size_t size)
-{
- if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
- return -EIO;
-
- if ((size != 8) || (offset & 0x7))
- return -EIO;
-
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u64 data;
- int ret;
-
- ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
- return -EIO;
-
- memcpy(buf, &data, size);
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u64 data;
- int ret;
-
- ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
- if (ret != 0)
- return ret;
-
- memcpy(&data, buf, size);
-
- if (qlcnic_pci_mem_write_2M(adapter, offset, data))
- return -EIO;
-
- return size;
-}
-
-static struct bin_attribute bin_attr_crb = {
- .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_crb,
- .write = qlcnic_sysfs_write_crb,
-};
-
-static struct bin_attribute bin_attr_mem = {
- .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_mem,
- .write = qlcnic_sysfs_write_mem,
-};
-
-static int
-validate_pm_config(struct qlcnic_adapter *adapter,
- struct qlcnic_pm_func_cfg *pm_cfg, int count)
-{
-
- u8 src_pci_func, s_esw_id, d_esw_id;
- u8 dest_pci_func;
- int i;
-
- for (i = 0; i < count; i++) {
- src_pci_func = pm_cfg[i].pci_func;
- dest_pci_func = pm_cfg[i].dest_npar;
- if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
- || dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- s_esw_id = adapter->npars[src_pci_func].phy_port;
- d_esw_id = adapter->npars[dest_pci_func].phy_port;
-
- if (s_esw_id != d_esw_id)
- return QL_STATUS_INVALID_PARAM;
-
- }
- return 0;
-
-}
-
-static ssize_t
-qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pm_func_cfg *pm_cfg;
- u32 id, action, pci_func;
- int count, rem, i, ret;
-
- count = size / sizeof(struct qlcnic_pm_func_cfg);
- rem = size % sizeof(struct qlcnic_pm_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- pm_cfg = (struct qlcnic_pm_func_cfg *) buf;
-
- ret = validate_pm_config(adapter, pm_cfg, count);
- if (ret)
- return ret;
- for (i = 0; i < count; i++) {
- pci_func = pm_cfg[i].pci_func;
- action = !!pm_cfg[i].action;
- id = adapter->npars[pci_func].phy_port;
- ret = qlcnic_config_port_mirroring(adapter, id,
- action, pci_func);
- if (ret)
- return ret;
- }
-
- for (i = 0; i < count; i++) {
- pci_func = pm_cfg[i].pci_func;
- id = adapter->npars[pci_func].phy_port;
- adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
- adapter->npars[pci_func].dest_npar = id;
- }
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
- int i;
-
- if (size != sizeof(pm_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- pm_cfg[i].action = adapter->npars[i].enable_pm;
- pm_cfg[i].dest_npar = 0;
- pm_cfg[i].pci_func = i;
- }
- memcpy(buf, &pm_cfg, size);
-
- return size;
-}
-
-static int
-validate_esw_config(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg, int count)
-{
- u32 op_mode;
- u8 pci_func;
- int i;
-
- op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
-
- for (i = 0; i < count; i++) {
- pci_func = esw_cfg[i].pci_func;
- if (pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
- QLCNIC_NON_PRIV_FUNC) {
- if (esw_cfg[i].mac_anti_spoof != 0)
- return QL_STATUS_INVALID_PARAM;
- if (esw_cfg[i].mac_override != 1)
- return QL_STATUS_INVALID_PARAM;
- if (esw_cfg[i].promisc_mode != 1)
- return QL_STATUS_INVALID_PARAM;
- }
- break;
- case QLCNIC_ADD_VLAN:
- if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
- return QL_STATUS_INVALID_PARAM;
- if (!esw_cfg[i].op_type)
- return QL_STATUS_INVALID_PARAM;
- break;
- case QLCNIC_DEL_VLAN:
- if (!esw_cfg[i].op_type)
- return QL_STATUS_INVALID_PARAM;
- break;
- default:
- return QL_STATUS_INVALID_PARAM;
- }
- }
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_func_cfg *esw_cfg;
- struct qlcnic_npar_info *npar;
- int count, rem, i, ret;
- u8 pci_func, op_mode = 0;
-
- count = size / sizeof(struct qlcnic_esw_func_cfg);
- rem = size % sizeof(struct qlcnic_esw_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- esw_cfg = (struct qlcnic_esw_func_cfg *) buf;
- ret = validate_esw_config(adapter, esw_cfg, count);
- if (ret)
- return ret;
-
- for (i = 0; i < count; i++) {
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
- if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
- continue;
-
- op_mode = esw_cfg[i].op_mode;
- qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
- esw_cfg[i].op_mode = op_mode;
- esw_cfg[i].pci_func = adapter->ahw->pci_func;
-
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
- break;
- case QLCNIC_ADD_VLAN:
- qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
- break;
- case QLCNIC_DEL_VLAN:
- esw_cfg[i].vlan_id = 0;
- qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
- break;
- }
- }
-
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- goto out;
-
- for (i = 0; i < count; i++) {
- pci_func = esw_cfg[i].pci_func;
- npar = &adapter->npars[pci_func];
- switch (esw_cfg[i].op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- npar->promisc_mode = esw_cfg[i].promisc_mode;
- npar->mac_override = esw_cfg[i].mac_override;
- npar->offload_flags = esw_cfg[i].offload_flags;
- npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
- npar->discard_tagged = esw_cfg[i].discard_tagged;
- break;
- case QLCNIC_ADD_VLAN:
- npar->pvid = esw_cfg[i].vlan_id;
- break;
- case QLCNIC_DEL_VLAN:
- npar->pvid = 0;
- break;
- }
- }
-out:
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
- u8 i;
-
- if (size != sizeof(esw_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- esw_cfg[i].pci_func = i;
- if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
- return QL_STATUS_INVALID_PARAM;
- }
- memcpy(buf, &esw_cfg, size);
-
- return size;
-}
-
-static int
-validate_npar_config(struct qlcnic_adapter *adapter,
- struct qlcnic_npar_func_cfg *np_cfg, int count)
-{
- u8 pci_func, i;
-
- for (i = 0; i < count; i++) {
- pci_func = np_cfg[i].pci_func;
- if (pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
-
- if (!IS_VALID_BW(np_cfg[i].min_bw) ||
- !IS_VALID_BW(np_cfg[i].max_bw))
- return QL_STATUS_INVALID_PARAM;
- }
- return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_info nic_info;
- struct qlcnic_npar_func_cfg *np_cfg;
- int i, count, rem, ret;
- u8 pci_func;
-
- count = size / sizeof(struct qlcnic_npar_func_cfg);
- rem = size % sizeof(struct qlcnic_npar_func_cfg);
- if (rem)
- return QL_STATUS_INVALID_PARAM;
-
- np_cfg = (struct qlcnic_npar_func_cfg *) buf;
- ret = validate_npar_config(adapter, np_cfg, count);
- if (ret)
- return ret;
-
- for (i = 0; i < count ; i++) {
- pci_func = np_cfg[i].pci_func;
- ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
- if (ret)
- return ret;
- nic_info.pci_func = pci_func;
- nic_info.min_tx_bw = np_cfg[i].min_bw;
- nic_info.max_tx_bw = np_cfg[i].max_bw;
- ret = qlcnic_set_nic_info(adapter, &nic_info);
- if (ret)
- return ret;
- adapter->npars[i].min_bw = nic_info.min_tx_bw;
- adapter->npars[i].max_bw = nic_info.max_tx_bw;
- }
-
- return size;
-
-}
-static ssize_t
-qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_info nic_info;
- struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
- int i, ret;
-
- if (size != sizeof(np_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- ret = qlcnic_get_nic_info(adapter, &nic_info, i);
- if (ret)
- return ret;
-
- np_cfg[i].pci_func = i;
- np_cfg[i].op_mode = (u8)nic_info.op_mode;
- np_cfg[i].port_num = nic_info.phys_port;
- np_cfg[i].fw_capab = nic_info.capabilities;
- np_cfg[i].min_bw = nic_info.min_tx_bw ;
- np_cfg[i].max_bw = nic_info.max_tx_bw;
- np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
- np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
- }
- memcpy(buf, &np_cfg, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_statistics port_stats;
- int ret;
-
- if (size != sizeof(struct qlcnic_esw_statistics))
- return QL_STATUS_INVALID_PARAM;
-
- if (offset >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- memset(&port_stats, 0, size);
- ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
- &port_stats.rx);
- if (ret)
- return ret;
-
- ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
- &port_stats.tx);
- if (ret)
- return ret;
-
- memcpy(buf, &port_stats, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_esw_statistics esw_stats;
- int ret;
-
- if (size != sizeof(struct qlcnic_esw_statistics))
- return QL_STATUS_INVALID_PARAM;
-
- if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
- return QL_STATUS_INVALID_PARAM;
-
- memset(&esw_stats, 0, size);
- ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
- &esw_stats.rx);
- if (ret)
- return ret;
-
- ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
- &esw_stats.tx);
- if (ret)
- return ret;
-
- memcpy(buf, &esw_stats, size);
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
- return QL_STATUS_INVALID_PARAM;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
- QLCNIC_QUERY_RX_COUNTER);
- if (ret)
- return ret;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
- QLCNIC_QUERY_TX_COUNTER);
- if (ret)
- return ret;
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- int ret;
-
- if (offset >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
- QLCNIC_QUERY_RX_COUNTER);
- if (ret)
- return ret;
-
- ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
- QLCNIC_QUERY_TX_COUNTER);
- if (ret)
- return ret;
-
- return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
- struct qlcnic_pci_info *pci_info;
- int i, ret;
-
- if (size != sizeof(pci_cfg))
- return QL_STATUS_INVALID_PARAM;
-
- pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
- if (!pci_info)
- return -ENOMEM;
-
- ret = qlcnic_get_pci_info(adapter, pci_info);
- if (ret) {
- kfree(pci_info);
- return ret;
- }
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
- pci_cfg[i].pci_func = pci_info[i].id;
- pci_cfg[i].func_type = pci_info[i].type;
- pci_cfg[i].port_num = pci_info[i].default_port;
- pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
- pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
- memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
- }
- memcpy(buf, &pci_cfg, size);
- kfree(pci_info);
- return size;
-}
-static struct bin_attribute bin_attr_npar_config = {
- .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_npar_config,
- .write = qlcnic_sysfs_write_npar_config,
-};
-
-static struct bin_attribute bin_attr_pci_config = {
- .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_pci_config,
- .write = NULL,
-};
-
-static struct bin_attribute bin_attr_port_stats = {
- .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_get_port_stats,
- .write = qlcnic_sysfs_clear_port_stats,
-};
-
-static struct bin_attribute bin_attr_esw_stats = {
- .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_get_esw_stats,
- .write = qlcnic_sysfs_clear_esw_stats,
-};
-
-static struct bin_attribute bin_attr_esw_config = {
- .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_esw_config,
- .write = qlcnic_sysfs_write_esw_config,
-};
-
-static struct bin_attribute bin_attr_pm_config = {
- .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
- .size = 0,
- .read = qlcnic_sysfs_read_pm_config,
- .write = qlcnic_sysfs_write_pm_config,
-};
-
-static void
-qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- if (device_create_file(dev, &dev_attr_bridged_mode))
- dev_warn(dev,
- "failed to create bridged_mode sysfs entry\n");
-}
-
-static void
-qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
-
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
- device_remove_file(dev, &dev_attr_bridged_mode);
-}
-
-static void
-qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
- u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
- if (device_create_bin_file(dev, &bin_attr_port_stats))
- dev_info(dev, "failed to create port stats sysfs entry");
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return;
- if (device_create_file(dev, &dev_attr_diag_mode))
- dev_info(dev, "failed to create diag_mode sysfs entry\n");
- if (device_create_bin_file(dev, &bin_attr_crb))
- dev_info(dev, "failed to create crb sysfs entry\n");
- if (device_create_bin_file(dev, &bin_attr_mem))
- dev_info(dev, "failed to create mem sysfs entry\n");
-
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
- return;
-
- if (device_create_bin_file(dev, &bin_attr_pci_config))
- dev_info(dev, "failed to create pci config sysfs entry");
- if (device_create_file(dev, &dev_attr_beacon))
- dev_info(dev, "failed to create beacon sysfs entry");
-
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
- if (device_create_bin_file(dev, &bin_attr_esw_config))
- dev_info(dev, "failed to create esw config sysfs entry");
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return;
- if (device_create_bin_file(dev, &bin_attr_npar_config))
- dev_info(dev, "failed to create npar config sysfs entry");
- if (device_create_bin_file(dev, &bin_attr_pm_config))
- dev_info(dev, "failed to create pm config sysfs entry");
- if (device_create_bin_file(dev, &bin_attr_esw_stats))
- dev_info(dev, "failed to create eswitch stats sysfs entry");
-}
-
-static void
-qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
-{
- struct device *dev = &adapter->pdev->dev;
- u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
- device_remove_bin_file(dev, &bin_attr_port_stats);
-
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return;
- device_remove_file(dev, &dev_attr_diag_mode);
- device_remove_bin_file(dev, &bin_attr_crb);
- device_remove_bin_file(dev, &bin_attr_mem);
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
- return;
- device_remove_bin_file(dev, &bin_attr_pci_config);
- device_remove_file(dev, &dev_attr_beacon);
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
- device_remove_bin_file(dev, &bin_attr_esw_config);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return;
- device_remove_bin_file(dev, &bin_attr_npar_config);
- device_remove_bin_file(dev, &bin_attr_pm_config);
- device_remove_bin_file(dev, &bin_attr_esw_stats);
-}
-
#ifdef CONFIG_INET
#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
new file mode 100644
index 0000000..4555016
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -0,0 +1,896 @@
+#include <linux/sysfs.h>
+#include "qlcnic.h"
+
+static ssize_t
+qlcnic_store_bridged_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ unsigned long new;
+ int ret = -EINVAL;
+
+ if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
+ goto err_out;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ goto err_out;
+
+ if (kstrtoul(buf, 2, &new))
+ goto err_out;
+
+ if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
+ ret = len;
+
+err_out:
+ return ret;
+}
+
+static ssize_t
+qlcnic_show_bridged_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int bridged_mode = 0;
+
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
+
+ return sprintf(buf, "%d\n", bridged_mode);
+}
+
+static struct device_attribute dev_attr_bridged_mode = {
+ .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_bridged_mode,
+ .store = qlcnic_store_bridged_mode,
+};
+
+static ssize_t
+qlcnic_store_diag_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ unsigned long new;
+
+ if (kstrtoul(buf, 2, &new))
+ return -EINVAL;
+
+ if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ adapter->flags ^= QLCNIC_DIAG_ENABLED;
+
+ return len;
+}
+
+static ssize_t
+qlcnic_show_diag_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n",
+ !!(adapter->flags & QLCNIC_DIAG_ENABLED));
+}
+
+static struct device_attribute dev_attr_diag_mode = {
+ .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_diag_mode,
+ .store = qlcnic_store_diag_mode,
+};
+
+static int
+qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
+ u8 *rate)
+{
+ *rate = LSB(beacon);
+ *state = MSB(beacon);
+
+ QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
+
+ if (!*state) {
+ *rate = __QLCNIC_MAX_LED_RATE;
+ return 0;
+ } else if (*state > __QLCNIC_MAX_LED_STATE)
+ return -EINVAL;
+
+ if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t
+qlcnic_store_beacon(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int max_sds_rings = adapter->max_sds_rings;
+ int dev_down = 0;
+ u16 beacon;
+ u8 b_state, b_rate;
+ int err;
+
+ if (len != sizeof(u16))
+ return QL_STATUS_INVALID_PARAM;
+
+ memcpy(&beacon, buf, sizeof(u16));
+ err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
+ if (err)
+ return err;
+
+ if (adapter->ahw->beacon_state == b_state)
+ return len;
+
+ if (!adapter->ahw->beacon_state)
+ if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
+ return -EBUSY;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EIO;
+ err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
+ if (err) {
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+ return err;
+ }
+ dev_down = 1;
+ }
+
+ err = qlcnic_config_led(adapter, b_state, b_rate);
+
+ if (!err) {
+ adapter->ahw->beacon_state = b_state;
+ err = len;
+ }
+
+ if (dev_down) {
+ qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ }
+
+ if (!b_state)
+ clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+
+ return err;
+}
+
+static ssize_t
+qlcnic_show_beacon(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
+}
+
+static struct device_attribute dev_attr_beacon = {
+ .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
+ .show = qlcnic_show_beacon,
+ .store = qlcnic_store_beacon,
+};
+
+static int
+qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
+ loff_t offset, size_t size)
+{
+ size_t crb_size = 4;
+
+ if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ return -EIO;
+
+ if (offset < QLCNIC_PCI_CRBSPACE) {
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
+ QLCNIC_PCI_CAMQM_END))
+ crb_size = 8;
+ else
+ return -EINVAL;
+ }
+
+ if ((size != crb_size) || (offset & (crb_size-1)))
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t
+qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ adapter->ahw->hw_ops->read_crb(adapter, buf, offset, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size);
+ return size;
+}
+
+static int
+qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
+ loff_t offset, size_t size)
+{
+ if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ return -EIO;
+
+ if ((size != 8) || (offset & 0x7))
+ return -EIO;
+
+ return 0;
+}
+
+static ssize_t
+qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u64 data;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
+ return -EIO;
+
+ memcpy(buf, &data, size);
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ u64 data;
+ int ret;
+
+ ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ memcpy(&data, buf, size);
+
+ if (qlcnic_pci_mem_write_2M(adapter, offset, data))
+ return -EIO;
+
+ return size;
+}
+
+static struct bin_attribute bin_attr_crb = {
+ .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_crb,
+ .write = qlcnic_sysfs_write_crb,
+};
+
+static struct bin_attribute bin_attr_mem = {
+ .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_mem,
+ .write = qlcnic_sysfs_write_mem,
+};
+
+static int
+validate_pm_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_pm_func_cfg *pm_cfg, int count)
+{
+
+ u8 src_pci_func, s_esw_id, d_esw_id;
+ u8 dest_pci_func;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ src_pci_func = pm_cfg[i].pci_func;
+ dest_pci_func = pm_cfg[i].dest_npar;
+ if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
+ || dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ s_esw_id = adapter->npars[src_pci_func].phy_port;
+ d_esw_id = adapter->npars[dest_pci_func].phy_port;
+
+ if (s_esw_id != d_esw_id)
+ return QL_STATUS_INVALID_PARAM;
+
+ }
+ return 0;
+
+}
+
+static ssize_t
+qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pm_func_cfg *pm_cfg;
+ u32 id, action, pci_func;
+ int count, rem, i, ret;
+
+ count = size / sizeof(struct qlcnic_pm_func_cfg);
+ rem = size % sizeof(struct qlcnic_pm_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ pm_cfg = (struct qlcnic_pm_func_cfg *) buf;
+
+ ret = validate_pm_config(adapter, pm_cfg, count);
+ if (ret)
+ return ret;
+ for (i = 0; i < count; i++) {
+ pci_func = pm_cfg[i].pci_func;
+ action = !!pm_cfg[i].action;
+ id = adapter->npars[pci_func].phy_port;
+ ret = qlcnic_config_port_mirroring(adapter, id,
+ action, pci_func);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < count; i++) {
+ pci_func = pm_cfg[i].pci_func;
+ id = adapter->npars[pci_func].phy_port;
+ adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
+ adapter->npars[pci_func].dest_npar = id;
+ }
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
+ int i;
+
+ if (size != sizeof(pm_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ pm_cfg[i].action = adapter->npars[i].enable_pm;
+ pm_cfg[i].dest_npar = 0;
+ pm_cfg[i].pci_func = i;
+ }
+ memcpy(buf, &pm_cfg, size);
+
+ return size;
+}
+
+static int
+validate_esw_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg, int count)
+{
+ u32 op_mode;
+ u8 pci_func;
+ int i;
+
+ op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+
+ for (i = 0; i < count; i++) {
+ pci_func = esw_cfg[i].pci_func;
+ if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+ QLCNIC_NON_PRIV_FUNC) {
+ if (esw_cfg[i].mac_anti_spoof != 0)
+ return QL_STATUS_INVALID_PARAM;
+ if (esw_cfg[i].mac_override != 1)
+ return QL_STATUS_INVALID_PARAM;
+ if (esw_cfg[i].promisc_mode != 1)
+ return QL_STATUS_INVALID_PARAM;
+ }
+ break;
+ case QLCNIC_ADD_VLAN:
+ if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+ return QL_STATUS_INVALID_PARAM;
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ case QLCNIC_DEL_VLAN:
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ default:
+ return QL_STATUS_INVALID_PARAM;
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_func_cfg *esw_cfg;
+ struct qlcnic_npar_info *npar;
+ int count, rem, i, ret;
+ u8 pci_func, op_mode = 0;
+
+ count = size / sizeof(struct qlcnic_esw_func_cfg);
+ rem = size % sizeof(struct qlcnic_esw_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ esw_cfg = (struct qlcnic_esw_func_cfg *) buf;
+ ret = validate_esw_config(adapter, esw_cfg, count);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < count; i++) {
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
+ continue;
+
+ op_mode = esw_cfg[i].op_mode;
+ qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+ esw_cfg[i].op_mode = op_mode;
+ esw_cfg[i].pci_func = adapter->ahw->pci_func;
+
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_ADD_VLAN:
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_DEL_VLAN:
+ esw_cfg[i].vlan_id = 0;
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ }
+ }
+
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ goto out;
+
+ for (i = 0; i < count; i++) {
+ pci_func = esw_cfg[i].pci_func;
+ npar = &adapter->npars[pci_func];
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ npar->promisc_mode = esw_cfg[i].promisc_mode;
+ npar->mac_override = esw_cfg[i].mac_override;
+ npar->offload_flags = esw_cfg[i].offload_flags;
+ npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+ npar->discard_tagged = esw_cfg[i].discard_tagged;
+ break;
+ case QLCNIC_ADD_VLAN:
+ npar->pvid = esw_cfg[i].vlan_id;
+ break;
+ case QLCNIC_DEL_VLAN:
+ npar->pvid = 0;
+ break;
+ }
+ }
+out:
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
+ u8 i;
+
+ if (size != sizeof(esw_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ esw_cfg[i].pci_func = i;
+ if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
+ }
+ memcpy(buf, &esw_cfg, size);
+
+ return size;
+}
+
+static int
+validate_npar_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_npar_func_cfg *np_cfg, int count)
+{
+ u8 pci_func, i;
+
+ for (i = 0; i < count; i++) {
+ pci_func = np_cfg[i].pci_func;
+ if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
+
+ if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+ !IS_VALID_BW(np_cfg[i].max_bw))
+ return QL_STATUS_INVALID_PARAM;
+ }
+ return 0;
+}
+
+static ssize_t
+qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_info nic_info;
+ struct qlcnic_npar_func_cfg *np_cfg;
+ int i, count, rem, ret;
+ u8 pci_func;
+
+ count = size / sizeof(struct qlcnic_npar_func_cfg);
+ rem = size % sizeof(struct qlcnic_npar_func_cfg);
+ if (rem)
+ return QL_STATUS_INVALID_PARAM;
+
+ np_cfg = (struct qlcnic_npar_func_cfg *) buf;
+ ret = validate_npar_config(adapter, np_cfg, count);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < count ; i++) {
+ pci_func = np_cfg[i].pci_func;
+ ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+ if (ret)
+ return ret;
+ nic_info.pci_func = pci_func;
+ nic_info.min_tx_bw = np_cfg[i].min_bw;
+ nic_info.max_tx_bw = np_cfg[i].max_bw;
+ ret = qlcnic_set_nic_info(adapter, &nic_info);
+ if (ret)
+ return ret;
+ adapter->npars[i].min_bw = nic_info.min_tx_bw;
+ adapter->npars[i].max_bw = nic_info.max_tx_bw;
+ }
+
+ return size;
+
+}
+static ssize_t
+qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_info nic_info;
+ struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
+ int i, ret;
+
+ if (size != sizeof(np_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ ret = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (ret)
+ return ret;
+
+ np_cfg[i].pci_func = i;
+ np_cfg[i].op_mode = (u8)nic_info.op_mode;
+ np_cfg[i].port_num = nic_info.phys_port;
+ np_cfg[i].fw_capab = nic_info.capabilities;
+ np_cfg[i].min_bw = nic_info.min_tx_bw ;
+ np_cfg[i].max_bw = nic_info.max_tx_bw;
+ np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
+ np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+ }
+ memcpy(buf, &np_cfg, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics port_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&port_stats, 0, size);
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &port_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &port_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &port_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics esw_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&esw_stats, 0, size);
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &esw_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &esw_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &esw_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
+ struct qlcnic_pci_info *pci_info;
+ int i, ret;
+
+ if (size != sizeof(pci_cfg))
+ return QL_STATUS_INVALID_PARAM;
+
+ pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+ if (!pci_info)
+ return -ENOMEM;
+
+ ret = qlcnic_get_pci_info(adapter, pci_info);
+ if (ret) {
+ kfree(pci_info);
+ return ret;
+ }
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
+ pci_cfg[i].pci_func = pci_info[i].id;
+ pci_cfg[i].func_type = pci_info[i].type;
+ pci_cfg[i].port_num = pci_info[i].default_port;
+ pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
+ pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
+ memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
+ }
+ memcpy(buf, &pci_cfg, size);
+ kfree(pci_info);
+ return size;
+}
+static struct bin_attribute bin_attr_npar_config = {
+ .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_npar_config,
+ .write = qlcnic_sysfs_write_npar_config,
+};
+
+static struct bin_attribute bin_attr_pci_config = {
+ .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_pci_config,
+ .write = NULL,
+};
+
+static struct bin_attribute bin_attr_port_stats = {
+ .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_port_stats,
+ .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+ .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_esw_stats,
+ .write = qlcnic_sysfs_clear_esw_stats,
+};
+
+static struct bin_attribute bin_attr_esw_config = {
+ .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_esw_config,
+ .write = qlcnic_sysfs_write_esw_config,
+};
+
+static struct bin_attribute bin_attr_pm_config = {
+ .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_pm_config,
+ .write = qlcnic_sysfs_write_pm_config,
+};
+
+void
+qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ if (device_create_file(dev, &dev_attr_bridged_mode))
+ dev_warn(dev,
+ "failed to create bridged_mode sysfs entry\n");
+}
+
+void
+qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ device_remove_file(dev, &dev_attr_bridged_mode);
+}
+
+void
+qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ if (device_create_bin_file(dev, &bin_attr_port_stats))
+ dev_info(dev, "failed to create port stats sysfs entry");
+
+ if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
+ if (device_create_file(dev, &dev_attr_diag_mode))
+ dev_info(dev, "failed to create diag_mode sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_beacon))
+ dev_info(dev, "failed to create beacon sysfs entry");
+ if (device_create_bin_file(dev, &bin_attr_crb))
+ dev_info(dev, "failed to create crb sysfs entry\n");
+ if (device_create_bin_file(dev, &bin_attr_mem))
+ dev_info(dev, "failed to create mem sysfs entry\n");
+ if (device_create_bin_file(dev, &bin_attr_pci_config))
+ dev_info(dev, "failed to create pci config sysfs entry");
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ if (device_create_bin_file(dev, &bin_attr_esw_config))
+ dev_info(dev, "failed to create esw config sysfs entry");
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return;
+ if (device_create_bin_file(dev, &bin_attr_npar_config))
+ dev_info(dev, "failed to create npar config sysfs entry");
+ if (device_create_bin_file(dev, &bin_attr_pm_config))
+ dev_info(dev, "failed to create pm config sysfs entry");
+ if (device_create_bin_file(dev, &bin_attr_esw_stats))
+ dev_info(dev, "failed to create eswitch stats sysfs entry");
+}
+
+void
+qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+
+ device_remove_bin_file(dev, &bin_attr_port_stats);
+
+ if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
+ device_remove_file(dev, &dev_attr_diag_mode);
+ device_remove_file(dev, &dev_attr_beacon);
+ device_remove_bin_file(dev, &bin_attr_crb);
+ device_remove_bin_file(dev, &bin_attr_mem);
+ device_remove_bin_file(dev, &bin_attr_pci_config);
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ device_remove_bin_file(dev, &bin_attr_esw_config);
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return;
+ device_remove_bin_file(dev, &bin_attr_npar_config);
+ device_remove_bin_file(dev, &bin_attr_pm_config);
+ device_remove_bin_file(dev, &bin_attr_esw_stats);
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 05/15] qlcnic: remove 82xx specific register dump utility
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Remove 82xx specific register dump utility
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 466 ----------------------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 -
2 files changed, 0 insertions(+), 467 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 7e943db..3ec03e1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1330,472 +1330,6 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return rv;
}
-/* FW dump related functions */
-static u32
-qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i;
- u32 addr, data;
- struct __crb *crb = &entry->region.crb;
- void __iomem *base = adapter->ahw->pci_base0;
-
- addr = crb->addr;
-
- for (i = 0; i < crb->no_ops; i++) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(addr);
- *buffer++ = cpu_to_le32(data);
- addr += crb->stride;
- }
- return crb->no_ops * 2 * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i, k, timeout = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- u32 addr, data;
- u8 opcode, no_ops;
- struct __ctrl *ctr = &entry->region.ctrl;
- struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
-
- addr = ctr->addr;
- no_ops = ctr->no_ops;
-
- for (i = 0; i < no_ops; i++) {
- k = 0;
- opcode = 0;
- for (k = 0; k < 8; k++) {
- if (!(ctr->opcode & (1 << k)))
- continue;
- switch (1 << k) {
- case QLCNIC_DUMP_WCRB:
- QLCNIC_WR_DUMP_REG(addr, base, ctr->val1);
- break;
- case QLCNIC_DUMP_RWCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base, data);
- break;
- case QLCNIC_DUMP_ANDCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base,
- (data & ctr->val2));
- break;
- case QLCNIC_DUMP_ORCRB:
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- QLCNIC_WR_DUMP_REG(addr, base,
- (data | ctr->val3));
- break;
- case QLCNIC_DUMP_POLLCRB:
- while (timeout <= ctr->timeout) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- if ((data & ctr->val2) == ctr->val1)
- break;
- msleep(1);
- timeout++;
- }
- if (timeout > ctr->timeout) {
- dev_info(&adapter->pdev->dev,
- "Timed out, aborting poll CRB\n");
- return -EINVAL;
- }
- break;
- case QLCNIC_DUMP_RD_SAVE:
- if (ctr->index_a)
- addr = t_hdr->saved_state[ctr->index_a];
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- t_hdr->saved_state[ctr->index_v] = data;
- break;
- case QLCNIC_DUMP_WRT_SAVED:
- if (ctr->index_v)
- data = t_hdr->saved_state[ctr->index_v];
- else
- data = ctr->val1;
- if (ctr->index_a)
- addr = t_hdr->saved_state[ctr->index_a];
- QLCNIC_WR_DUMP_REG(addr, base, data);
- break;
- case QLCNIC_DUMP_MOD_SAVE_ST:
- data = t_hdr->saved_state[ctr->index_v];
- data <<= ctr->shl_val;
- data >>= ctr->shr_val;
- if (ctr->val2)
- data &= ctr->val2;
- data |= ctr->val3;
- data += ctr->val1;
- t_hdr->saved_state[ctr->index_v] = data;
- break;
- default:
- dev_info(&adapter->pdev->dev,
- "Unknown opcode\n");
- break;
- }
- }
- addr += ctr->stride;
- }
- return 0;
-}
-
-static u32
-qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int loop;
- u32 val, data = 0;
- struct __mux *mux = &entry->region.mux;
- void __iomem *base = adapter->ahw->pci_base0;
-
- val = mux->val;
- for (loop = 0; loop < mux->no_ops; loop++) {
- QLCNIC_WR_DUMP_REG(mux->addr, base, val);
- QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data);
- *buffer++ = cpu_to_le32(val);
- *buffer++ = cpu_to_le32(data);
- val += mux->val_stride;
- }
- return 2 * mux->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i, loop;
- u32 cnt, addr, data, que_id = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __queue *que = &entry->region.que;
-
- addr = que->read_addr;
- cnt = que->read_addr_cnt;
-
- for (loop = 0; loop < que->no_ops; loop++) {
- QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id);
- addr = que->read_addr;
- for (i = 0; i < cnt; i++) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += que->read_addr_stride;
- }
- que_id += que->stride;
- }
- return que->no_ops * cnt * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i;
- u32 data;
- void __iomem *addr;
- struct __ocm *ocm = &entry->region.ocm;
-
- addr = adapter->ahw->pci_base0 + ocm->read_addr;
- for (i = 0; i < ocm->no_ops; i++) {
- data = readl(addr);
- *buffer++ = cpu_to_le32(data);
- addr += ocm->read_addr_stride;
- }
- return ocm->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
- u32 *buffer)
-{
- int i, count = 0;
- u32 fl_addr, size, val, lck_val, addr;
- struct __mem *rom = &entry->region.mem;
- void __iomem *base = adapter->ahw->pci_base0;
-
- fl_addr = rom->addr;
- size = rom->size/4;
-lock_try:
- lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
- if (!lck_val && count < MAX_CTL_CHECK) {
- msleep(10);
- count++;
- goto lock_try;
- }
- writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
- for (i = 0; i < size; i++) {
- addr = fl_addr & 0xFFFF0000;
- QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr);
- addr = LSW(fl_addr) + FLASH_ROM_DATA;
- QLCNIC_RD_DUMP_REG(addr, base, &val);
- fl_addr += 4;
- *buffer++ = cpu_to_le32(val);
- }
- readl(base + QLCNIC_FLASH_SEM2_ULK);
- return rom->size;
-}
-
-static u32
-qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i;
- u32 cnt, val, data, addr;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __cache *l1 = &entry->region.cache;
-
- val = l1->init_tag_val;
-
- for (i = 0; i < l1->no_ops; i++) {
- QLCNIC_WR_DUMP_REG(l1->addr, base, val);
- QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val));
- addr = l1->read_addr;
- cnt = l1->read_addr_num;
- while (cnt) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += l1->read_addr_stride;
- cnt--;
- }
- val += l1->stride;
- }
- return l1->no_ops * l1->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- int i;
- u32 cnt, val, data, addr;
- u8 poll_mask, poll_to, time_out = 0;
- void __iomem *base = adapter->ahw->pci_base0;
- struct __cache *l2 = &entry->region.cache;
-
- val = l2->init_tag_val;
- poll_mask = LSB(MSW(l2->ctrl_val));
- poll_to = MSB(MSW(l2->ctrl_val));
-
- for (i = 0; i < l2->no_ops; i++) {
- QLCNIC_WR_DUMP_REG(l2->addr, base, val);
- if (LSW(l2->ctrl_val))
- QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
- LSW(l2->ctrl_val));
- if (!poll_mask)
- goto skip_poll;
- do {
- QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
- if (!(data & poll_mask))
- break;
- msleep(1);
- time_out++;
- } while (time_out <= poll_to);
-
- if (time_out > poll_to) {
- dev_err(&adapter->pdev->dev,
- "Timeout exceeded in %s, aborting dump\n",
- __func__);
- return -EINVAL;
- }
-skip_poll:
- addr = l2->read_addr;
- cnt = l2->read_addr_num;
- while (cnt) {
- QLCNIC_RD_DUMP_REG(addr, base, &data);
- *buffer++ = cpu_to_le32(data);
- addr += l2->read_addr_stride;
- cnt--;
- }
- val += l2->stride;
- }
- return l2->no_ops * l2->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_read_memory(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- u32 addr, data, test, ret = 0;
- int i, reg_read;
- struct __mem *mem = &entry->region.mem;
- void __iomem *base = adapter->ahw->pci_base0;
-
- reg_read = mem->size;
- addr = mem->addr;
- /* check for data size of multiple of 16 and 16 byte alignment */
- if ((addr & 0xf) || (reg_read%16)) {
- dev_info(&adapter->pdev->dev,
- "Unaligned memory addr:0x%x size:0x%x\n",
- addr, reg_read);
- return -EINVAL;
- }
-
- mutex_lock(&adapter->ahw->mem_lock);
-
- while (reg_read != 0) {
- QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr);
- QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0);
- QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base,
- TA_CTL_ENABLE | TA_CTL_START);
-
- for (i = 0; i < MAX_CTL_CHECK; i++) {
- QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test);
- if (!(test & TA_CTL_BUSY))
- break;
- }
- if (i == MAX_CTL_CHECK) {
- if (printk_ratelimit()) {
- dev_err(&adapter->pdev->dev,
- "failed to read through agent\n");
- ret = -EINVAL;
- goto out;
- }
- }
- for (i = 0; i < 4; i++) {
- QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data);
- *buffer++ = cpu_to_le32(data);
- }
- addr += 16;
- reg_read -= 16;
- ret += 16;
- }
-out:
- mutex_unlock(&adapter->ahw->mem_lock);
- return mem->size;
-}
-
-static u32
-qlcnic_dump_nop(struct qlcnic_adapter *adapter,
- struct qlcnic_dump_entry *entry, u32 *buffer)
-{
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- return 0;
-}
-
-struct qlcnic_dump_operations fw_dump_ops[] = {
- { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
- { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
- { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
- { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
- { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
- { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
- { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
- { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
- { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
- { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
- { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
- { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
- { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
- { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
-};
-
-/* Walk the template and collect dump for each entry in the dump template */
-static int
-qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
- u32 size)
-{
- int ret = 1;
- if (size != entry->hdr.cap_size) {
- dev_info(dev,
- "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
- entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
- dev_info(dev, "Aborting further dump capture\n");
- ret = 0;
- }
- return ret;
-}
-
-int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
-{
- u32 *buffer;
- char mesg[64];
- char *msg[] = {mesg, NULL};
- int i, k, ops_cnt, ops_index, dump_size = 0;
- u32 entry_offset, dump, no_entries, buf_offset = 0;
- struct qlcnic_dump_entry *entry;
- struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
- struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
-
- if (fw_dump->clr) {
- dev_info(&adapter->pdev->dev,
- "Previous dump not cleared, not capturing dump\n");
- return -EIO;
- }
- /* Calculate the size for dump data area only */
- for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
- if (i & tmpl_hdr->drv_cap_mask)
- dump_size += tmpl_hdr->cap_sizes[k];
- if (!dump_size)
- return -EIO;
-
- fw_dump->data = vzalloc(dump_size);
- if (!fw_dump->data) {
- dev_info(&adapter->pdev->dev,
- "Unable to allocate (%d KB) for fw dump\n",
- dump_size/1024);
- return -ENOMEM;
- }
- buffer = fw_dump->data;
- fw_dump->size = dump_size;
- no_entries = tmpl_hdr->num_entries;
- ops_cnt = ARRAY_SIZE(fw_dump_ops);
- entry_offset = tmpl_hdr->offset;
- tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
- tmpl_hdr->sys_info[1] = adapter->fw_version;
-
- for (i = 0; i < no_entries; i++) {
- entry = (void *)tmpl_hdr + entry_offset;
- if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- entry_offset += entry->hdr.offset;
- continue;
- }
- /* Find the handler for this entry */
- ops_index = 0;
- while (ops_index < ops_cnt) {
- if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
- break;
- ops_index++;
- }
- if (ops_index == ops_cnt) {
- dev_info(&adapter->pdev->dev,
- "Invalid entry type %d, exiting dump\n",
- entry->hdr.type);
- goto error;
- }
- /* Collect dump for this entry */
- dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
- if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
- dump))
- entry->hdr.flags |= QLCNIC_DUMP_SKIP;
- buf_offset += entry->hdr.cap_size;
- entry_offset += entry->hdr.offset;
- buffer = fw_dump->data + buf_offset;
- }
- if (dump_size != buf_offset) {
- dev_info(&adapter->pdev->dev,
- "Captured(%d) and expected size(%d) do not match\n",
- buf_offset, dump_size);
- goto error;
- } else {
- fw_dump->clr = 1;
- snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
- adapter->netdev->name);
- dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
- fw_dump->size);
- /* Send a udev event to notify availability of FW dump */
- kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
- return 0;
- }
-error:
- vfree(fw_dump->data);
- return -EINVAL;
-}
-
void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
{
void __iomem *msix_base_addr;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 0cf9991..56c03f5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2303,7 +2303,6 @@ skip_ack_check:
if (ahw->fw_dump.enable &&
(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
QLCDB(adapter, DRV, "Take FW dump\n");
- qlcnic_dump_fw(adapter);
adapter->flags |= QLCNIC_FW_HANG;
}
rtnl_unlock();
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 04/15] qlcnic: Refactoring - Moving hw specific data to hardware context
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Anirban Chakraborty
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Group all the HW data in a seperate data structure
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 62 ++++++-------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 25 +++---
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 69 +++++++-------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 3 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 29 +++---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 20 ++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 94 ++++++++++----------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 22 +++---
9 files changed, 164 insertions(+), 162 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 7f1a3e1..86e6a80 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -35,9 +35,9 @@
#include "qlcnic_hdr.h"
#define _QLCNIC_LINUX_MAJOR 5
-#define _QLCNIC_LINUX_MINOR 0
+#define _QLCNIC_LINUX_MINOR 1
#define _QLCNIC_LINUX_SUBVERSION 29
-#define QLCNIC_LINUX_VERSIONID "5.0.29"
+#define QLCNIC_LINUX_VERSIONID "5.1.29"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -458,11 +458,36 @@ struct qlcnic_hardware_context {
u8 pci_func;
u8 linkup;
u8 loopback_state;
+ u8 beacon_state;
+ u8 has_link_events;
+ u8 fw_type;
+ u8 physical_port;
+ u8 reset_context;
+ u8 msix_supported;
+ u8 max_mac_filters;
+ u8 mc_enabled;
+ u8 max_mc_count;
+ u8 diag_test;
+ char diag_cnt;
+
u16 port_type;
u16 board_type;
- u8 beacon_state;
+ u16 link_speed;
+ u16 link_duplex;
+ u16 link_autoneg;
+ u16 module_type;
+ u16 op_mode;
+ u16 switch_mode;
+ u16 max_tx_ques;
+ u16 max_rx_ques;
+ u16 max_mtu;
+ u16 msg_enable;
+
+ u32 capabilities;
+ u32 temp;
+ u32 int_vec_bit;
u32 fw_hal_version;
struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
@@ -525,6 +550,7 @@ struct qlcnic_host_sds_ring {
} ____cacheline_internodealigned_in_smp;
struct qlcnic_host_tx_ring {
+ u16 ctx_id;
u32 producer;
u32 sw_consumer;
u32 num_desc;
@@ -996,49 +1022,22 @@ struct qlcnic_adapter {
u8 max_rds_rings;
u8 max_sds_rings;
- u8 msix_supported;
u8 portnum;
- u8 physical_port;
- u8 reset_context;
- u8 mc_enabled;
- u8 max_mc_count;
u8 fw_wait_cnt;
u8 fw_fail_cnt;
u8 tx_timeo_cnt;
u8 need_fw_reset;
- u8 has_link_events;
- u8 fw_type;
- u16 tx_context_id;
u16 is_up;
-
- u16 link_speed;
- u16 link_duplex;
- u16 link_autoneg;
- u16 module_type;
-
- u16 op_mode;
- u16 switch_mode;
- u16 max_tx_ques;
- u16 max_rx_ques;
- u16 max_mtu;
u16 pvid;
- u32 capabilities;
u32 irq;
- u32 temp;
-
- u32 int_vec_bit;
u32 heartbeat;
- u8 max_mac_filters;
u8 dev_state;
- u8 diag_test;
- char diag_cnt;
u8 reset_ack_timeo;
u8 dev_init_timeo;
- u16 msg_enable;
u8 mac_addr[ETH_ALEN];
@@ -1062,7 +1061,6 @@ struct qlcnic_adapter {
struct delayed_work fw_work;
-
struct qlcnic_filter_hash fhash;
spinlock_t tx_clean_lock;
@@ -1658,7 +1656,7 @@ struct qlcnic_hardware_ops {
};
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
- if (NETIF_MSG_##lvl & adapter->msg_enable) \
+ if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
printk(KERN_INFO "%s: %s: " _fmt, \
dev_name(&adapter->pdev->dev), \
__func__, ##_args); \
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index c9be09b..c79bc9a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -452,8 +452,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
- adapter->tx_context_id =
- le16_to_cpu(prsp->context_id);
+ tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
} else {
dev_err(&adapter->pdev->dev,
"Failed to create tx ctx in firmware%d\n", err);
@@ -475,7 +474,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
struct qlcnic_cmd_args cmd;
memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = adapter->tx_context_id;
+ cmd.req.arg1 = adapter->tx_ring->ctx_id;
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
cmd.req.arg3 = 0;
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
@@ -755,7 +754,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
struct qlcnic_info *nic_info;
size_t nic_size = sizeof(struct qlcnic_info);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return err;
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
@@ -855,7 +854,7 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
u32 arg1;
struct qlcnic_cmd_args cmd;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
return err;
@@ -895,8 +894,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
if (esw_stats == NULL)
return -ENOMEM;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
- func != adapter->ahw->pci_func) {
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC &&
+ func != adapter->ahw->pci_func) {
dev_err(&adapter->pdev->dev,
"Not privilege to query stats for func=%d", func);
return -EIO;
@@ -1007,7 +1006,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
if (esw_stats == NULL)
return -ENOMEM;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return -EIO;
if (adapter->npars == NULL)
return -EIO;
@@ -1058,7 +1057,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
u32 arg1;
struct qlcnic_cmd_args cmd;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return -EIO;
if (func_esw == QLCNIC_STATS_PORT) {
@@ -1131,7 +1130,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args cmd;
u8 pci_func;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return err;
pci_func = esw_cfg->pci_func;
arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
@@ -1146,7 +1145,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
case QLCNIC_PORT_DEFAULTS:
arg1 |= (BIT_4 | BIT_6 | BIT_7);
arg2 |= (BIT_0 | BIT_1);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
arg2 |= (BIT_2 | BIT_3);
if (!(esw_cfg->discard_tagged))
arg1 &= ~BIT_4;
@@ -1199,10 +1198,10 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
{
u32 arg1, arg2;
u8 phy_port;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
else
- phy_port = adapter->physical_port;
+ phy_port = adapter->ahw->physical_port;
arg1 = phy_port;
arg1 |= (esw_cfg->pci_func << 8);
if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index a114d9f..ec2ad45 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -209,9 +209,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full);
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->duplex = adapter->link_duplex;
- ecmd->autoneg = adapter->link_autoneg;
+ ethtool_cmd_speed_set(ecmd, ahw->link_speed);
+ ecmd->duplex = ahw->link_duplex;
+ ecmd->autoneg = ahw->link_autoneg;
} else if (ahw->port_type == QLCNIC_XGBE) {
u32 val;
@@ -225,10 +225,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_10000baseT_Full;
}
- if (netif_running(dev) && adapter->has_link_events) {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->autoneg = adapter->link_autoneg;
- ecmd->duplex = adapter->link_duplex;
+ if (netif_running(dev) && ahw->has_link_events) {
+ ethtool_cmd_speed_set(ecmd, ahw->link_speed);
+ ecmd->autoneg = ahw->link_autoneg;
+ ecmd->duplex = ahw->link_duplex;
goto skip;
}
@@ -239,7 +239,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EIO;
skip:
- ecmd->phy_address = adapter->physical_port;
+ ecmd->phy_address = adapter->ahw->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;
switch (ahw->board_type) {
@@ -255,7 +255,7 @@ skip:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
- ecmd->autoneg = adapter->link_autoneg;
+ ecmd->autoneg = ahw->link_autoneg;
break;
case QLCNIC_BRDTYPE_P3P_IMEZ:
case QLCNIC_BRDTYPE_P3P_XG_LOM:
@@ -271,7 +271,7 @@ skip:
ecmd->advertising |= ADVERTISED_TP;
ecmd->supported |= SUPPORTED_TP;
check_sfp_module = netif_running(dev) &&
- adapter->has_link_events;
+ ahw->has_link_events;
case QLCNIC_BRDTYPE_P3P_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
@@ -286,7 +286,7 @@ skip:
(ADVERTISED_FIBRE | ADVERTISED_TP);
ecmd->port = PORT_FIBRE;
check_sfp_module = netif_running(dev) &&
- adapter->has_link_events;
+ ahw->has_link_events;
} else {
ecmd->autoneg = AUTONEG_ENABLE;
ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
@@ -302,7 +302,7 @@ skip:
}
if (check_sfp_module) {
- switch (adapter->module_type) {
+ switch (adapter->ahw->module_type) {
case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
case LINKEVENT_MODULE_OPTICAL_SRLR:
case LINKEVENT_MODULE_OPTICAL_LRM:
@@ -360,9 +360,9 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
else if (ret)
return -EIO;
- adapter->link_speed = ethtool_cmd_speed(ecmd);
- adapter->link_duplex = ecmd->duplex;
- adapter->link_autoneg = ecmd->autoneg;
+ adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
+ adapter->ahw->link_duplex = ecmd->duplex;
+ adapter->ahw->link_autoneg = ecmd->autoneg;
if (!netif_running(dev))
return 0;
@@ -513,11 +513,11 @@ static void qlcnic_get_channels(struct net_device *dev,
struct qlcnic_adapter *adapter = netdev_priv(dev);
channel->max_rx = rounddown_pow_of_two(min_t(int,
- adapter->max_rx_ques, num_online_cpus()));
- channel->max_tx = adapter->max_tx_ques;
+ adapter->ahw->max_rx_ques, num_online_cpus()));
+ channel->max_tx = adapter->ahw->max_tx_ques;
channel->rx_count = adapter->max_sds_rings;
- channel->tx_count = adapter->max_tx_ques;
+ channel->tx_count = adapter->ahw->max_tx_ques;
}
static int qlcnic_set_channels(struct net_device *dev,
@@ -546,7 +546,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
- int port = adapter->physical_port;
+ int port = adapter->ahw->physical_port;
__u32 val;
if (ahw->port_type == QLCNIC_GBE) {
@@ -592,7 +592,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
- int port = adapter->physical_port;
+ int port = adapter->ahw->physical_port;
__u32 val;
/* read mode */
@@ -706,7 +706,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
if (ret)
goto clear_it;
- adapter->diag_cnt = 0;
+ adapter->ahw->diag_cnt = 0;
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
cmd.req.arg1 = adapter->ahw->pci_func;
@@ -718,7 +718,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
msleep(10);
- ret = !adapter->diag_cnt;
+ ret = !adapter->ahw->diag_cnt;
done:
qlcnic_diag_free_res(netdev, max_sds_rings);
@@ -764,7 +764,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
- adapter->diag_cnt = 0;
+ adapter->ahw->diag_cnt = 0;
qlcnic_xmit_frame(skb, adapter->netdev);
loop = 0;
@@ -773,11 +773,11 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
qlcnic_process_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
break;
- } while (!adapter->diag_cnt);
+ } while (!adapter->ahw->diag_cnt);
dev_kfree_skb_any(skb);
- if (!adapter->diag_cnt)
+ if (!adapter->ahw->diag_cnt)
QLCDB(adapter, DRV,
"LB Test: packet #%d was not received\n", i + 1);
else
@@ -799,18 +799,19 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int max_sds_rings = adapter->max_sds_rings;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_host_sds_ring *sds_ring;
int loop = 0;
int ret;
- if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
+ if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
netdev_info(netdev, "Firmware is not loopback test capable\n");
return -EOPNOTSUPP;
}
QLCDB(adapter, DRV, "%s loopback test in progress\n",
mode == QLCNIC_ILB_MODE ? "internal" : "external");
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(netdev, "Loopback test not supported for non "
"privilege function\n");
return 0;
@@ -829,7 +830,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
if (ret)
goto free_res;
- adapter->diag_cnt = 0;
+ ahw->diag_cnt = 0;
do {
msleep(500);
qlcnic_process_rcv_ring_diag(sds_ring);
@@ -838,11 +839,11 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
" configure request\n");
ret = -QLCNIC_FW_NOT_RESPOND;
goto free_res;
- } else if (adapter->diag_cnt) {
- ret = adapter->diag_cnt;
+ } else if (ahw->diag_cnt) {
+ ret = ahw->diag_cnt;
goto free_res;
}
- } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
+ } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
ret = qlcnic_do_lb_test(adapter, mode);
@@ -1031,7 +1032,7 @@ static int qlcnic_set_led(struct net_device *dev,
int max_sds_rings = adapter->max_sds_rings;
int err = -EIO, active = 1;
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(dev, "LED test not supported for non "
"privilege function\n");
return -EOPNOTSUPP;
@@ -1210,14 +1211,14 @@ static u32 qlcnic_get_msglevel(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- return adapter->msg_enable;
+ return adapter->ahw->msg_enable;
}
static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- adapter->msg_enable = msglvl;
+ adapter->ahw->msg_enable = msglvl;
}
static int
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 0bee9f7..92cd3c3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -715,6 +715,9 @@ enum {
#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45
+#define QLCNIC_MAX_MC_COUNT 38
+#define QLCNIC_WATCHDOG_TIMEOUTVALUE 5
+
#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 2f42d3e..7e943db 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -442,7 +442,7 @@ void qlcnic_set_multi(struct net_device *netdev)
}
if ((netdev->flags & IFF_ALLMULTI) ||
- (netdev_mc_count(netdev) > adapter->max_mc_count)) {
+ (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
goto send_fw_cmd;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 8abd7d9..5a1704e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -199,6 +199,7 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
struct qlcnic_cmd_buffer *cmd_buf_arr;
struct net_device *netdev = adapter->netdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
size = sizeof(struct qlcnic_host_tx_ring);
tx_ring = kzalloc(size, GFP_KERNEL);
@@ -242,7 +243,7 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
rds_ring->dma_size =
QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
rds_ring->skb_size =
@@ -651,7 +652,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
"Not an Ethernet NIC func=%u\n", val);
return -EIO;
}
- adapter->physical_port = (val >> 2);
+ adapter->ahw->physical_port = (val >> 2);
if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
timeo = QLCNIC_INIT_TIMEOUT_SECS;
@@ -989,7 +990,7 @@ qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
{
u32 offs = QLCNIC_BOOTLD_START;
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
QLCNIC_UNI_DIR_SECT_BOOTLD,
QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
@@ -1002,7 +1003,7 @@ qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
{
u32 offs = QLCNIC_IMAGE_START;
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
QLCNIC_UNI_DIR_SECT_FW,
QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
@@ -1013,7 +1014,7 @@ qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
static __le32
qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
{
- if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
return cpu_to_le32((qlcnic_get_data_desc(adapter,
QLCNIC_UNI_DIR_SECT_FW,
QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
@@ -1031,7 +1032,7 @@ qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
const u8 *ver_str;
int i, ret;
- if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
@@ -1059,7 +1060,7 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
const struct firmware *fw = adapter->fw;
__le32 bios_ver, prd_off = adapter->file_prd_off;
- if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
return cpu_to_le32(
*(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
@@ -1129,7 +1130,7 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
dev_info(&pdev->dev, "loading firmware from %s\n",
- fw_name[adapter->fw_type]);
+ fw_name[adapter->ahw->fw_type]);
if (fw) {
__le64 data;
@@ -1221,7 +1222,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
u32 ver, bios, min_size;
struct pci_dev *pdev = adapter->pdev;
const struct firmware *fw = adapter->fw;
- u8 fw_type = adapter->fw_type;
+ u8 fw_type = adapter->ahw->fw_type;
if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
if (qlcnic_validate_unified_romimage(adapter))
@@ -1266,7 +1267,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
{
u8 fw_type;
- switch (adapter->fw_type) {
+ switch (adapter->ahw->fw_type) {
case QLCNIC_UNKNOWN_ROMIMAGE:
fw_type = QLCNIC_UNIFIED_ROMIMAGE;
break;
@@ -1277,7 +1278,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
break;
}
- adapter->fw_type = fw_type;
+ adapter->ahw->fw_type = fw_type;
}
@@ -1287,16 +1288,16 @@ void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int rc;
- adapter->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
+ adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
next:
qlcnic_get_next_fwtype(adapter);
- if (adapter->fw_type == QLCNIC_FLASH_ROMIMAGE) {
+ if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
adapter->fw = NULL;
} else {
rc = request_firmware(&adapter->fw,
- fw_name[adapter->fw_type], &pdev->dev);
+ fw_name[adapter->ahw->fw_type], &pdev->dev);
if (rc != 0)
goto next;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 8f5ee9f..03b5e3e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -580,7 +580,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
u8 lb_status = 0;
struct net_device *netdev = adapter->netdev;
- adapter->has_link_events = 1;
+ adapter->ahw->has_link_events = 1;
cable_OUI = msg->body[1] & 0xffffffff;
cable_len = (msg->body[1] >> 32) & 0xffff;
@@ -607,13 +607,13 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
qlcnic_advert_link_change(adapter, link_status);
if (duplex == LINKEVENT_FULL_DUPLEX)
- adapter->link_duplex = DUPLEX_FULL;
+ adapter->ahw->link_duplex = DUPLEX_FULL;
else
- adapter->link_duplex = DUPLEX_HALF;
+ adapter->ahw->link_duplex = DUPLEX_HALF;
- adapter->module_type = module;
- adapter->link_autoneg = autoneg;
- adapter->link_speed = link_speed;
+ adapter->ahw->module_type = module;
+ adapter->ahw->link_autoneg = autoneg;
+ adapter->ahw->link_speed = link_speed;
}
static void
@@ -651,17 +651,17 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
break;
case 1:
dev_info(dev, "loopback already in progress\n");
- adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+ adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
break;
case 2:
dev_info(dev, "loopback cable is not connected\n");
- adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+ adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
break;
default:
dev_info(dev,
"configure loopback request failed, ret %x\n",
ret);
- adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+ adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
break;
}
break;
@@ -1124,7 +1124,7 @@ void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
skb_pull(skb, pkt_offset);
if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
- adapter->diag_cnt++;
+ adapter->ahw->diag_cnt++;
else
dump_skb(skb, adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index b4edf75..0cf9991 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -329,7 +329,7 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
adapter->max_sds_rings = 1;
adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
- if (adapter->msix_supported) {
+ if (adapter->ahw->msix_supported) {
enable_msix:
for (i = 0; i < num_msix; i++)
adapter->msix_entries[i].entry = i;
@@ -370,7 +370,7 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
- adapter->int_vec_bit = legacy_intrp->int_vec_bit;
+ adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
legacy_intrp->tgt_status_reg);
adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter->ahw,
@@ -388,7 +388,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
{
int num_msix, err;
- if (adapter->msix_supported)
+ if (adapter->ahw->msix_supported)
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
QLCNIC_DEF_NUM_STS_DESC_RINGS));
else
@@ -537,7 +537,7 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
priv_level = QLC_DEV_GET_DRV(op_mode, ahw->pci_func);
if (priv_level == QLCNIC_NON_PRIV_FUNC) {
- adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
+ ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d Non Privileged function\n",
ahw->fw_hal_version);
@@ -621,7 +621,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) {
+ if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
if (fw_dump->tmpl_hdr == NULL ||
adapter->fw_version > prev_fw_version) {
if (fw_dump->tmpl_hdr)
@@ -653,7 +653,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
}
- adapter->msix_supported = !!use_msi_x;
+ adapter->ahw->msix_supported = !!use_msi_x;
adapter->num_txd = MAX_CMD_DESCRIPTORS;
@@ -670,15 +670,15 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
if (err)
return err;
- adapter->physical_port = (u8)nic_info.phys_port;
- adapter->switch_mode = nic_info.switch_mode;
- adapter->max_tx_ques = nic_info.max_tx_ques;
- adapter->max_rx_ques = nic_info.max_rx_ques;
- adapter->capabilities = nic_info.capabilities;
- adapter->max_mac_filters = nic_info.max_mac_filters;
- adapter->max_mtu = nic_info.max_mtu;
+ adapter->ahw->physical_port = (u8)nic_info.phys_port;
+ adapter->ahw->switch_mode = nic_info.switch_mode;
+ adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
+ adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
+ adapter->ahw->capabilities = nic_info.capabilities;
+ adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
+ adapter->ahw->max_mtu = nic_info.max_mtu;
- if (adapter->capabilities & BIT_6)
+ if (adapter->ahw->capabilities & BIT_6)
adapter->flags |= QLCNIC_ESWITCH_ENABLED;
else
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
@@ -765,7 +765,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
features |= (NETIF_F_TSO | NETIF_F_TSO6);
vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
}
@@ -812,7 +812,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
if (priv_level == QLCNIC_MGMT_FUNC) {
- adapter->op_mode = QLCNIC_MGMT_FUNC;
+ adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
err = qlcnic_init_pci_info(adapter);
if (err)
return err;
@@ -822,7 +822,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
"HAL Version: %d, Management function\n",
adapter->ahw->fw_hal_version);
} else if (priv_level == QLCNIC_PRIV_FUNC) {
- adapter->op_mode = QLCNIC_PRIV_FUNC;
+ adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d, Privileged function\n",
adapter->ahw->fw_hal_version);
@@ -852,7 +852,7 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
esw_cfg.offload_flags = BIT_0;
esw_cfg.mac_override = BIT_0;
esw_cfg.promisc_mode = BIT_0;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
esw_cfg.offload_flags |= (BIT_1 | BIT_2);
if (qlcnic_config_switch_port(adapter, &esw_cfg))
return -EIO;
@@ -933,7 +933,7 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
u32 npar_state;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
return 0;
npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
@@ -955,7 +955,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
int err;
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
+ adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return 0;
err = qlcnic_set_default_offload_settings(adapter);
@@ -989,7 +989,7 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
if (err)
goto err_out;
- adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
+ adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
}
err = qlcnic_need_fw_reset(adapter);
@@ -1050,7 +1050,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
handler = qlcnic_tmp_intr;
if (!QLCNIC_IS_MSI_FAMILY(adapter))
flags |= IRQF_SHARED;
@@ -1109,7 +1109,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (qlcnic_set_eswitch_port_config(adapter))
return -EIO;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
@@ -1140,7 +1140,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_linkevent_request(adapter, 1);
- adapter->reset_context = 0;
+ adapter->ahw->reset_context = 0;
set_bit(__QLCNIC_DEV_UP, &adapter->state);
return 0;
}
@@ -1273,7 +1273,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
int ring;
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
QLCNIC_DISABLE_INTR(sds_ring->crb_intr_mask);
@@ -1284,7 +1284,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
qlcnic_detach(adapter);
- adapter->diag_test = 0;
+ adapter->ahw->diag_test = 0;
adapter->max_sds_rings = max_sds_rings;
if (qlcnic_attach(adapter))
@@ -1344,7 +1344,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_detach(adapter);
adapter->max_sds_rings = 1;
- adapter->diag_test = test;
+ adapter->ahw->diag_test = test;
ret = qlcnic_attach(adapter);
if (ret) {
@@ -1364,14 +1364,14 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
qlcnic_post_rx_buffers(adapter, rds_ring);
}
- if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
}
}
- if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+ if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
adapter->ahw->loopback_state = 0;
qlcnic_linkevent_request(adapter, 1);
}
@@ -1442,11 +1442,11 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
int err;
struct pci_dev *pdev = adapter->pdev;
- adapter->mc_enabled = 0;
- adapter->max_mc_count = 38;
+ adapter->ahw->mc_enabled = 0;
+ adapter->ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
netdev->netdev_ops = &qlcnic_netdev_ops;
- netdev->watchdog_timeo = 5*HZ;
+ netdev->watchdog_timeo = QLCNIC_WATCHDOG_TIMEOUTVALUE*HZ;
qlcnic_change_mtu(netdev, netdev->mtu);
@@ -1455,16 +1455,16 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
if (pci_using_dac)
netdev->hw_features |= NETIF_F_HIGHDMA;
netdev->vlan_features = netdev->hw_features;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
netdev->hw_features |= NETIF_F_HW_VLAN_TX;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
netdev->hw_features |= NETIF_F_LRO;
netdev->features |= netdev->hw_features |
@@ -1895,7 +1895,7 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
temp_val);
rv = 1;
} else if (temp_state == QLCNIC_TEMP_WARN) {
- if (adapter->temp == QLCNIC_TEMP_NORMAL) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
dev_err(&netdev->dev,
"Device temperature %d degrees C "
"exceeds operating range."
@@ -1903,13 +1903,13 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
temp_val);
}
} else {
- if (adapter->temp == QLCNIC_TEMP_WARN) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
dev_info(&netdev->dev,
"Device temperature is now %d degrees C"
" in normal range.\n", temp_val);
}
}
- adapter->temp = temp_state;
+ adapter->ahw->temp = temp_state;
return rv;
}
@@ -1925,7 +1925,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
adapter->need_fw_reset = 1;
else
- adapter->reset_context = 1;
+ adapter->ahw->reset_context = 1;
}
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
@@ -1949,7 +1949,7 @@ static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
status = readl(adapter->isr_int_vec);
- if (!(status & adapter->int_vec_bit))
+ if (!(status & adapter->ahw->int_vec_bit))
return IRQ_NONE;
/* check interrupt state machine, to be sure */
@@ -1981,7 +1981,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
return IRQ_NONE;
done:
- adapter->diag_cnt++;
+ adapter->ahw->diag_cnt++;
QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
return IRQ_HANDLED;
}
@@ -2264,7 +2264,7 @@ qlcnic_fwinit_work(struct work_struct *work)
return;
}
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
qlcnic_api_unlock(adapter);
goto wait_npar;
}
@@ -2380,9 +2380,9 @@ qlcnic_detach_work(struct work_struct *work)
goto err_ret;
}
- if (adapter->temp == QLCNIC_TEMP_PANIC) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
- adapter->temp);
+ adapter->ahw->temp);
goto err_ret;
}
@@ -2508,7 +2508,7 @@ qlcnic_attach_work(struct work_struct *work)
struct net_device *netdev = adapter->netdev;
u32 npar_state;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC) {
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
qlcnic_clr_all_drv_state(adapter, 0);
@@ -2565,7 +2565,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->reset_context && auto_fw_reset) {
+ if (adapter->ahw->reset_context && auto_fw_reset) {
qlcnic_reset_hw_context(adapter);
adapter->netdev->trans_start = jiffies;
}
@@ -2678,7 +2678,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (qlcnic_api_lock(adapter))
return -EINVAL;
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
+ if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 4555016..a9f8836 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -9,7 +9,7 @@ qlcnic_store_bridged_mode(struct device *dev,
unsigned long new;
int ret = -EINVAL;
- if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
+ if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
goto err_out;
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
@@ -32,7 +32,7 @@ qlcnic_show_bridged_mode(struct device *dev,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
int bridged_mode = 0;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
return sprintf(buf, "%d\n", bridged_mode);
@@ -407,7 +407,7 @@ validate_esw_config(struct qlcnic_adapter *adapter,
if (pci_func >= QLCNIC_MAX_PCI_FUNC)
return QL_STATUS_INVALID_PARAM;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
return QL_STATUS_INVALID_PARAM;
@@ -462,7 +462,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
return ret;
for (i = 0; i < count; i++) {
- if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
return QL_STATUS_INVALID_PARAM;
@@ -488,7 +488,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
}
}
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
goto out;
for (i = 0; i < count; i++) {
@@ -822,7 +822,7 @@ qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
if (device_create_file(dev, &dev_attr_bridged_mode))
dev_warn(dev,
"failed to create bridged_mode sysfs entry\n");
@@ -833,7 +833,7 @@ qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
device_remove_file(dev, &dev_attr_bridged_mode);
}
@@ -845,7 +845,7 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
if (device_create_bin_file(dev, &bin_attr_port_stats))
dev_info(dev, "failed to create port stats sysfs entry");
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
dev_info(dev, "failed to create diag_mode sysfs entry\n");
@@ -861,7 +861,7 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
return;
if (device_create_bin_file(dev, &bin_attr_esw_config))
dev_info(dev, "failed to create esw config sysfs entry");
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return;
if (device_create_bin_file(dev, &bin_attr_npar_config))
dev_info(dev, "failed to create npar config sysfs entry");
@@ -878,7 +878,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
device_remove_bin_file(dev, &bin_attr_port_stats);
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
device_remove_file(dev, &dev_attr_beacon);
@@ -888,7 +888,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
device_remove_bin_file(dev, &bin_attr_esw_config);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return;
device_remove_bin_file(dev, &bin_attr_npar_config);
device_remove_bin_file(dev, &bin_attr_pm_config);
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 01/15] qlcnic: Refactoring - template based hardware interface
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Anirban Chakraborty
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Separate adapter specific hardware accesses routines
Create template based hardware interface
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 35 ++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 37 ++--
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 29 ++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 55 +----
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 90 ++++++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 28 ++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 270 +++++++++-----------
7 files changed, 294 insertions(+), 250 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index eaa1db9..fec4b89 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -439,6 +439,8 @@ struct qlcnic_fw_dump {
struct qlcnic_dump_template_hdr *tmpl_hdr;
};
+struct qlcnic_hardware_ops;
+
/*
* One hardware_context{} per adapter
* contains interrupt info as well shared hardware info.
@@ -461,6 +463,8 @@ struct qlcnic_hardware_context {
u8 beacon_state;
+ u32 fw_hal_version;
+ struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
};
@@ -552,8 +556,9 @@ struct qlcnic_recv_context {
/* HW context creation */
#define QLCNIC_OS_CRB_RETRY_COUNT 4000
-#define QLCNIC_CDRP_SIGNATURE_MAKE(pcifn, version) \
- (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
+#define QLCNIC_CDRP_SIGNATURE_MAKE(ahw) \
+ (((ahw->pci_func) & 0xff) | (((ahw->fw_hal_version) & \
+ 0xff) << 8) | (0xcafe << 16))
#define QLCNIC_CDRP_CMD_BIT 0x80000000
@@ -573,9 +578,7 @@ struct qlcnic_recv_context {
* the crb QLCNIC_CDRP_CRB_OFFSET.
*/
#define QLCNIC_CDRP_FORM_CMD(cmd) (QLCNIC_CDRP_CMD_BIT | (cmd))
-#define QLCNIC_CDRP_IS_CMD(cmd) (((cmd) & QLCNIC_CDRP_CMD_BIT) != 0)
-#define QLCNIC_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
#define QLCNIC_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
#define QLCNIC_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
#define QLCNIC_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
@@ -1022,7 +1025,6 @@ struct qlcnic_adapter {
u16 max_mtu;
u16 pvid;
- u32 fw_hal_version;
u32 capabilities;
u32 irq;
u32 temp;
@@ -1443,9 +1445,9 @@ void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64);
(((addr) < (high)) && ((addr) >= (low)))
#define QLCRD32(adapter, off) \
- (qlcnic_hw_read_wx_2M(adapter, off))
+ adapter->ahw->hw_ops->rdreg(adapter, off)
#define QLCWR32(adapter, off, val) \
- (qlcnic_hw_write_wx_2M(adapter, off, val))
+ adapter->ahw->hw_ops->wrtreg(adapter, off, val)
int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32);
void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
@@ -1480,6 +1482,7 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
int qlcnic_dump_fw(struct qlcnic_adapter *);
+void qlcnic_get_ocm_win(struct qlcnic_hardware_context *);
/* Functions from qlcnic_init.c */
int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
@@ -1496,7 +1499,7 @@ int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter);
void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter);
-void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32);
+void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *, u32);
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);
@@ -1537,6 +1540,9 @@ void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
+void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+
/* Functions from qlcnic_ethtool.c */
int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
@@ -1551,6 +1557,8 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
void qlcnic_dev_request_reset(struct qlcnic_adapter *);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
+int qlcnic_setup_intr(struct qlcnic_adapter *);
+
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
@@ -1625,6 +1633,17 @@ struct qlcnic_nic_template {
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
};
+/* function template for hardware ops based on different chip type */
+struct qlcnic_hardware_ops {
+ void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
+ void (*write_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
+ u32 (*rdreg) (struct qlcnic_adapter *, ulong);
+ int (*wrtreg) (struct qlcnic_adapter *, ulong, u32);
+ void (*get_ocm_win) (struct qlcnic_hardware_context *);
+ int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
+ int (*setup_intr) (struct qlcnic_adapter *);
+ void (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+};
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
if (NETIF_MSG_##lvl & adapter->msg_enable) \
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index b8ead69..14ddd27 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -34,8 +34,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
struct pci_dev *pdev = adapter->pdev;
struct qlcnic_hardware_context *ahw = adapter->ahw;
- signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func,
- adapter->fw_hal_version);
+ signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw);
/* Acquire semaphore before accessing CRB */
if (qlcnic_api_lock(adapter)) {
@@ -129,7 +128,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_TEMP_SIZE;
memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
- qlcnic_issue_cmd(adapter, &cmd);
+ ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (cmd.rsp.cmd != QLCNIC_RCODE_SUCCESS) {
dev_info(&adapter->pdev->dev,
"Can't get template size %d\n", cmd.rsp.cmd);
@@ -153,7 +152,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
cmd.req.arg1 = LSD(tmp_addr_t);
cmd.req.arg2 = MSD(tmp_addr_t);
cmd.req.arg3 = temp_size;
- qlcnic_issue_cmd(adapter, &cmd);
+ ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
@@ -200,7 +199,7 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
cmd.req.arg2 = mtu;
cmd.req.arg3 = 0;
if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (cmd.rsp.cmd) {
dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
return -EIO;
@@ -319,7 +318,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
cmd.req.arg2 = (u32) (phys_addr & 0xffffffff);
cmd.req.arg3 = rq_size;
cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_RX_CTX;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err) {
dev_err(&adapter->pdev->dev,
@@ -374,7 +373,7 @@ qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
cmd.req.arg3 = 0;
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_RX_CTX;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev,
"Failed to destroy rx ctx in firmware\n");
@@ -446,7 +445,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
cmd.req.arg2 = ((u32)phys_addr & 0xffffffff);
cmd.req.arg3 = rq_size;
cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_TX_CTX;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
@@ -480,7 +479,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
cmd.req.arg3 = 0;
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev,
"Failed to destroy tx ctx in firmware\n");
@@ -494,7 +493,7 @@ qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
memset(&cmd, 0, sizeof(cmd));
cmd.req.arg1 = config;
cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIG_PORT;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
return cmd.rsp.cmd;
}
@@ -667,7 +666,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
cmd.req.arg1 = adapter->ahw->pci_func | BIT_8;
cmd.req.cmd = QLCNIC_CDRP_CMD_MAC_ADDRESS;
cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS)
@@ -704,7 +703,7 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
cmd.req.arg1 = MSD(nic_dma_t);
cmd.req.arg2 = LSD(nic_dma_t);
cmd.req.arg3 = (func_id << 16 | nic_size);
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
@@ -775,7 +774,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
cmd.req.arg1 = MSD(nic_dma_t);
cmd.req.arg2 = LSD(nic_dma_t);
cmd.req.arg3 = ((nic->pci_func << 16) | nic_size);
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
@@ -813,7 +812,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
cmd.req.arg1 = MSD(pci_info_dma_t);
cmd.req.arg2 = LSD(pci_info_dma_t);
cmd.req.arg3 = pci_size;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
@@ -858,7 +857,7 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_SET_PORTMIRRORING;
cmd.req.arg1 = arg1;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
@@ -911,7 +910,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
cmd.req.arg1 = arg1;
cmd.req.arg2 = MSD(stats_dma_t);
cmd.req.arg3 = LSD(stats_dma_t);
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (!err) {
@@ -1073,7 +1072,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS;
cmd.req.arg1 = arg1;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
return cmd.rsp.cmd;
err_ret:
@@ -1094,7 +1093,7 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG;
cmd.req.arg1 = *arg1;
cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
*arg1 = cmd.rsp.arg1;
*arg2 = cmd.rsp.arg2;
err = cmd.rsp.cmd;
@@ -1172,7 +1171,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH;
cmd.req.arg1 = arg1;
cmd.req.arg2 = arg2;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 9e9e78a..a114d9f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -192,10 +192,11 @@ static int
qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
int check_sfp_module = 0;
/* read which mode */
- if (adapter->ahw->port_type == QLCNIC_GBE) {
+ if (ahw->port_type == QLCNIC_GBE) {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
@@ -212,7 +213,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->duplex = adapter->link_duplex;
ecmd->autoneg = adapter->link_autoneg;
- } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
+ } else if (ahw->port_type == QLCNIC_XGBE) {
u32 val;
val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
@@ -241,7 +242,7 @@ skip:
ecmd->phy_address = adapter->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;
- switch (adapter->ahw->board_type) {
+ switch (ahw->board_type) {
case QLCNIC_BRDTYPE_P3P_REF_QG:
case QLCNIC_BRDTYPE_P3P_4_GB:
case QLCNIC_BRDTYPE_P3P_4_GB_MM:
@@ -278,7 +279,7 @@ skip:
ecmd->autoneg = AUTONEG_DISABLE;
break;
case QLCNIC_BRDTYPE_P3P_10G_TP:
- if (adapter->ahw->port_type == QLCNIC_XGBE) {
+ if (ahw->port_type == QLCNIC_XGBE) {
ecmd->autoneg = AUTONEG_DISABLE;
ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
ecmd->advertising |=
@@ -296,7 +297,7 @@ skip:
break;
default:
dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
- adapter->ahw->board_type);
+ ahw->board_type);
return -EIO;
}
@@ -376,12 +377,13 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 *regs_buff = p;
int ring, i = 0, j = 0;
memset(p, 0, qlcnic_get_regs_len(dev));
regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
- (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
+ (ahw->revision_id << 16) | (adapter->pdev)->device;
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
regs_buff[1] = QLCNIC_MGMT_API_VERSION;
@@ -543,10 +545,11 @@ qlcnic_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
int port = adapter->physical_port;
__u32 val;
- if (adapter->ahw->port_type == QLCNIC_GBE) {
+ if (ahw->port_type == QLCNIC_GBE) {
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
return;
/* get flow control settings */
@@ -568,7 +571,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
break;
}
- } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
+ } else if (ahw->port_type == QLCNIC_XGBE) {
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return;
pause->rx_pause = 1;
@@ -588,11 +591,12 @@ qlcnic_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
int port = adapter->physical_port;
__u32 val;
/* read mode */
- if (adapter->ahw->port_type == QLCNIC_GBE) {
+ if (ahw->port_type == QLCNIC_GBE) {
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
return -EIO;
/* set flow control */
@@ -603,8 +607,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
else
qlcnic_gb_unset_rx_flowctl(val);
- QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
- val);
+ QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
/* set autoneg */
val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
switch (port) {
@@ -635,7 +638,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
break;
}
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
- } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
+ } else if (ahw->port_type == QLCNIC_XGBE) {
if (!pause->rx_pause || pause->autoneg)
return -EOPNOTSUPP;
@@ -707,7 +710,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
cmd.req.arg1 = adapter->ahw->pci_func;
- qlcnic_issue_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
ret = cmd.rsp.cmd;
if (ret)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 28a6b28..0bee9f7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -449,13 +449,10 @@ enum {
#define ISR_INT_TARGET_STATUS_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
#define ISR_INT_TARGET_MASK_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
-#define QLCNIC_PCI_MN_2M (0)
-#define QLCNIC_PCI_MS_2M (0x80000)
#define QLCNIC_PCI_OCM0_2M (0x000c0000UL)
#define QLCNIC_PCI_CRBSPACE (0x06000000UL)
#define QLCNIC_PCI_CAMQM (0x04800000UL)
#define QLCNIC_PCI_CAMQM_END (0x04800800UL)
-#define QLCNIC_PCI_2MB_SIZE (0x00200000UL)
#define QLCNIC_PCI_CAMQM_2M_BASE (0x000ff800UL)
#define QLCNIC_CRB_CAM QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_CAM)
@@ -520,23 +517,6 @@ enum {
#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
-/*
- * Register offsets for MS
- */
-#define SIU_TEST_AGT_BASE (0x60)
-
-#define SIU_TEST_AGT_ADDR_LO (0x04)
-#define SIU_TEST_AGT_ADDR_HI (0x18)
-#define SIU_TEST_AGT_WRDATA_LO (0x08)
-#define SIU_TEST_AGT_WRDATA_HI (0x0c)
-#define SIU_TEST_AGT_WRDATA(i) (0x08+(4*(i)))
-#define SIU_TEST_AGT_RDDATA_LO (0x10)
-#define SIU_TEST_AGT_RDDATA_HI (0x14)
-#define SIU_TEST_AGT_RDDATA(i) (0x10+(4*(i)))
-
-#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
-#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
-
/* XG Link status */
#define XG_LINK_UP 0x10
#define XG_LINK_DOWN 0x20
@@ -579,17 +559,13 @@ enum {
#define CRB_XG_STATE_P3P (QLCNIC_REG(0x98))
#define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8))
-#define CRB_PF_LINK_SPEED_2 (QLCNIC_REG(0xec))
#define CRB_TEMP_STATE (QLCNIC_REG(0x1b4))
-#define CRB_V2P_0 (QLCNIC_REG(0x290))
-#define CRB_V2P(port) (CRB_V2P_0+((port)*4))
#define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0))
#define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128))
#define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c))
-#define CRB_MAC_BLOCK_START (QLCNIC_CAM_RAM(0x1c0))
/*
* CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
@@ -616,11 +592,6 @@ enum {
/* Lock IDs for PHY lock */
#define PHY_LOCK_DRIVER 0x44524956
-/* Used for PS PCI Memory access */
-#define PCIX_PS_OP_ADDR_LO (0x10000)
-/* via CRB (PS side only) */
-#define PCIX_PS_OP_ADDR_HI (0x10004)
-
#define PCIX_INT_VECTOR (0x10100)
#define PCIX_INT_MASK (0x10104)
@@ -763,7 +734,6 @@ struct qlcnic_legacy_intr_set {
u32 int_vec_bit;
u32 tgt_status_reg;
u32 tgt_mask_reg;
- u32 pci_int_reg;
};
#define QLCNIC_FW_API 0x1b216c
@@ -837,50 +807,42 @@ enum {
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \
.tgt_status_reg = ISR_INT_TARGET_STATUS, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, }, \
\
{ \
.int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \
.tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \
- .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \
- .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, }, \
}
/* NIU REGS */
@@ -1031,4 +993,5 @@ struct crb_128M_2M_sub_block_map {
struct crb_128M_2M_block_map{
struct crb_128M_2M_sub_block_map sub_block[16];
};
+
#endif /* __QLCNIC_HDR_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index b528e52..2f42d3e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -6,6 +6,7 @@
*/
#include "qlcnic.h"
+#include "qlcnic_hdr.h"
#include <linux/slab.h>
#include <net/ip.h>
@@ -266,6 +267,13 @@ static const unsigned crb_hub_agt[64] = {
0,
};
+static const u32 msi_tgt_status[8] = {
+ ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
+};
+
/* PCI Windowing for DDR regions. */
#define QLCNIC_PCIE_SEM_TIMEOUT 10000
@@ -864,7 +872,7 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
* In: 'off' is offset from base in 128M pci map
*/
static int
-qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
+qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw,
ulong off, void __iomem **addr)
{
const struct crb_128M_2M_sub_block_map *m;
@@ -880,7 +888,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
- *addr = adapter->ahw->pci_base0 + m->start_2M +
+ *addr = ahw->pci_base0 + m->start_2M +
(off - m->start_128M);
return 0;
}
@@ -888,7 +896,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
/*
* Not in direct map, use crb window
*/
- *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
+ *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
return 1;
}
@@ -929,7 +937,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
int rv;
void __iomem *addr = NULL;
- rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
if (rv == 0) {
writel(data, addr);
@@ -962,7 +970,7 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
u32 data = -1;
void __iomem *addr = NULL;
- rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
if (rv == 0)
return readl(addr);
@@ -986,11 +994,11 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
void __iomem *
-qlcnic_get_ioaddr(struct qlcnic_adapter *adapter, u32 offset)
+qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, u32 offset)
{
void __iomem *addr = NULL;
- WARN_ON(qlcnic_pci_get_crb_addr_2M(adapter, offset, &addr));
+ WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr));
return addr;
}
@@ -1078,13 +1086,13 @@ qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
/* P3 onward, test agent base for MIU and SIU is same */
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
+ mem_crb = qlcnic_get_ioaddr(adapter->ahw,
QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
goto correct;
}
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
+ mem_crb = qlcnic_get_ioaddr(adapter->ahw,
QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
goto correct;
}
@@ -1170,13 +1178,13 @@ qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
/* P3 onward, test agent base for MIU and SIU is same */
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
+ mem_crb = qlcnic_get_ioaddr(adapter->ahw,
QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
goto correct;
}
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter,
+ mem_crb = qlcnic_get_ioaddr(adapter->ahw,
QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
goto correct;
}
@@ -1230,6 +1238,7 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
{
int offset, board_type, magic;
struct pci_dev *pdev = adapter->pdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
offset = QLCNIC_FW_MAGIC_OFFSET;
if (qlcnic_rom_fast_read(adapter, offset, &magic))
@@ -1245,7 +1254,7 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
if (qlcnic_rom_fast_read(adapter, offset, &board_type))
return -EIO;
- adapter->ahw->board_type = board_type;
+ ahw->board_type = board_type;
if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I);
@@ -1264,20 +1273,20 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
case QLCNIC_BRDTYPE_P3P_10G_XFP:
case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
- adapter->ahw->port_type = QLCNIC_XGBE;
+ ahw->port_type = QLCNIC_XGBE;
break;
case QLCNIC_BRDTYPE_P3P_REF_QG:
case QLCNIC_BRDTYPE_P3P_4_GB:
case QLCNIC_BRDTYPE_P3P_4_GB_MM:
- adapter->ahw->port_type = QLCNIC_GBE;
+ ahw->port_type = QLCNIC_GBE;
break;
case QLCNIC_BRDTYPE_P3P_10G_TP:
- adapter->ahw->port_type = (adapter->portnum < 2) ?
+ ahw->port_type = (adapter->portnum < 2) ?
QLCNIC_XGBE : QLCNIC_GBE;
break;
default:
dev_err(&pdev->dev, "unknown board type %x\n", board_type);
- adapter->ahw->port_type = QLCNIC_XGBE;
+ ahw->port_type = QLCNIC_XGBE;
break;
}
@@ -1786,3 +1795,52 @@ error:
vfree(fw_dump->data);
return -EINVAL;
}
+
+void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
+{
+ void __iomem *msix_base_addr;
+ u32 func;
+ u32 msix_base;
+
+ pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
+ msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
+ msix_base = readl(msix_base_addr);
+ func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
+ adapter->ahw->pci_func = func;
+}
+
+void qlcnic_get_ocm_win(struct qlcnic_hardware_context *ahw)
+{
+ ahw->ocm_win_crb = qlcnic_get_ioaddr(ahw, QLCNIC_PCIX_PS_REG(
+ PCIX_OCM_WINDOW_REG(ahw->pci_func)));
+}
+
+void qlcnic_82xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ u32 data;
+ u64 qmdata;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+ memcpy(buf, &qmdata, size);
+ } else {
+ data = QLCRD32(adapter, offset);
+ memcpy(buf, &data, size);
+ }
+}
+
+void qlcnic_82xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ u32 data;
+ u64 qmdata;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ memcpy(&qmdata, buf, size);
+ qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+ } else {
+ memcpy(&data, buf, size);
+ QLCWR32(adapter, offset, data);
+ }
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
new file mode 100644
index 0000000..82c466c
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -0,0 +1,28 @@
+#ifndef __QLCNIC_HW_H
+#define __QLCNIC_HW_H
+
+#include "qlcnic.h"
+
+/* List of PCI device IDs */
+#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
+#define QLCNIC_P3P_BAR0_LENGTH 0x00200000UL
+
+#define QLCNIC_BAR_LENGTH(dev_id, bar) \
+do { \
+ if (dev_id == PCI_DEVICE_ID_QLOGIC_QLE824X)\
+ *bar = QLCNIC_P3P_BAR0_LENGTH; \
+ else \
+ *bar = 0; \
+} while (0)
+
+#define QLCNIC_ENABLE_INTR(adapter, crb) { \
+ writel(1, crb); \
+ if (!QLCNIC_IS_MSI_FAMILY(adapter)) \
+ writel(0xfbff, adapter->tgt_mask_reg); \
+}
+
+#define QLCNIC_DISABLE_INTR(crb) { \
+ writel(0, crb); \
+}
+
+#endif /* __QLCNIC_HDR_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 212c121..ab10b1c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include "qlcnic.h"
+#include "qlcnic_hw.h"
#include <linux/swab.h>
#include <linux/dma-mapping.h>
@@ -105,8 +106,6 @@ static int qlcnic_vlan_rx_del(struct net_device *, u16);
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
-#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
-
static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
{0,}
@@ -240,35 +239,6 @@ qlcnic_napi_disable(struct qlcnic_adapter *adapter)
}
}
-static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
-{
- memset(&adapter->stats, 0, sizeof(adapter->stats));
-}
-
-static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
-{
- u32 control;
- int pos;
-
- pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
- if (pos) {
- pci_read_config_dword(pdev, pos, &control);
- if (enable)
- control |= PCI_MSIX_FLAGS_ENABLE;
- else
- control = 0;
- pci_write_config_dword(pdev, pos, control);
- }
-}
-
-static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- adapter->msix_entries[i].entry = i;
-}
-
static int
qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
{
@@ -276,7 +246,7 @@ qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- if (qlcnic_get_mac_address(adapter, mac_addr) != 0)
+ if (adapter->ahw->hw_ops->get_mac_address(adapter, mac_addr) != 0)
return -EIO;
memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
@@ -354,38 +324,58 @@ static struct qlcnic_nic_template qlcnic_vf_ops = {
.start_firmware = qlcnicvf_start_firmware
};
+static struct qlcnic_hardware_ops qlcnic_82xx_ops = {
+ .read_crb = qlcnic_82xx_read_crb,
+ .write_crb = qlcnic_82xx_write_crb,
+ .rdreg = qlcnic_hw_read_wx_2M,
+ .wrtreg = qlcnic_hw_write_wx_2M,
+ .get_mac_address = qlcnic_get_mac_address,
+ .setup_intr = qlcnic_setup_intr,
+ .mbx_cmd = qlcnic_issue_cmd,
+};
+
static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
{
struct pci_dev *pdev = adapter->pdev;
- int err = -1;
+ int err = -1, i;
+
+ if (!adapter->msix_entries) {
+ adapter->msix_entries = kcalloc(num_msix,
+ sizeof(struct msix_entry), GFP_KERNEL);
+ if (!adapter->msix_entries) {
+ dev_err(&pdev->dev, "failed allocating msix_entries\n");
+ return -ENOMEM;
+ }
+ }
adapter->max_sds_rings = 1;
adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
- qlcnic_set_msix_bit(pdev, 0);
if (adapter->msix_supported) {
enable_msix:
- qlcnic_init_msix_entries(adapter, num_msix);
+ for (i = 0; i < num_msix; i++)
+ adapter->msix_entries[i].entry = i;
+
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
if (err == 0) {
adapter->flags |= QLCNIC_MSIX_ENABLED;
- qlcnic_set_msix_bit(pdev, 1);
-
adapter->max_sds_rings = num_msix;
dev_info(&pdev->dev, "using msi-x interrupts\n");
return err;
- }
- if (err > 0) {
+ } else if (err > 0) {
num_msix = rounddown_pow_of_two(err);
- if (num_msix)
+ if (num_msix) {
+ dev_info(&pdev->dev,
+ "Can't get %d vectors,trying %d vectors\n",
+ err, num_msix);
goto enable_msix;
+ }
}
}
return err;
}
-
static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
{
const struct qlcnic_legacy_intr_set *legacy_intrp;
@@ -393,7 +383,7 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
if (use_msi && !pci_enable_msi(pdev)) {
adapter->flags |= QLCNIC_MSI_ENABLED;
- adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
+ adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
msi_tgt_status[adapter->ahw->pci_func]);
dev_info(&pdev->dev, "using msi interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
@@ -403,33 +393,35 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
adapter->int_vec_bit = legacy_intrp->int_vec_bit;
- adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
+ adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
legacy_intrp->tgt_status_reg);
- adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
+ adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter->ahw,
legacy_intrp->tgt_mask_reg);
- adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
+ adapter->isr_int_vec = qlcnic_get_ioaddr(adapter->ahw, ISR_INT_VECTOR);
- adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
+ adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter->ahw,
ISR_INT_STATE_REG);
dev_info(&pdev->dev, "using legacy interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
}
-static void
+int
qlcnic_setup_intr(struct qlcnic_adapter *adapter)
{
- int num_msix;
+ int num_msix, err;
- if (adapter->msix_supported) {
+ if (adapter->msix_supported)
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
QLCNIC_DEF_NUM_STS_DESC_RINGS));
- } else
+ else
num_msix = 1;
- if (!qlcnic_enable_msix(adapter, num_msix))
- return;
+ err = qlcnic_enable_msix(adapter, num_msix);
+ if (err == -ENOMEM || !err)
+ return err;
qlcnic_enable_msi_legacy(adapter);
+ return 0;
}
static void
@@ -442,10 +434,10 @@ qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
}
static void
-qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
+qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
{
- if (adapter->ahw->pci_base0 != NULL)
- iounmap(adapter->ahw->pci_base0);
+ if (ahw->pci_base0 != NULL)
+ iounmap(ahw->pci_base0);
}
static int
@@ -552,9 +544,10 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
u32 func;
u32 msix_base;
u32 op_mode, priv_level;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
/* Determine FW API version */
- adapter->fw_hal_version = readl(adapter->ahw->pci_base0 +
+ ahw->fw_hal_version = readl(adapter->ahw->pci_base0 +
QLCNIC_FW_API);
/* Find PCI function number */
@@ -562,40 +555,40 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
msix_base = readl(msix_base_addr);
func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
- adapter->ahw->pci_func = func;
+ ahw->pci_func = func;
/* Determine function privilege level */
- priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+ priv_op = ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
op_mode = readl(priv_op);
if (op_mode == QLC_DEV_DRV_DEFAULT)
priv_level = QLCNIC_MGMT_FUNC;
else
- priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
+ priv_level = QLC_DEV_GET_DRV(op_mode, ahw->pci_func);
if (priv_level == QLCNIC_NON_PRIV_FUNC) {
adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d Non Privileged function\n",
- adapter->fw_hal_version);
+ ahw->fw_hal_version);
adapter->nic_ops = &qlcnic_vf_ops;
} else
adapter->nic_ops = &qlcnic_ops;
}
static int
-qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
+qlcnic_setup_pci_map(struct pci_dev *pdev,
+ struct qlcnic_hardware_context *ahw)
{
void __iomem *mem_ptr0 = NULL;
resource_size_t mem_base;
- unsigned long mem_len, pci_len0 = 0;
-
- struct pci_dev *pdev = adapter->pdev;
+ unsigned long mem_len, pci_len0 = 0, bar0_len;
/* remap phys address */
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
mem_len = pci_resource_len(pdev, 0);
- if (mem_len == QLCNIC_PCI_2MB_SIZE) {
+ QLCNIC_BAR_LENGTH(pdev->device, &bar0_len);
+ if (mem_len == bar0_len) {
mem_ptr0 = pci_ioremap_bar(pdev, 0);
if (mem_ptr0 == NULL) {
@@ -609,19 +602,16 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
- adapter->ahw->pci_base0 = mem_ptr0;
- adapter->ahw->pci_len0 = pci_len0;
-
- qlcnic_check_vf(adapter);
+ ahw->pci_base0 = mem_ptr0;
+ ahw->pci_len0 = pci_len0;
- adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter,
- QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(
- adapter->ahw->pci_func)));
+ qlcnic_get_ioaddr(ahw,
+ QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func)));
return 0;
}
-static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
+static void qlcnic_get_brd_name(struct qlcnic_adapter *adapter, char *name)
{
struct pci_dev *pdev = adapter->pdev;
int i, found = 0;
@@ -649,7 +639,8 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
{
u32 fw_major, fw_minor, fw_build, prev_fw_version;
struct pci_dev *pdev = adapter->pdev;
- struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
prev_fw_version = adapter->fw_version;
@@ -672,7 +663,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
fw_major, fw_minor, fw_build);
- if (adapter->ahw->port_type == QLCNIC_XGBE) {
+ if (ahw->port_type == QLCNIC_XGBE) {
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
@@ -684,7 +675,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
- } else if (adapter->ahw->port_type == QLCNIC_GBE) {
+ } else if (ahw->port_type == QLCNIC_GBE) {
adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
@@ -832,6 +823,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
void __iomem *priv_op;
u32 op_mode, priv_level;
int err = 0;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
err = qlcnic_initialize_nic(adapter);
if (err)
@@ -840,14 +832,14 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
return 0;
- priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+ priv_op = ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
op_mode = readl(priv_op);
- priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
+ priv_level = QLC_DEV_GET_DRV(op_mode, ahw->pci_func);
if (op_mode == QLC_DEV_DRV_DEFAULT)
priv_level = QLCNIC_MGMT_FUNC;
else
- priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
+ priv_level = QLC_DEV_GET_DRV(op_mode, ahw->pci_func);
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
if (priv_level == QLCNIC_MGMT_FUNC) {
@@ -859,12 +851,12 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
qlcnic_set_function_modes(adapter);
dev_info(&adapter->pdev->dev,
"HAL Version: %d, Management function\n",
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
} else if (priv_level == QLCNIC_PRIV_FUNC) {
adapter->op_mode = QLCNIC_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d, Privileged function\n",
- adapter->fw_hal_version);
+ adapter->ahw->fw_hal_version);
}
}
@@ -1338,21 +1330,11 @@ out:
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
{
int err = 0;
- adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context),
- GFP_KERNEL);
- if (!adapter->ahw) {
- dev_err(&adapter->pdev->dev,
- "Failed to allocate recv ctx resources for adapter\n");
- err = -ENOMEM;
- goto err_out;
- }
adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
GFP_KERNEL);
if (!adapter->recv_ctx) {
dev_err(&adapter->pdev->dev,
"Failed to allocate recv ctx resources for adapter\n");
- kfree(adapter->ahw);
- adapter->ahw = NULL;
err = -ENOMEM;
goto err_out;
}
@@ -1360,6 +1342,8 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
+ /* clear stats */
+ memset(&adapter->stats, 0, sizeof(adapter->stats));
err_out:
return err;
}
@@ -1373,8 +1357,6 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
vfree(adapter->ahw->fw_dump.tmpl_hdr);
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
- kfree(adapter->ahw);
- adapter->ahw = NULL;
}
int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
@@ -1546,26 +1528,13 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
return 0;
}
-static int
-qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
-{
- adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry),
- GFP_KERNEL);
-
- if (adapter->msix_entries)
- return 0;
-
- dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n");
- return -ENOMEM;
-}
-
static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct qlcnic_adapter *adapter = NULL;
+ struct qlcnic_hardware_context *ahw;
int err;
- uint8_t revision_id;
uint8_t pci_using_dac;
char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
@@ -1589,10 +1558,23 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
pci_enable_pcie_error_reporting(pdev);
+ ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
+ if (!ahw)
+ goto err_out_free_res;
+
+ if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X)
+ ahw->hw_ops = &qlcnic_82xx_ops;
+ else
+ goto err_out_free_hw_res;
+
+ err = qlcnic_setup_pci_map(pdev, ahw);
+ if (err)
+ goto err_out_free_hw_res;
+
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) {
err = -ENOMEM;
- goto err_out_free_res;
+ goto err_out_iounmap;
}
SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -1600,13 +1582,13 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
+ adapter->ahw = ahw;
if (qlcnic_alloc_adapter_resources(adapter))
goto err_out_free_netdev;
adapter->dev_rst_time = jiffies;
- revision_id = pdev->revision;
- adapter->ahw->revision_id = revision_id;
+ adapter->ahw->revision_id = pdev->revision;
adapter->mac_learn = qlcnic_mac_learn;
rwlock_init(&adapter->ahw->crb_lock);
@@ -1615,9 +1597,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list);
- err = qlcnic_setup_pci_map(adapter);
- if (err)
- goto err_out_free_hw;
+ qlcnic_check_vf(adapter);
/* This will be reset for mezz cards */
adapter->portnum = adapter->ahw->pci_func;
@@ -1625,12 +1605,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = qlcnic_get_board_info(adapter);
if (err) {
dev_err(&pdev->dev, "Error getting board config info.\n");
- goto err_out_iounmap;
+ goto err_out_free_hw;
}
err = qlcnic_setup_idc_param(adapter);
if (err)
- goto err_out_iounmap;
+ goto err_out_free_hw;
adapter->flags |= QLCNIC_NEED_FLR;
@@ -1645,21 +1625,17 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_warn(&pdev->dev, "failed to read mac addr\n");
if (adapter->portnum == 0) {
- get_brd_name(adapter, brd_name);
+ qlcnic_get_brd_name(adapter, brd_name);
pr_info("%s: %s Board Chip rev 0x%x\n",
module_name(THIS_MODULE),
brd_name, adapter->ahw->revision_id);
}
- qlcnic_clear_stats(adapter);
-
- err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques);
- if (err)
+ err = ahw->hw_ops->setup_intr(adapter);
+ if (err == -ENOMEM)
goto err_out_decr_ref;
- qlcnic_setup_intr(adapter);
-
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
if (err)
goto err_out_disable_msi;
@@ -1693,15 +1669,18 @@ err_out_disable_msi:
err_out_decr_ref:
qlcnic_clr_all_drv_state(adapter, 0);
-err_out_iounmap:
- qlcnic_cleanup_pci_map(adapter);
-
err_out_free_hw:
qlcnic_free_adapter_resources(adapter);
err_out_free_netdev:
free_netdev(netdev);
+err_out_iounmap:
+ qlcnic_cleanup_pci_map(ahw);
+
+err_out_free_hw_res:
+ kfree(ahw);
+
err_out_free_res:
pci_release_regions(pdev);
@@ -1727,12 +1706,14 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
{
struct qlcnic_adapter *adapter;
struct net_device *netdev;
+ struct qlcnic_hardware_context *ahw;
adapter = pci_get_drvdata(pdev);
if (adapter == NULL)
return;
netdev = adapter->netdev;
+ ahw = adapter->ahw;
qlcnic_cancel_fw_work(adapter);
@@ -1756,7 +1737,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
qlcnic_remove_diag_entries(adapter);
- qlcnic_cleanup_pci_map(adapter);
+ qlcnic_cleanup_pci_map(ahw);
qlcnic_release_firmware(adapter);
@@ -1766,6 +1747,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
qlcnic_free_adapter_resources(adapter);
+ kfree(ahw);
free_netdev(netdev);
}
static int __qlcnic_shutdown(struct pci_dev *pdev)
@@ -2735,12 +2717,13 @@ static int
qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
{
int act, state, active_mask;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
- active_mask = (~(1 << (adapter->ahw->pci_func * 4)));
+ active_mask = (~(1 << (ahw->pci_func * 4)));
act = act & active_mask;
}
@@ -2857,6 +2840,7 @@ qlcnic_fwinit_work(struct work_struct *work)
struct qlcnic_adapter, fw_work.work);
u32 dev_state = 0xf;
u32 val;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
if (qlcnic_api_lock(adapter))
goto err_ret;
@@ -2906,7 +2890,7 @@ skip_ack_check:
qlcnic_api_unlock(adapter);
rtnl_lock();
- if (adapter->ahw->fw_dump.enable &&
+ if (ahw->fw_dump.enable &&
(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
QLCDB(adapter, DRV, "Take FW dump\n");
qlcnic_dump_fw(adapter);
@@ -3064,7 +3048,8 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
qlcnic_idc_debug_info(adapter, 0);
}
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
+ QLCNIC_DEV_NPAR_NON_OPER);
qlcnic_api_unlock(adapter);
}
@@ -3266,6 +3251,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
int err, first_func;
struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
pdev->error_state = pci_channel_io_normal;
@@ -3295,7 +3281,9 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
return err;
qlcnic_clr_drv_state(adapter);
- qlcnic_setup_intr(adapter);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+ err = ahw->hw_ops->setup_intr(adapter);
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
@@ -3510,6 +3498,8 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
__qlcnic_down(adapter, netdev);
qlcnic_detach(adapter);
qlcnic_teardown_intr(adapter);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
if (qlcnic_enable_msix(adapter, data)) {
netdev_info(netdev, "failed setting max_rss; rss disabled\n");
@@ -3662,21 +3652,13 @@ qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
{
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u32 data;
- u64 qmdata;
int ret;
ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
if (ret != 0)
return ret;
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
- memcpy(buf, &qmdata, size);
- } else {
- data = QLCRD32(adapter, offset);
- memcpy(buf, &data, size);
- }
+ adapter->ahw->hw_ops->read_crb(adapter, buf, offset, size);
return size;
}
@@ -3687,21 +3669,13 @@ qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
{
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- u32 data;
- u64 qmdata;
int ret;
ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
if (ret != 0)
return ret;
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- memcpy(&qmdata, buf, size);
- qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
- } else {
- memcpy(&data, buf, size);
- QLCWR32(adapter, offset, data);
- }
+ adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size);
return size;
}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 02/15] qlcnic: Refactoring - Tx/Rx code path separation
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Anirban Chakraborty
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Move data path code to a new file
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 6 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 16 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 638 ------------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 1195 ++++++++++++++++++++++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 596 +-----------
6 files changed, 1219 insertions(+), 1234 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index ddba83e..a26ee17 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -5,4 +5,4 @@
obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
- qlcnic_ethtool.o qlcnic_ctx.o
+ qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index fec4b89..53ccbf9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1483,6 +1483,7 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
int qlcnic_dump_fw(struct qlcnic_adapter *);
void qlcnic_get_ocm_win(struct qlcnic_hardware_context *);
+void qlcnic_get_func_no(struct qlcnic_adapter *);
/* Functions from qlcnic_init.c */
int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
@@ -1523,7 +1524,6 @@ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
-void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
@@ -1535,7 +1535,6 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
@@ -1558,6 +1557,8 @@ void qlcnic_dev_request_reset(struct qlcnic_adapter *);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
int qlcnic_setup_intr(struct qlcnic_adapter *);
+int qlcnic_poll(struct napi_struct *, int);
+int qlcnic_rx_poll(struct napi_struct *, int);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
@@ -1643,6 +1644,7 @@ struct qlcnic_hardware_ops {
int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
int (*setup_intr) (struct qlcnic_adapter *);
void (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+ void (*get_func_no) (struct qlcnic_adapter *);
};
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 14ddd27..c9be09b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -657,10 +657,12 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
/* Get MAC address of a NIC partition */
+
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
{
- int err;
+ int err, i;
struct qlcnic_cmd_args cmd;
+ u32 mac_low, mac_high;
memset(&cmd, 0, sizeof(cmd));
cmd.req.arg1 = adapter->ahw->pci_func | BIT_8;
@@ -669,9 +671,15 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
- if (err == QLCNIC_RCODE_SUCCESS)
- qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
- else {
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ mac_low = cmd.rsp.arg1;
+ mac_high = cmd.rsp.arg2;
+
+ for (i = 0; i < 2; i++)
+ mac[i] = (u8) (mac_high >> ((1 - i) * 8));
+ for (i = 2; i < 6; i++)
+ mac[i] = (u8) (mac_low >> ((5 - i) * 8));
+ } else {
dev_err(&adapter->pdev->dev,
"Failed to get mac address%d\n", err);
err = -EIO;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 0bcda9c..8abd7d9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -5,10 +5,6 @@
* See LICENSE.qlcnic for copyright and licensing details.
*/
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/if_vlan.h>
#include "qlcnic.h"
struct crb_addr_pair {
@@ -25,10 +21,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
#define QLCNIC_ADDR_ERROR (0xffffffff)
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring);
-
static int
qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
@@ -1324,633 +1316,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter)
release_firmware(adapter->fw);
adapter->fw = NULL;
}
-
-static void
-qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
- struct qlcnic_fw_msg *msg)
-{
- u32 cable_OUI;
- u16 cable_len;
- u16 link_speed;
- u8 link_status, module, duplex, autoneg;
- u8 lb_status = 0;
- struct net_device *netdev = adapter->netdev;
-
- adapter->has_link_events = 1;
-
- cable_OUI = msg->body[1] & 0xffffffff;
- cable_len = (msg->body[1] >> 32) & 0xffff;
- link_speed = (msg->body[1] >> 48) & 0xffff;
-
- link_status = msg->body[2] & 0xff;
- duplex = (msg->body[2] >> 16) & 0xff;
- autoneg = (msg->body[2] >> 24) & 0xff;
- lb_status = (msg->body[2] >> 32) & 0x3;
-
- module = (msg->body[2] >> 8) & 0xff;
- if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
- dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, "
- "length %d\n", cable_OUI, cable_len);
- else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
- dev_info(&netdev->dev, "unsupported cable length %d\n",
- cable_len);
-
- if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
- lb_status == QLCNIC_ELB_MODE))
- adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
-
- qlcnic_advert_link_change(adapter, link_status);
-
- if (duplex == LINKEVENT_FULL_DUPLEX)
- adapter->link_duplex = DUPLEX_FULL;
- else
- adapter->link_duplex = DUPLEX_HALF;
-
- adapter->module_type = module;
- adapter->link_autoneg = autoneg;
-
- if (link_status) {
- adapter->link_speed = link_speed;
- } else {
- adapter->link_speed = SPEED_UNKNOWN;
- adapter->link_duplex = DUPLEX_UNKNOWN;
- }
-}
-
-static void
-qlcnic_handle_fw_message(int desc_cnt, int index,
- struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_fw_msg msg;
- struct status_desc *desc;
- struct qlcnic_adapter *adapter;
- struct device *dev;
- int i = 0, opcode, ret;
-
- while (desc_cnt > 0 && i < 8) {
- desc = &sds_ring->desc_head[index];
- msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
- msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
-
- index = get_next_index(index, sds_ring->num_desc);
- desc_cnt--;
- }
-
- adapter = sds_ring->adapter;
- dev = &adapter->pdev->dev;
- opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
-
- switch (opcode) {
- case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
- qlcnic_handle_linkevent(adapter, &msg);
- break;
- case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
- ret = (u32)(msg.body[1]);
- switch (ret) {
- case 0:
- adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
- break;
- case 1:
- dev_info(dev, "loopback already in progress\n");
- adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
- break;
- case 2:
- dev_info(dev, "loopback cable is not connected\n");
- adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
- break;
- default:
- dev_info(dev, "loopback configure request failed,"
- " ret %x\n", ret);
- adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static int
-qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring,
- struct qlcnic_rx_buffer *buffer)
-{
- struct sk_buff *skb;
- dma_addr_t dma;
- struct pci_dev *pdev = adapter->pdev;
-
- skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
- if (!skb) {
- adapter->stats.skb_alloc_failure++;
- return -ENOMEM;
- }
-
- skb_reserve(skb, NET_IP_ALIGN);
-
- dma = pci_map_single(pdev, skb->data,
- rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-
- if (pci_dma_mapping_error(pdev, dma)) {
- adapter->stats.rx_dma_map_error++;
- dev_kfree_skb_any(skb);
- return -ENOMEM;
- }
-
- buffer->skb = skb;
- buffer->dma = dma;
-
- return 0;
-}
-
-static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
-{
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- if (unlikely(buffer->skb == NULL)) {
- WARN_ON(1);
- return NULL;
- }
-
- pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
-
- skb = buffer->skb;
-
- if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
- (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
- adapter->stats.csummed++;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else {
- skb_checksum_none_assert(skb);
- }
-
- buffer->skb = NULL;
-
- return skb;
-}
-
-static inline int
-qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
- u16 *vlan_tag)
-{
- struct ethhdr *eth_hdr;
-
- if (!__vlan_get_tag(skb, vlan_tag)) {
- eth_hdr = (struct ethhdr *) skb->data;
- memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
- skb_pull(skb, VLAN_HLEN);
- }
- if (!adapter->pvid)
- return 0;
-
- if (*vlan_tag == adapter->pvid) {
- /* Outer vlan tag. Packet should follow non-vlan path */
- *vlan_tag = 0xffff;
- return 0;
- }
- if (adapter->flags & QLCNIC_TAGGING_ENABLED)
- return 0;
-
- return -EINVAL;
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_rcv(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0)
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum, pkt_offset;
- u16 vid = 0xffff;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_sts_refhandle(sts_data0);
- if (unlikely(index >= rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- length = qlcnic_get_sts_totallength(sts_data0);
- cksum = qlcnic_get_sts_status(sts_data0);
- pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
- if (!skb)
- return buffer;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (pkt_offset)
- skb_pull(skb, pkt_offset);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
-
- napi_gro_receive(&sds_ring->napi, skb);
-
- adapter->stats.rx_pkts++;
- adapter->stats.rxbytes += length;
-
- return buffer;
-}
-
-#define QLC_TCP_HDR_SIZE 20
-#define QLC_TCP_TS_OPTION_SIZE 12
-#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_lro(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0, u64 sts_data1)
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- struct iphdr *iph;
- struct tcphdr *th;
- bool push, timestamp;
- int l2_hdr_offset, l4_hdr_offset;
- int index;
- u16 lro_length, length, data_offset;
- u32 seq_number;
- u16 vid = 0xffff;
-
- if (unlikely(ring > adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_lro_sts_refhandle(sts_data0);
- if (unlikely(index > rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
- lro_length = qlcnic_get_lro_sts_length(sts_data0);
- l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
- l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
- push = qlcnic_get_lro_sts_push_flag(sts_data0);
- seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
- if (!skb)
- return buffer;
-
- if (timestamp)
- data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
- else
- data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
-
- skb_put(skb, lro_length + data_offset);
-
- skb_pull(skb, l2_hdr_offset);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- iph = (struct iphdr *)skb->data;
- th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-
- length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
- iph->tot_len = htons(length);
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
- th->psh = push;
- th->seq = htonl(seq_number);
-
- length = skb->len;
-
- if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
- skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
- netif_receive_skb(skb);
-
- adapter->stats.lro_pkts++;
- adapter->stats.lrobytes += length;
-
- return buffer;
-}
-
-int
-qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct list_head *cur;
- struct status_desc *desc;
- struct qlcnic_rx_buffer *rxbuf;
- u64 sts_data0, sts_data1;
-
- int count = 0;
- int opcode, ring, desc_cnt;
- u32 consumer = sds_ring->consumer;
-
- while (count < max) {
- desc = &sds_ring->desc_head[consumer];
- sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
- if (!(sts_data0 & STATUS_OWNER_HOST))
- break;
-
- desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
- opcode = qlcnic_get_sts_opcode(sts_data0);
-
- switch (opcode) {
- case QLCNIC_RXPKT_DESC:
- case QLCNIC_OLD_RXPKT_DESC:
- case QLCNIC_SYN_OFFLOAD:
- ring = qlcnic_get_sts_type(sts_data0);
- rxbuf = qlcnic_process_rcv(adapter, sds_ring,
- ring, sts_data0);
- break;
- case QLCNIC_LRO_DESC:
- ring = qlcnic_get_lro_sts_type(sts_data0);
- sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
- rxbuf = qlcnic_process_lro(adapter, sds_ring,
- ring, sts_data0, sts_data1);
- break;
- case QLCNIC_RESPONSE_DESC:
- qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
- default:
- goto skip;
- }
-
- WARN_ON(desc_cnt > 1);
-
- if (likely(rxbuf))
- list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
- else
- adapter->stats.null_rxbuf++;
-
-skip:
- for (; desc_cnt > 0; desc_cnt--) {
- desc = &sds_ring->desc_head[consumer];
- desc->status_desc_data[0] =
- cpu_to_le64(STATUS_OWNER_PHANTOM);
- consumer = get_next_index(consumer, sds_ring->num_desc);
- }
- count++;
- }
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- struct qlcnic_host_rds_ring *rds_ring =
- &adapter->recv_ctx->rds_rings[ring];
-
- if (!list_empty(&sds_ring->free_list[ring])) {
- list_for_each(cur, &sds_ring->free_list[ring]) {
- rxbuf = list_entry(cur,
- struct qlcnic_rx_buffer, list);
- qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
- }
- spin_lock(&rds_ring->lock);
- list_splice_tail_init(&sds_ring->free_list[ring],
- &rds_ring->free_list);
- spin_unlock(&rds_ring->lock);
- }
-
- qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
- }
-
- if (count) {
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
- }
-
- return count;
-}
-
-void
-qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
-{
- struct rcv_desc *pdesc;
- struct qlcnic_rx_buffer *buffer;
- int count = 0;
- u32 producer;
- struct list_head *head;
-
- producer = rds_ring->producer;
-
- head = &rds_ring->free_list;
- while (!list_empty(head)) {
-
- buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
- if (!buffer->skb) {
- if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
- break;
- }
-
- count++;
- list_del(&buffer->list);
-
- /* make a rcv descriptor */
- pdesc = &rds_ring->desc_head[producer];
- pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-
- producer = get_next_index(producer, rds_ring->num_desc);
- }
-
- if (count) {
- rds_ring->producer = producer;
- writel((producer-1) & (rds_ring->num_desc-1),
- rds_ring->crb_rcv_producer);
- }
-}
-
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
-{
- struct rcv_desc *pdesc;
- struct qlcnic_rx_buffer *buffer;
- int count = 0;
- uint32_t producer;
- struct list_head *head;
-
- if (!spin_trylock(&rds_ring->lock))
- return;
-
- producer = rds_ring->producer;
-
- head = &rds_ring->free_list;
- while (!list_empty(head)) {
-
- buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
- if (!buffer->skb) {
- if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
- break;
- }
-
- count++;
- list_del(&buffer->list);
-
- /* make a rcv descriptor */
- pdesc = &rds_ring->desc_head[producer];
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
- pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-
- producer = get_next_index(producer, rds_ring->num_desc);
- }
-
- if (count) {
- rds_ring->producer = producer;
- writel((producer - 1) & (rds_ring->num_desc - 1),
- rds_ring->crb_rcv_producer);
- }
- spin_unlock(&rds_ring->lock);
-}
-
-static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
-{
- int i;
- unsigned char *data = skb->data;
-
- printk(KERN_INFO "\n");
- for (i = 0; i < skb->len; i++) {
- QLCDB(adapter, DRV, "%02x ", data[i]);
- if ((i & 0x0f) == 8)
- printk(KERN_INFO "\n");
- }
-}
-
-void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data0)
-{
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum, pkt_offset;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_get_sts_refhandle(sts_data0);
- length = qlcnic_get_sts_totallength(sts_data0);
- if (unlikely(index >= rds_ring->num_desc))
- return;
-
- cksum = qlcnic_get_sts_status(sts_data0);
- pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
- if (!skb)
- return;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (pkt_offset)
- skb_pull(skb, pkt_offset);
-
- if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
- adapter->diag_cnt++;
- else
- dump_skb(skb, adapter);
-
- dev_kfree_skb_any(skb);
- adapter->stats.rx_pkts++;
- adapter->stats.rxbytes += length;
-
- return;
-}
-
-void
-qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct status_desc *desc;
- u64 sts_data0;
- int ring, opcode, desc_cnt;
-
- u32 consumer = sds_ring->consumer;
-
- desc = &sds_ring->desc_head[consumer];
- sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
- if (!(sts_data0 & STATUS_OWNER_HOST))
- return;
-
- desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
- opcode = qlcnic_get_sts_opcode(sts_data0);
- switch (opcode) {
- case QLCNIC_RESPONSE_DESC:
- qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
- break;
- default:
- ring = qlcnic_get_sts_type(sts_data0);
- qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
- break;
- }
-
- for (; desc_cnt > 0; desc_cnt--) {
- desc = &sds_ring->desc_head[consumer];
- desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
- consumer = get_next_index(consumer, sds_ring->num_desc);
- }
-
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
-}
-
-void
-qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
- u8 alt_mac, u8 *mac)
-{
- u32 mac_low, mac_high;
- int i;
-
- mac_low = off1;
- mac_high = off2;
-
- if (alt_mac) {
- mac_low |= (mac_low >> 16) | (mac_high << 16);
- mac_high >>= 16;
- }
-
- for (i = 0; i < 2; i++)
- mac[i] = (u8)(mac_high >> ((1 - i) * 8));
- for (i = 2; i < 6; i++)
- mac[i] = (u8)(mac_low >> ((5 - i) * 8));
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
new file mode 100644
index 0000000..8f5ee9f
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -0,0 +1,1195 @@
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+
+#include "qlcnic.h"
+#include "qlcnic_hw.h"
+
+static void
+qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring);
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+ u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+{
+ struct cmd_desc_type0 *hwdesc;
+ struct qlcnic_nic_req *req;
+ struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
+ u32 producer;
+ u64 word;
+
+ producer = tx_ring->producer;
+ hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+ req = (struct qlcnic_nic_req *)hwdesc;
+ memset(req, 0, sizeof(struct qlcnic_nic_req));
+ req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+ word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+ req->req_hdr = cpu_to_le64(word);
+
+ mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+ mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+ memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+ vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+ vlan_req->vlan_id = vlan_id;
+
+ tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+ smp_mb();
+}
+
+#define QLCNIC_MAC_HASH(MAC)\
+ ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+static void
+qlcnic_send_filter(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
+{
+ struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct qlcnic_filter *fil, *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ u64 src_addr = 0;
+ __le16 vlan_id = 0;
+ u8 hindex;
+
+ if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
+ return;
+
+ if (adapter->fhash.fnum >= adapter->fhash.fmax)
+ return;
+
+ /* Only NPAR capable devices support vlan based learning*/
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ vlan_id = first_desc->vlan_TCI;
+ memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+ hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+ head = &(adapter->fhash.fhead[hindex]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+ tmp_fil->vlan_id == vlan_id) {
+
+ if (jiffies >
+ (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
+ qlcnic_change_filter(adapter, src_addr, vlan_id,
+ tx_ring);
+ tmp_fil->ftime = jiffies;
+ return;
+ }
+ }
+
+ fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+ if (!fil)
+ return;
+
+ qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+ fil->ftime = jiffies;
+ fil->vlan_id = vlan_id;
+ memcpy(fil->faddr, &src_addr, ETH_ALEN);
+ spin_lock(&adapter->mac_learn_lock);
+ hlist_add_head(&(fil->fnode), head);
+ adapter->fhash.fnum++;
+ spin_unlock(&adapter->mac_learn_lock);
+}
+
+static int
+qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
+{
+ u8 opcode = 0, hdr_len = 0;
+ u16 flags = 0, vlan_tci = 0;
+ int copied, offset, copy_len;
+ struct cmd_desc_type0 *hwdesc;
+ struct vlan_ethhdr *vh;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+ u16 protocol = ntohs(skb->protocol);
+ u32 producer = tx_ring->producer;
+
+ if (protocol == ETH_P_8021Q) {
+ vh = (struct vlan_ethhdr *)skb->data;
+ flags = FLAGS_VLAN_TAGGED;
+ vlan_tci = vh->h_vlan_TCI;
+ } else if (vlan_tx_tag_present(skb)) {
+ flags = FLAGS_VLAN_OOB;
+ vlan_tci = vlan_tx_tag_get(skb);
+ }
+ if (unlikely(adapter->pvid)) {
+ if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+ return -EIO;
+ if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+ goto set_flags;
+
+ flags = FLAGS_VLAN_OOB;
+ vlan_tci = adapter->pvid;
+ }
+set_flags:
+ qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
+ qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ if (*(skb->data) & BIT_0) {
+ flags |= BIT_0;
+ memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
+ }
+ opcode = TX_ETHER_PKT;
+ if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
+
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ first_desc->total_hdr_length = hdr_len;
+
+ opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
+
+ /* For LSO, we need to copy the MAC/IP/TCP headers into
+ * the descriptor ring */
+ copied = 0;
+ offset = 2;
+
+ if (flags & FLAGS_VLAN_OOB) {
+ first_desc->total_hdr_length += VLAN_HLEN;
+ first_desc->tcp_hdr_offset = VLAN_HLEN;
+ first_desc->ip_hdr_offset = VLAN_HLEN;
+ /* Only in case of TSO on vlan device */
+ flags |= FLAGS_VLAN_TAGGED;
+
+ /* Create a TSO vlan header template for firmware */
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) -
+ offset, hdr_len + VLAN_HLEN);
+
+ vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
+ skb_copy_from_linear_data(skb, vh, 12);
+ vh->h_vlan_proto = htons(ETH_P_8021Q);
+ vh->h_vlan_TCI = htons(vlan_tci);
+
+ skb_copy_from_linear_data_offset(skb, 12,
+ (char *)vh + 16, copy_len - 16);
+
+ copied = copy_len - VLAN_HLEN;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ while (copied < hdr_len) {
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) -
+ offset, (hdr_len - copied));
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ skb_copy_from_linear_data_offset(skb, copied,
+ (char *) hwdesc + offset, copy_len);
+
+ copied += copy_len;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ tx_ring->producer = producer;
+ smp_mb();
+ adapter->stats.lso_frames++;
+
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 l4proto;
+
+ if (protocol == ETH_P_IP) {
+ l4proto = ip_hdr(skb)->protocol;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCP_PKT;
+ else if (l4proto == IPPROTO_UDP)
+ opcode = TX_UDP_PKT;
+ } else if (protocol == ETH_P_IPV6) {
+ l4proto = ipv6_hdr(skb)->nexthdr;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCPV6_PKT;
+ else if (l4proto == IPPROTO_UDP)
+ opcode = TX_UDPV6_PKT;
+ }
+ }
+ first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+ first_desc->ip_hdr_offset += skb_network_offset(skb);
+ qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ return 0;
+}
+
+static int
+qlcnic_map_tx_skb(struct pci_dev *pdev,
+ struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
+{
+ struct qlcnic_skb_frag *nf;
+ struct skb_frag_struct *frag;
+ int i, nr_frags;
+ dma_addr_t map;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ nf = &pbuf->frag_array[0];
+
+ map = pci_map_single(pdev, skb->data,
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, map))
+ goto out_err;
+
+ nf->dma = map;
+ nf->length = skb_headlen(skb);
+
+ for (i = 0; i < nr_frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ nf = &pbuf->frag_array[i+1];
+
+ map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&pdev->dev, map))
+ goto unwind;
+
+ nf->dma = map;
+ nf->length = frag->size;
+ }
+
+ return 0;
+
+unwind:
+ while (--i >= 0) {
+ nf = &pbuf->frag_array[i+1];
+ pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+ }
+
+ nf = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+
+out_err:
+ return -ENOMEM;
+}
+
+static void
+qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
+ struct qlcnic_cmd_buffer *pbuf)
+{
+ struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
+ int nr_frags = skb_shinfo(skb)->nr_frags;
+ int i;
+
+ for (i = 0; i < nr_frags; i++) {
+ nf = &pbuf->frag_array[i+1];
+ pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+ }
+
+ nf = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+ pbuf->skb = NULL;
+}
+
+static inline void
+qlcnic_clear_cmddesc(u64 *desc)
+{
+ desc[0] = 0ULL;
+ desc[2] = 0ULL;
+ desc[7] = 0ULL;
+}
+
+netdev_tx_t
+qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+ struct qlcnic_cmd_buffer *pbuf;
+ struct qlcnic_skb_frag *buffrag;
+ struct cmd_desc_type0 *hwdesc, *first_desc;
+ struct pci_dev *pdev;
+ struct ethhdr *phdr;
+ int delta = 0;
+ int i, k;
+
+ u32 producer;
+ int frag_count;
+ u32 num_txd = tx_ring->num_desc;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ netif_stop_queue(netdev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (adapter->flags & QLCNIC_MACSPOOF) {
+ phdr = (struct ethhdr *)skb->data;
+ if (compare_ether_addr(phdr->h_source,
+ adapter->mac_addr))
+ goto drop_packet;
+ }
+
+ frag_count = skb_shinfo(skb)->nr_frags + 1;
+ /* 14 frags supported for normal packet and
+ * 32 frags supported for TSO packet
+ */
+ if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+
+ for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+ delta += skb_shinfo(skb)->frags[i].size;
+
+ if (!__pskb_pull_tail(skb, delta))
+ goto drop_packet;
+
+ frag_count = 1 + skb_shinfo(skb)->nr_frags;
+ }
+
+ if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
+ netif_stop_queue(netdev);
+ if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
+ netif_start_queue(netdev);
+ else {
+ adapter->stats.xmit_off++;
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ producer = tx_ring->producer;
+ pbuf = &tx_ring->cmd_buf_arr[producer];
+
+ pdev = adapter->pdev;
+
+ first_desc = hwdesc = &tx_ring->desc_head[producer];
+ qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+ if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
+ adapter->stats.tx_dma_map_error++;
+ goto drop_packet;
+ }
+
+ pbuf->skb = skb;
+ pbuf->frag_count = frag_count;
+
+ qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
+ qlcnic_set_tx_port(first_desc, adapter->portnum);
+
+ for (i = 0; i < frag_count; i++) {
+
+ k = i % 4;
+
+ if ((k == 0) && (i > 0)) {
+ /* move to next desc.*/
+ producer = get_next_index(producer, num_txd);
+ hwdesc = &tx_ring->desc_head[producer];
+ qlcnic_clear_cmddesc((u64 *)hwdesc);
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+ }
+
+ buffrag = &pbuf->frag_array[i];
+
+ hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
+ switch (k) {
+ case 0:
+ hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+ break;
+ case 1:
+ hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
+ break;
+ case 2:
+ hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
+ break;
+ case 3:
+ hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
+ break;
+ }
+ }
+
+ tx_ring->producer = get_next_index(producer, num_txd);
+ smp_mb();
+
+ if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
+ goto unwind_buff;
+
+ if (adapter->mac_learn)
+ qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
+ adapter->stats.txbytes += skb->len;
+ adapter->stats.xmitcalled++;
+
+ qlcnic_update_cmd_producer(adapter, tx_ring);
+
+ return NETDEV_TX_OK;
+
+unwind_buff:
+ qlcnic_unmap_buffers(pdev, skb, pbuf);
+drop_packet:
+ adapter->stats.txdropped++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (adapter->ahw->linkup && !linkup) {
+ netdev_info(netdev, "NIC Link is down\n");
+ adapter->ahw->linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else if (!adapter->ahw->linkup && linkup) {
+ netdev_info(netdev, "NIC Link is up\n");
+ adapter->ahw->linkup = 1;
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
+static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+{
+ u32 sw_consumer, hw_consumer;
+ int count = 0, i;
+ struct qlcnic_cmd_buffer *buffer;
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_skb_frag *frag;
+ int done;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+ if (!spin_trylock(&adapter->tx_clean_lock))
+ return 1;
+
+ sw_consumer = tx_ring->sw_consumer;
+ hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+ while (sw_consumer != hw_consumer) {
+ buffer = &tx_ring->cmd_buf_arr[sw_consumer];
+ if (buffer->skb) {
+ frag = &buffer->frag_array[0];
+ pci_unmap_single(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
+ for (i = 1; i < buffer->frag_count; i++) {
+ frag++;
+ pci_unmap_page(pdev, frag->dma, frag->length,
+ PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
+ }
+
+ adapter->stats.xmitfinished++;
+ dev_kfree_skb_any(buffer->skb);
+ buffer->skb = NULL;
+ }
+
+ sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
+ if (++count >= MAX_STATUS_HANDLE)
+ break;
+ }
+
+ if (count && netif_running(netdev)) {
+ tx_ring->sw_consumer = sw_consumer;
+
+ smp_mb();
+
+ if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+ if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+ netif_wake_queue(netdev);
+ adapter->stats.xmit_on++;
+ }
+ }
+ adapter->tx_timeo_cnt = 0;
+ }
+ /*
+ * If everything is freed up to consumer then check if the ring is full
+ * If the ring is full then check if more needs to be freed and
+ * schedule the call back again.
+ *
+ * This happens when there are 2 CPUs. One could be freeing and the
+ * other filling it. If the ring is full when we get out of here and
+ * the card has already interrupted the host then the host can miss the
+ * interrupt.
+ *
+ * There is still a possible race condition and the host could miss an
+ * interrupt. The card has to take care of this.
+ */
+ hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+ done = (sw_consumer == hw_consumer);
+ spin_unlock(&adapter->tx_clean_lock);
+
+ return done;
+}
+
+int qlcnic_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+ int tx_complete;
+ int work_done;
+
+ tx_complete = qlcnic_process_cmd_ring(adapter);
+
+ work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+ if ((work_done < budget) && tx_complete) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
+ }
+
+ return work_done;
+}
+
+int qlcnic_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ int work_done;
+
+ work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+ if (work_done < budget) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
+ }
+
+ return work_done;
+}
+
+static void
+qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
+ struct qlcnic_fw_msg *msg)
+{
+ u32 cable_OUI;
+ u16 cable_len;
+ u16 link_speed;
+ u8 link_status, module, duplex, autoneg;
+ u8 lb_status = 0;
+ struct net_device *netdev = adapter->netdev;
+
+ adapter->has_link_events = 1;
+
+ cable_OUI = msg->body[1] & 0xffffffff;
+ cable_len = (msg->body[1] >> 32) & 0xffff;
+ link_speed = (msg->body[1] >> 48) & 0xffff;
+
+ link_status = msg->body[2] & 0xff;
+ duplex = (msg->body[2] >> 16) & 0xff;
+ autoneg = (msg->body[2] >> 24) & 0xff;
+ lb_status = (msg->body[2] >> 32) & 0x3;
+
+ module = (msg->body[2] >> 8) & 0xff;
+ if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
+ dev_info(&netdev->dev,
+ "unsupported cable: OUI 0x%x, length %d\n",
+ cable_OUI, cable_len);
+ else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
+ dev_info(&netdev->dev, "unsupported cable length %d\n",
+ cable_len);
+
+ if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+ lb_status == QLCNIC_ELB_MODE))
+ adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
+ qlcnic_advert_link_change(adapter, link_status);
+
+ if (duplex == LINKEVENT_FULL_DUPLEX)
+ adapter->link_duplex = DUPLEX_FULL;
+ else
+ adapter->link_duplex = DUPLEX_HALF;
+
+ adapter->module_type = module;
+ adapter->link_autoneg = autoneg;
+ adapter->link_speed = link_speed;
+}
+
+static void
+qlcnic_handle_fw_message(int desc_cnt, int index,
+ struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_fw_msg msg;
+ struct status_desc *desc;
+ struct qlcnic_adapter *adapter;
+ struct device *dev;
+ int i = 0, opcode, ret;
+
+ while (desc_cnt > 0 && i < 8) {
+ desc = &sds_ring->desc_head[index];
+ msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+ msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+ index = get_next_index(index, sds_ring->num_desc);
+ desc_cnt--;
+ }
+
+ adapter = sds_ring->adapter;
+ dev = &adapter->pdev->dev;
+ opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
+ switch (opcode) {
+ case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+ qlcnic_handle_linkevent(adapter, &msg);
+ break;
+ case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+ ret = (u32)(msg.body[1]);
+ switch (ret) {
+ case 0:
+ adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+ break;
+ case 1:
+ dev_info(dev, "loopback already in progress\n");
+ adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+ break;
+ case 2:
+ dev_info(dev, "loopback cable is not connected\n");
+ adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+ break;
+ default:
+ dev_info(dev,
+ "configure loopback request failed, ret %x\n",
+ ret);
+ adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring,
+ struct qlcnic_rx_buffer *buffer)
+{
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ struct pci_dev *pdev = adapter->pdev;
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
+ if (!skb) {
+ adapter->stats.skb_alloc_failure++;
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ dma = pci_map_single(pdev, skb->data,
+ rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+
+ if (pci_dma_mapping_error(pdev, dma)) {
+ adapter->stats.rx_dma_map_error++;
+ dev_kfree_skb_any(skb);
+ return -ENOMEM;
+ }
+
+ buffer->skb = skb;
+ buffer->dma = dma;
+
+ return 0;
+}
+
+static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
+{
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ if (unlikely(buffer->skb == NULL)) {
+ WARN_ON(1);
+ return NULL;
+ }
+
+ pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+
+ skb = buffer->skb;
+
+ if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
+ (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
+ adapter->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else {
+ skb_checksum_none_assert(skb);
+ }
+
+ skb->dev = adapter->netdev;
+
+ buffer->skb = NULL;
+
+ return skb;
+}
+
+static inline int
+qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
+ u16 *vlan_tag)
+{
+ struct ethhdr *eth_hdr;
+
+ if (!__vlan_get_tag(skb, vlan_tag)) {
+ eth_hdr = (struct ethhdr *) skb->data;
+ memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+ skb_pull(skb, VLAN_HLEN);
+ }
+ if (!adapter->pvid)
+ return 0;
+
+ if (*vlan_tag == adapter->pvid) {
+ /* Outer vlan tag. Packet should follow non-vlan path */
+ *vlan_tag = 0xffff;
+ return 0;
+ }
+ if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+ return 0;
+
+ return -EINVAL;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_rcv(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ length = qlcnic_get_sts_totallength(sts_data0);
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return buffer;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+
+ napi_gro_receive(&sds_ring->napi, skb);
+
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return buffer;
+}
+
+#define QLC_TCP_HDR_SIZE 20
+#define QLC_TCP_TS_OPTION_SIZE 12
+#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_lro(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0, u64 sts_data1)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ bool push, timestamp;
+ int l2_hdr_offset, l4_hdr_offset;
+ int index;
+ u16 lro_length, length, data_offset;
+ u32 seq_number;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring > adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_lro_sts_refhandle(sts_data0);
+ if (unlikely(index > rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
+ lro_length = qlcnic_get_lro_sts_length(sts_data0);
+ l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
+ l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
+ push = qlcnic_get_lro_sts_push_flag(sts_data0);
+ seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return buffer;
+
+ if (timestamp)
+ data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+ else
+ data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+ skb_put(skb, lro_length + data_offset);
+
+ skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ iph = (struct iphdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+
+ length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+ iph->tot_len = htons(length);
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ th->psh = push;
+ th->seq = htonl(seq_number);
+
+ length = skb->len;
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+ netif_receive_skb(skb);
+
+ adapter->stats.lro_pkts++;
+ adapter->stats.lrobytes += length;
+
+ return buffer;
+}
+
+int
+qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct list_head *cur;
+ struct status_desc *desc;
+ struct qlcnic_rx_buffer *rxbuf;
+ u64 sts_data0, sts_data1;
+
+ int count = 0;
+ int opcode, ring, desc_cnt;
+ u32 consumer = sds_ring->consumer;
+
+ while (count < max) {
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ break;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+
+ switch (opcode) {
+ case QLCNIC_RXPKT_DESC:
+ case QLCNIC_OLD_RXPKT_DESC:
+ case QLCNIC_SYN_OFFLOAD:
+ ring = qlcnic_get_sts_type(sts_data0);
+ rxbuf = qlcnic_process_rcv(adapter, sds_ring,
+ ring, sts_data0);
+ break;
+ case QLCNIC_LRO_DESC:
+ ring = qlcnic_get_lro_sts_type(sts_data0);
+ sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+ rxbuf = qlcnic_process_lro(adapter, sds_ring,
+ ring, sts_data0, sts_data1);
+ break;
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ default:
+ goto skip;
+ }
+
+ WARN_ON(desc_cnt > 1);
+
+ if (likely(rxbuf))
+ list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+ else
+ adapter->stats.null_rxbuf++;
+
+skip:
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] =
+ cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+ count++;
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ struct qlcnic_host_rds_ring *rds_ring =
+ &adapter->recv_ctx->rds_rings[ring];
+
+ if (!list_empty(&sds_ring->free_list[ring])) {
+ list_for_each(cur, &sds_ring->free_list[ring]) {
+ rxbuf = list_entry(cur,
+ struct qlcnic_rx_buffer, list);
+ qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+ }
+ spin_lock(&rds_ring->lock);
+ list_splice_tail_init(&sds_ring->free_list[ring],
+ &rds_ring->free_list);
+ spin_unlock(&rds_ring->lock);
+ }
+
+ qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
+ }
+
+ if (count) {
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+ }
+
+ return count;
+}
+
+void
+qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring)
+{
+ struct rcv_desc *pdesc;
+ struct qlcnic_rx_buffer *buffer;
+ int count = 0;
+ u32 producer;
+ struct list_head *head;
+
+ producer = rds_ring->producer;
+
+ head = &rds_ring->free_list;
+ while (!list_empty(head)) {
+
+ buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+ if (!buffer->skb) {
+ if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+ break;
+ }
+
+ count++;
+ list_del(&buffer->list);
+
+ /* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+
+ producer = get_next_index(producer, rds_ring->num_desc);
+ }
+
+ if (count) {
+ rds_ring->producer = producer;
+ writel((producer-1) & (rds_ring->num_desc-1),
+ rds_ring->crb_rcv_producer);
+ }
+}
+
+static void
+qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *rds_ring)
+{
+ struct rcv_desc *pdesc;
+ struct qlcnic_rx_buffer *buffer;
+ int count = 0;
+ uint32_t producer;
+ struct list_head *head;
+
+ if (!spin_trylock(&rds_ring->lock))
+ return;
+
+ producer = rds_ring->producer;
+
+ head = &rds_ring->free_list;
+ while (!list_empty(head)) {
+
+ buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+ if (!buffer->skb) {
+ if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+ break;
+ }
+
+ count++;
+ list_del(&buffer->list);
+
+ /* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+ pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+
+ producer = get_next_index(producer, rds_ring->num_desc);
+ }
+
+ if (count) {
+ rds_ring->producer = producer;
+ writel((producer - 1) & (rds_ring->num_desc - 1),
+ rds_ring->crb_rcv_producer);
+ }
+ spin_unlock(&rds_ring->lock);
+}
+
+static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ pr_info("\n");
+ for (i = 0; i < skb->len; i++) {
+ QLCDB(adapter, DRV, "%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ pr_info("\n");
+ }
+}
+
+void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0)
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_get_sts_refhandle(sts_data0);
+ length = qlcnic_get_sts_totallength(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ cksum = qlcnic_get_sts_status(sts_data0);
+ pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->diag_cnt++;
+ else
+ dump_skb(skb, adapter);
+
+ dev_kfree_skb_any(skb);
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return;
+}
+
+void
+qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data0;
+ int ring, opcode, desc_cnt;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+ if (!(sts_data0 & STATUS_OWNER_HOST))
+ return;
+
+ desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+ opcode = qlcnic_get_sts_opcode(sts_data0);
+ switch (opcode) {
+ case QLCNIC_RESPONSE_DESC:
+ qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+ break;
+ default:
+ ring = qlcnic_get_sts_type(sts_data0);
+ qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
+ break;
+ }
+
+ for (; desc_cnt > 0; desc_cnt--) {
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ }
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
+
+void
+qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
+ u8 alt_mac, u8 *mac)
+{
+ u32 mac_low, mac_high;
+ int i;
+
+ mac_low = off1;
+ mac_high = off2;
+
+ if (alt_mac) {
+ mac_low |= (mac_low >> 16) | (mac_high << 16);
+ mac_high >>= 16;
+ }
+
+ for (i = 0; i < 2; i++)
+ mac[i] = (u8)(mac_high >> ((1 - i) * 8));
+ for (i = 2; i < 6; i++)
+ mac[i] = (u8)(mac_low >> ((5 - i) * 8));
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index ab10b1c..a5941c4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -67,8 +67,6 @@ static void qlcnic_fw_poll_work(struct work_struct *work);
static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay);
static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
-static int qlcnic_poll(struct napi_struct *napi, int budget);
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev);
#endif
@@ -131,21 +129,6 @@ static const u32 msi_tgt_status[8] = {
static const
struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
-static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
- writel(0, sds_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
-
- writel(0x1, sds_ring->crb_intr_mask);
-
- if (!QLCNIC_IS_MSI_FAMILY(adapter))
- writel(0xfbff, adapter->tgt_mask_reg);
-}
-
static int
qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
{
@@ -217,7 +200,7 @@ qlcnic_napi_enable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
napi_enable(&sds_ring->napi);
- qlcnic_enable_int(sds_ring);
+ QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
}
}
@@ -233,7 +216,7 @@ qlcnic_napi_disable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
- qlcnic_disable_int(sds_ring);
+ QLCNIC_DISABLE_INTR(sds_ring->crb_intr_mask);
napi_synchronize(&sds_ring->napi);
napi_disable(&sds_ring->napi);
}
@@ -332,6 +315,7 @@ static struct qlcnic_hardware_ops qlcnic_82xx_ops = {
.get_mac_address = qlcnic_get_mac_address,
.setup_intr = qlcnic_setup_intr,
.mbx_cmd = qlcnic_issue_cmd,
+ .get_func_no = qlcnic_get_func_no,
};
static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -539,10 +523,7 @@ err_lock:
static void
qlcnic_check_vf(struct qlcnic_adapter *adapter)
{
- void __iomem *msix_base_addr;
void __iomem *priv_op;
- u32 func;
- u32 msix_base;
u32 op_mode, priv_level;
struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -551,11 +532,7 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
QLCNIC_FW_API);
/* Find PCI function number */
- pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
- msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
- msix_base = readl(msix_base_addr);
- func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
- ahw->pci_func = func;
+ ahw->hw_ops->get_func_no(adapter);
/* Determine function privilege level */
priv_op = ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
@@ -1307,7 +1284,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
- qlcnic_disable_int(sds_ring);
+ QLCNIC_DISABLE_INTR(sds_ring->crb_intr_mask);
}
}
@@ -1398,7 +1375,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
- qlcnic_enable_int(sds_ring);
+ QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
}
}
@@ -1908,428 +1885,6 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
adapter->fhash.fmax = 0;
}
-static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
- u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
-{
- struct cmd_desc_type0 *hwdesc;
- struct qlcnic_nic_req *req;
- struct qlcnic_mac_req *mac_req;
- struct qlcnic_vlan_req *vlan_req;
- u32 producer;
- u64 word;
-
- producer = tx_ring->producer;
- hwdesc = &tx_ring->desc_head[tx_ring->producer];
-
- req = (struct qlcnic_nic_req *)hwdesc;
- memset(req, 0, sizeof(struct qlcnic_nic_req));
- req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
-
- word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
- req->req_hdr = cpu_to_le64(word);
-
- mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
- mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
- memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
-
- vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
- vlan_req->vlan_id = vlan_id;
-
- tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
- smp_mb();
-}
-
-#define QLCNIC_MAC_HASH(MAC)\
- ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
-
-static void
-qlcnic_send_filter(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring,
- struct cmd_desc_type0 *first_desc,
- struct sk_buff *skb)
-{
- struct ethhdr *phdr = (struct ethhdr *)(skb->data);
- struct qlcnic_filter *fil, *tmp_fil;
- struct hlist_node *tmp_hnode, *n;
- struct hlist_head *head;
- u64 src_addr = 0;
- __le16 vlan_id = 0;
- u8 hindex;
-
- if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
- return;
-
- if (adapter->fhash.fnum >= adapter->fhash.fmax)
- return;
-
- /* Only NPAR capable devices support vlan based learning*/
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
- vlan_id = first_desc->vlan_TCI;
- memcpy(&src_addr, phdr->h_source, ETH_ALEN);
- hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
- head = &(adapter->fhash.fhead[hindex]);
-
- hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
- if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
- tmp_fil->vlan_id == vlan_id) {
-
- if (jiffies >
- (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
- qlcnic_change_filter(adapter, src_addr, vlan_id,
- tx_ring);
- tmp_fil->ftime = jiffies;
- return;
- }
- }
-
- fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
- if (!fil)
- return;
-
- qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
-
- fil->ftime = jiffies;
- fil->vlan_id = vlan_id;
- memcpy(fil->faddr, &src_addr, ETH_ALEN);
- spin_lock(&adapter->mac_learn_lock);
- hlist_add_head(&(fil->fnode), head);
- adapter->fhash.fnum++;
- spin_unlock(&adapter->mac_learn_lock);
-}
-
-static int
-qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
- struct cmd_desc_type0 *first_desc,
- struct sk_buff *skb)
-{
- u8 opcode = 0, hdr_len = 0;
- u16 flags = 0, vlan_tci = 0;
- int copied, offset, copy_len;
- struct cmd_desc_type0 *hwdesc;
- struct vlan_ethhdr *vh;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
- u16 protocol = ntohs(skb->protocol);
- u32 producer = tx_ring->producer;
-
- if (protocol == ETH_P_8021Q) {
- vh = (struct vlan_ethhdr *)skb->data;
- flags = FLAGS_VLAN_TAGGED;
- vlan_tci = vh->h_vlan_TCI;
- protocol = ntohs(vh->h_vlan_encapsulated_proto);
- } else if (vlan_tx_tag_present(skb)) {
- flags = FLAGS_VLAN_OOB;
- vlan_tci = vlan_tx_tag_get(skb);
- }
- if (unlikely(adapter->pvid)) {
- if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
- return -EIO;
- if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
- goto set_flags;
-
- flags = FLAGS_VLAN_OOB;
- vlan_tci = adapter->pvid;
- }
-set_flags:
- qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
- qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
- if (*(skb->data) & BIT_0) {
- flags |= BIT_0;
- memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
- }
- opcode = TX_ETHER_PKT;
- if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
- skb_shinfo(skb)->gso_size > 0) {
-
- hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-
- first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- first_desc->total_hdr_length = hdr_len;
-
- opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
-
- /* For LSO, we need to copy the MAC/IP/TCP headers into
- * the descriptor ring */
- copied = 0;
- offset = 2;
-
- if (flags & FLAGS_VLAN_OOB) {
- first_desc->total_hdr_length += VLAN_HLEN;
- first_desc->tcp_hdr_offset = VLAN_HLEN;
- first_desc->ip_hdr_offset = VLAN_HLEN;
- /* Only in case of TSO on vlan device */
- flags |= FLAGS_VLAN_TAGGED;
-
- /* Create a TSO vlan header template for firmware */
-
- hwdesc = &tx_ring->desc_head[producer];
- tx_ring->cmd_buf_arr[producer].skb = NULL;
-
- copy_len = min((int)sizeof(struct cmd_desc_type0) -
- offset, hdr_len + VLAN_HLEN);
-
- vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
- skb_copy_from_linear_data(skb, vh, 12);
- vh->h_vlan_proto = htons(ETH_P_8021Q);
- vh->h_vlan_TCI = htons(vlan_tci);
-
- skb_copy_from_linear_data_offset(skb, 12,
- (char *)vh + 16, copy_len - 16);
-
- copied = copy_len - VLAN_HLEN;
- offset = 0;
-
- producer = get_next_index(producer, tx_ring->num_desc);
- }
-
- while (copied < hdr_len) {
-
- copy_len = min((int)sizeof(struct cmd_desc_type0) -
- offset, (hdr_len - copied));
-
- hwdesc = &tx_ring->desc_head[producer];
- tx_ring->cmd_buf_arr[producer].skb = NULL;
-
- skb_copy_from_linear_data_offset(skb, copied,
- (char *) hwdesc + offset, copy_len);
-
- copied += copy_len;
- offset = 0;
-
- producer = get_next_index(producer, tx_ring->num_desc);
- }
-
- tx_ring->producer = producer;
- smp_mb();
- adapter->stats.lso_frames++;
-
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- u8 l4proto;
-
- if (protocol == ETH_P_IP) {
- l4proto = ip_hdr(skb)->protocol;
-
- if (l4proto == IPPROTO_TCP)
- opcode = TX_TCP_PKT;
- else if (l4proto == IPPROTO_UDP)
- opcode = TX_UDP_PKT;
- } else if (protocol == ETH_P_IPV6) {
- l4proto = ipv6_hdr(skb)->nexthdr;
-
- if (l4proto == IPPROTO_TCP)
- opcode = TX_TCPV6_PKT;
- else if (l4proto == IPPROTO_UDP)
- opcode = TX_UDPV6_PKT;
- }
- }
- first_desc->tcp_hdr_offset += skb_transport_offset(skb);
- first_desc->ip_hdr_offset += skb_network_offset(skb);
- qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
- return 0;
-}
-
-static int
-qlcnic_map_tx_skb(struct pci_dev *pdev,
- struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
-{
- struct qlcnic_skb_frag *nf;
- struct skb_frag_struct *frag;
- int i, nr_frags;
- dma_addr_t map;
-
- nr_frags = skb_shinfo(skb)->nr_frags;
- nf = &pbuf->frag_array[0];
-
- map = pci_map_single(pdev, skb->data,
- skb_headlen(skb), PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, map))
- goto out_err;
-
- nf->dma = map;
- nf->length = skb_headlen(skb);
-
- for (i = 0; i < nr_frags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- nf = &pbuf->frag_array[i+1];
-
- map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
- DMA_TO_DEVICE);
- if (dma_mapping_error(&pdev->dev, map))
- goto unwind;
-
- nf->dma = map;
- nf->length = skb_frag_size(frag);
- }
-
- return 0;
-
-unwind:
- while (--i >= 0) {
- nf = &pbuf->frag_array[i+1];
- pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
- }
-
- nf = &pbuf->frag_array[0];
- pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-
-out_err:
- return -ENOMEM;
-}
-
-static void
-qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
- struct qlcnic_cmd_buffer *pbuf)
-{
- struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
- int nr_frags = skb_shinfo(skb)->nr_frags;
- int i;
-
- for (i = 0; i < nr_frags; i++) {
- nf = &pbuf->frag_array[i+1];
- pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
- }
-
- nf = &pbuf->frag_array[0];
- pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
- pbuf->skb = NULL;
-}
-
-static inline void
-qlcnic_clear_cmddesc(u64 *desc)
-{
- desc[0] = 0ULL;
- desc[2] = 0ULL;
- desc[7] = 0ULL;
-}
-
-netdev_tx_t
-qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
- struct qlcnic_cmd_buffer *pbuf;
- struct qlcnic_skb_frag *buffrag;
- struct cmd_desc_type0 *hwdesc, *first_desc;
- struct pci_dev *pdev;
- struct ethhdr *phdr;
- int delta = 0;
- int i, k;
-
- u32 producer;
- int frag_count;
- u32 num_txd = tx_ring->num_desc;
-
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- netif_stop_queue(netdev);
- return NETDEV_TX_BUSY;
- }
-
- if (adapter->flags & QLCNIC_MACSPOOF) {
- phdr = (struct ethhdr *)skb->data;
- if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
- goto drop_packet;
- }
-
- frag_count = skb_shinfo(skb)->nr_frags + 1;
- /* 14 frags supported for normal packet and
- * 32 frags supported for TSO packet
- */
- if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
-
- for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
- delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
-
- if (!__pskb_pull_tail(skb, delta))
- goto drop_packet;
-
- frag_count = 1 + skb_shinfo(skb)->nr_frags;
- }
-
- if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
- netif_stop_queue(netdev);
- if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
- netif_start_queue(netdev);
- else {
- adapter->stats.xmit_off++;
- return NETDEV_TX_BUSY;
- }
- }
-
- producer = tx_ring->producer;
- pbuf = &tx_ring->cmd_buf_arr[producer];
-
- pdev = adapter->pdev;
-
- first_desc = hwdesc = &tx_ring->desc_head[producer];
- qlcnic_clear_cmddesc((u64 *)hwdesc);
-
- if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
- adapter->stats.tx_dma_map_error++;
- goto drop_packet;
- }
-
- pbuf->skb = skb;
- pbuf->frag_count = frag_count;
-
- qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
- qlcnic_set_tx_port(first_desc, adapter->portnum);
-
- for (i = 0; i < frag_count; i++) {
-
- k = i % 4;
-
- if ((k == 0) && (i > 0)) {
- /* move to next desc.*/
- producer = get_next_index(producer, num_txd);
- hwdesc = &tx_ring->desc_head[producer];
- qlcnic_clear_cmddesc((u64 *)hwdesc);
- tx_ring->cmd_buf_arr[producer].skb = NULL;
- }
-
- buffrag = &pbuf->frag_array[i];
-
- hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
- switch (k) {
- case 0:
- hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
- break;
- case 1:
- hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
- break;
- case 2:
- hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
- break;
- case 3:
- hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
- break;
- }
- }
-
- tx_ring->producer = get_next_index(producer, num_txd);
- smp_mb();
-
- if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
- goto unwind_buff;
-
- if (adapter->mac_learn)
- qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
-
- adapter->stats.txbytes += skb->len;
- adapter->stats.xmitcalled++;
-
- qlcnic_update_cmd_producer(adapter, tx_ring);
-
- return NETDEV_TX_OK;
-
-unwind_buff:
- qlcnic_unmap_buffers(pdev, skb, pbuf);
-drop_packet:
- adapter->stats.txdropped++;
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
-}
-
static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -2366,27 +1921,6 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
return rv;
}
-void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (adapter->ahw->linkup && !linkup) {
- netdev_info(netdev, "NIC Link is down\n");
- adapter->ahw->linkup = 0;
- if (netif_running(netdev)) {
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- } else if (!adapter->ahw->linkup && linkup) {
- netdev_info(netdev, "NIC Link is up\n");
- adapter->ahw->linkup = 1;
- if (netif_running(netdev)) {
- netif_carrier_on(netdev);
- netif_wake_queue(netdev);
- }
- }
-}
-
static void qlcnic_tx_timeout(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -2456,7 +1990,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
done:
adapter->diag_cnt++;
- qlcnic_enable_int(sds_ring);
+ QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
return IRQ_HANDLED;
}
@@ -2493,122 +2027,6 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data)
return IRQ_HANDLED;
}
-static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
-{
- u32 sw_consumer, hw_consumer;
- int count = 0, i;
- struct qlcnic_cmd_buffer *buffer;
- struct pci_dev *pdev = adapter->pdev;
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_skb_frag *frag;
- int done;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
- if (!spin_trylock(&adapter->tx_clean_lock))
- return 1;
-
- sw_consumer = tx_ring->sw_consumer;
- hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-
- while (sw_consumer != hw_consumer) {
- buffer = &tx_ring->cmd_buf_arr[sw_consumer];
- if (buffer->skb) {
- frag = &buffer->frag_array[0];
- pci_unmap_single(pdev, frag->dma, frag->length,
- PCI_DMA_TODEVICE);
- frag->dma = 0ULL;
- for (i = 1; i < buffer->frag_count; i++) {
- frag++;
- pci_unmap_page(pdev, frag->dma, frag->length,
- PCI_DMA_TODEVICE);
- frag->dma = 0ULL;
- }
-
- adapter->stats.xmitfinished++;
- dev_kfree_skb_any(buffer->skb);
- buffer->skb = NULL;
- }
-
- sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
- if (++count >= MAX_STATUS_HANDLE)
- break;
- }
-
- if (count && netif_running(netdev)) {
- tx_ring->sw_consumer = sw_consumer;
-
- smp_mb();
-
- if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
- if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
- netif_wake_queue(netdev);
- adapter->stats.xmit_on++;
- }
- }
- adapter->tx_timeo_cnt = 0;
- }
- /*
- * If everything is freed up to consumer then check if the ring is full
- * If the ring is full then check if more needs to be freed and
- * schedule the call back again.
- *
- * This happens when there are 2 CPUs. One could be freeing and the
- * other filling it. If the ring is full when we get out of here and
- * the card has already interrupted the host then the host can miss the
- * interrupt.
- *
- * There is still a possible race condition and the host could miss an
- * interrupt. The card has to take care of this.
- */
- hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
- done = (sw_consumer == hw_consumer);
- spin_unlock(&adapter->tx_clean_lock);
-
- return done;
-}
-
-static int qlcnic_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
-
- int tx_complete;
- int work_done;
-
- tx_complete = qlcnic_process_cmd_ring(adapter);
-
- work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
- if ((work_done < budget) && tx_complete) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_enable_int(sds_ring);
- }
-
- return work_done;
-}
-
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- int work_done;
-
- work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
- if (work_done < budget) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_enable_int(sds_ring);
- }
-
- return work_done;
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev)
{
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 06/15] qlcnic: change driver firmware interface mechanism
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Change 82xx specific firmware interface and create mailbox based interface
Modify firmware commands to use new mailbox interface
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 424 +++++----
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 646 ++++++-------
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 522 ++++-------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 101 +--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 344 ++++---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 211 ++++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 86 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 83 +--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1028 ++++++++++++--------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 170 +++-
10 files changed, 1971 insertions(+), 1644 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 86e6a80..29caa81 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -33,6 +33,7 @@
#include <linux/if_vlan.h>
#include "qlcnic_hdr.h"
+#include "qlcnic_hw.h"
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 1
@@ -89,6 +90,8 @@
#define QLCNIC_CT_DEFAULT_RX_BUF_LEN 2048
#define QLCNIC_LRO_BUFFER_EXTRA 2048
+#define RSS_HASHTYPE_IP_TCP 0x3
+
/* Opcodes to be used with the commands */
#define TX_ETHER_PKT 0x01
#define TX_TCP_PKT 0x02
@@ -106,7 +109,7 @@
#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
+ MGMT_CMD_DESC_RESV)
#define QLCNIC_MAX_TX_TIMEOUTS 2
-
+#define QLCNIC_MAX_TX_QUEUES 1
/*
* Following are the states of the Phantom. Phantom will set them and
* Host will read to check if the fields are correct.
@@ -157,7 +160,6 @@
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-
#define qlcnic_set_tx_port(_desc, _port) \
((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
@@ -210,6 +212,8 @@ struct rcv_desc {
#define QLCNIC_RESPONSE_DESC 0x05
#define QLCNIC_LRO_DESC 0x12
+#define QLCNIC_TX_POLL_BUDGET 128
+
/* for status field in status_desc */
#define STATUS_CKSUM_LOOP 0
#define STATUS_CKSUM_OK 2
@@ -219,12 +223,10 @@ struct rcv_desc {
#define STATUS_OWNER_PHANTOM (0x2ULL << 56)
/* Status descriptor:
- 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
- 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+ 0-3 rsvd, 4-7 status, 8-11 type, 12-27 total_length
+ 28-43 reference_handle, 44-47 rsvd, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
-#define qlcnic_get_sts_port(sts_data) \
- ((sts_data) & 0x0F)
#define qlcnic_get_sts_status(sts_data) \
(((sts_data) >> 4) & 0x0F)
#define qlcnic_get_sts_type(sts_data) \
@@ -232,9 +234,7 @@ struct rcv_desc {
#define qlcnic_get_sts_totallength(sts_data) \
(((sts_data) >> 12) & 0xFFFF)
#define qlcnic_get_sts_refhandle(sts_data) \
- (((sts_data) >> 28) & 0xFFFF)
-#define qlcnic_get_sts_prot(sts_data) \
- (((sts_data) >> 44) & 0x0F)
+ (((sts_data) >> 28) & 0x7FFF)
#define qlcnic_get_sts_pkt_offset(sts_data) \
(((sts_data) >> 48) & 0x1F)
#define qlcnic_get_sts_desc_cnt(sts_data) \
@@ -243,7 +243,7 @@ struct rcv_desc {
(((sts_data) >> 58) & 0x03F)
#define qlcnic_get_lro_sts_refhandle(sts_data) \
- ((sts_data) & 0x0FFFF)
+ ((sts_data) & 0x07FFF)
#define qlcnic_get_lro_sts_length(sts_data) \
(((sts_data) >> 16) & 0x0FFFF)
#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \
@@ -258,14 +258,13 @@ struct rcv_desc {
(((sts_data) >> 52) & 0x1)
#define qlcnic_get_lro_sts_seq_number(sts_data) \
((sts_data) & 0x0FFFFFFFF)
-#define qlcnic_get_lro_sts_mss(sts_data1) \
- ((sts_data1 >> 32) & 0x0FFFF)
struct status_desc {
__le64 status_desc_data[2];
} __attribute__ ((aligned(16)));
+#define QLCNIC_DEV_INFO_SIZE 1
/* UNIFIED ROMIMAGE */
#define QLCNIC_UNI_FW_MIN_SIZE 0xc8000
#define QLCNIC_UNI_DIR_SECT_PRODUCT_TBL 0x0
@@ -294,6 +293,7 @@ struct uni_data_desc{
/* Flash Defines and Structures */
#define QLCNIC_FLT_LOCATION 0x3F1000
+#define QLCNIC_FDT_LOCATION 0x3F0000
#define QLCNIC_B0_FW_IMAGE_REGION 0x74
#define QLCNIC_C0_FW_IMAGE_REGION 0x97
#define QLCNIC_BOOTLD_REGION 0X72
@@ -331,6 +331,7 @@ struct qlcnic_flt_entry {
#define QLCNIC_BRDTYPE_P3P_10G_CX4 0x0031
#define QLCNIC_BRDTYPE_P3P_10G_XFP 0x0032
#define QLCNIC_BRDTYPE_P3P_10G_TP 0x0080
+#define QLCNIC_BRDTYPE_83XX_10G 0x0083
#define QLCNIC_MSIX_TABLE_OFFSET 0x44
@@ -357,6 +358,11 @@ struct qlcnic_flt_entry {
#define QLCNIC_FLASH_ROMIMAGE_NAME "flash"
extern char qlcnic_driver_name[];
+extern int use_msi;
+extern int use_msi_x;
+extern int auto_fw_reset;
+extern int load_fw_file;
+extern int qlcnic_config_npars;
/* Number of status descriptors to handle per interrupt */
#define MAX_STATUS_HANDLE (64)
@@ -428,12 +434,14 @@ struct qlcnic_dump_template_hdr {
__le32 sys_info[3];
__le32 saved_state[16];
__le32 cap_sizes[8];
+ __le32 ocm_wnd_reg[16];
__le32 rsvd[0];
};
struct qlcnic_fw_dump {
u8 clr; /* flag to indicate if dump is cleared */
u8 enable; /* enable/disable dump */
+ u32 pos; /* position in the dump buffer */
u32 size; /* total size of the dump */
void *data; /* dump data area */
struct qlcnic_dump_template_hdr *tmpl_hdr;
@@ -468,6 +476,8 @@ struct qlcnic_hardware_context {
u8 mc_enabled;
u8 max_mc_count;
u8 diag_test;
+ u8 num_msix;
+ u8 nic_mode;
char diag_cnt;
u16 port_type;
@@ -484,14 +494,20 @@ struct qlcnic_hardware_context {
u16 max_rx_ques;
u16 max_mtu;
u16 msg_enable;
+ u16 act_pci_func;
u32 capabilities;
u32 temp;
u32 int_vec_bit;
u32 fw_hal_version;
+ u32 port_config;
struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
+ struct qlcnic_intrpt_config *intr_tbl;
+ u32 *reg_tbl;
+ u32 *ext_reg_tbl;
+ spinlock_t mbx_lock;
};
struct qlcnic_adapter_stats {
@@ -550,12 +566,17 @@ struct qlcnic_host_sds_ring {
} ____cacheline_internodealigned_in_smp;
struct qlcnic_host_tx_ring {
+ int irq;
+ void __iomem *crb_intr_mask;
+ char name[IFNAMSIZ+4];
u16 ctx_id;
u32 producer;
u32 sw_consumer;
u32 num_desc;
void __iomem *crb_cmd_producer;
struct cmd_desc_type0 *desc_head;
+ struct qlcnic_adapter *adapter;
+ struct napi_struct napi;
struct qlcnic_cmd_buffer *cmd_buf_arr;
__le32 *hw_consumer;
@@ -605,49 +626,9 @@ struct qlcnic_recv_context {
*/
#define QLCNIC_CDRP_FORM_CMD(cmd) (QLCNIC_CDRP_CMD_BIT | (cmd))
-#define QLCNIC_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
-#define QLCNIC_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
-#define QLCNIC_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
-#define QLCNIC_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
-#define QLCNIC_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
-#define QLCNIC_CDRP_CMD_CREATE_RX_CTX 0x00000007
-#define QLCNIC_CDRP_CMD_DESTROY_RX_CTX 0x00000008
-#define QLCNIC_CDRP_CMD_CREATE_TX_CTX 0x00000009
-#define QLCNIC_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
-#define QLCNIC_CDRP_CMD_INTRPT_TEST 0x00000011
-#define QLCNIC_CDRP_CMD_SET_MTU 0x00000012
-#define QLCNIC_CDRP_CMD_READ_PHY 0x00000013
-#define QLCNIC_CDRP_CMD_WRITE_PHY 0x00000014
-#define QLCNIC_CDRP_CMD_READ_HW_REG 0x00000015
-#define QLCNIC_CDRP_CMD_GET_FLOW_CTL 0x00000016
-#define QLCNIC_CDRP_CMD_SET_FLOW_CTL 0x00000017
-#define QLCNIC_CDRP_CMD_READ_MAX_MTU 0x00000018
-#define QLCNIC_CDRP_CMD_READ_MAX_LRO 0x00000019
-#define QLCNIC_CDRP_CMD_MAC_ADDRESS 0x0000001f
-
-#define QLCNIC_CDRP_CMD_GET_PCI_INFO 0x00000020
-#define QLCNIC_CDRP_CMD_GET_NIC_INFO 0x00000021
-#define QLCNIC_CDRP_CMD_SET_NIC_INFO 0x00000022
-#define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024
-#define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH 0x00000025
-#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
-#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
-#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
-#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029
-#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
-#define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E
-#define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f
-#define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030
-#define QLCNIC_CDRP_CMD_GET_MAC_STATS 0x00000037
-
#define QLCNIC_RCODE_SUCCESS 0
-#define QLCNIC_RCODE_INVALID_ARGS 6
#define QLCNIC_RCODE_NOT_SUPPORTED 9
-#define QLCNIC_RCODE_NOT_PERMITTED 10
-#define QLCNIC_RCODE_NOT_IMPL 15
-#define QLCNIC_RCODE_INVALID 16
#define QLCNIC_RCODE_TIMEOUT 17
-#define QLCNIC_DESTROY_CTX_RESET 0
/*
* Capabilities Announced
@@ -658,7 +639,6 @@ struct qlcnic_recv_context {
#define QLCNIC_CAP0_JUMBO_CONTIGUOUS (1 << 7)
#define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8)
#define QLCNIC_CAP0_VALIDOFF (1 << 11)
-#define QLCNIC_CAP0_LRO_MSS (1 << 21)
/*
* Context state
@@ -850,8 +830,8 @@ struct qlcnic_mac_list_s {
* Firmware --> Driver
*/
-#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f
-#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141
+#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8F
+#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D
#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
#define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */
@@ -865,9 +845,6 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9
#define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10
#define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27
-#define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31
-
-#define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
@@ -879,19 +856,10 @@ struct qlcnic_mac_list_s {
#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7
#define LINKEVENT_MODULE_TWINAX 8
-#define LINKSPEED_10GBPS 10000
-#define LINKSPEED_1GBPS 1000
-#define LINKSPEED_100MBPS 100
-#define LINKSPEED_10MBPS 10
-
#define LINKSPEED_ENCODED_10MBPS 0
#define LINKSPEED_ENCODED_100MBPS 1
#define LINKSPEED_ENCODED_1GBPS 2
-#define LINKEVENT_AUTONEG_DISABLED 0
-#define LINKEVENT_AUTONEG_ENABLED 1
-
-#define LINKEVENT_HALF_DUPLEX 0
#define LINKEVENT_FULL_DUPLEX 1
#define LINKEVENT_LINKSPEED_MBPS 0
@@ -957,7 +925,6 @@ struct qlcnic_ipaddr {
#define QLCNIC_NEED_FLR 0x1000
#define QLCNIC_FW_RESET_OWNER 0x2000
#define QLCNIC_FW_HANG 0x4000
-#define QLCNIC_FW_LRO_MSS_CAP 0x8000
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -976,6 +943,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_AER 5
#define __QLCNIC_DIAG_RES_ALLOC 6
#define __QLCNIC_LED_ENABLE 7
+#define __QLCNIC_ELB_INPROGRESS 8
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
@@ -1014,6 +982,7 @@ struct qlcnic_adapter {
unsigned long state;
u32 flags;
+ int max_drv_tx_rings;
u16 num_txd;
u16 num_rxd;
u16 num_jumbo_rxd;
@@ -1022,6 +991,7 @@ struct qlcnic_adapter {
u8 max_rds_rings;
u8 max_sds_rings;
+ u8 rx_csum;
u8 portnum;
u8 fw_wait_cnt;
@@ -1041,10 +1011,12 @@ struct qlcnic_adapter {
u8 mac_addr[ETH_ALEN];
- u64 dev_rst_time;
u8 mac_learn;
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ u64 dev_rst_time;
+ u8 flash_mfg_id;
+ struct vlan_group *vlgrp;
struct qlcnic_npar_info *npars;
struct qlcnic_eswitch *eswitch;
struct qlcnic_nic_template *nic_ops;
@@ -1085,7 +1057,24 @@ struct qlcnic_info {
__le16 max_rx_ques;
__le16 min_tx_bw;
__le16 max_tx_bw;
- u8 reserved2[104];
+ __le32 op_type;
+ __le16 max_bw_reg_offset;
+ __le16 max_linkspeed_reg_offset;
+ __le32 capability1;
+ __le32 capability2;
+ __le32 capability3;
+ __le16 max_tx_mac_filters;
+ __le16 max_rx_mcast_mac_filters;
+ __le16 max_rx_ucast_mac_filters;
+ __le16 max_rx_ip_addr;
+ __le16 max_rx_lro_flow;
+ __le16 max_rx_status_rings;
+ __le16 max_rx_buf_rings;
+ __le16 max_tx_vlan_keys;
+ u8 total_pf;
+ u8 total_rss_engines;
+ __le16 max_vports;
+ u8 reserved2[64];
} __packed;
struct qlcnic_pci_info {
@@ -1099,7 +1088,8 @@ struct qlcnic_pci_info {
__le16 reserved1[2];
u8 mac[ETH_ALEN];
- u8 reserved2[106];
+ __le16 func_count;
+ u8 reserved2[104];
} __packed;
struct qlcnic_npar_info {
@@ -1116,6 +1106,7 @@ struct qlcnic_npar_info {
u8 mac_anti_spoof;
u8 promisc_mode;
u8 offload_flags;
+ u8 pci_func;
};
struct qlcnic_eswitch {
@@ -1208,7 +1199,7 @@ do { \
(VAL1) += (VAL2); \
} while (0)
-struct qlcnic_mac_statistics{
+struct qlcnic_mac_statistics {
__le64 mac_tx_frames;
__le64 mac_tx_bytes;
__le64 mac_tx_mcast_pkts;
@@ -1244,7 +1235,7 @@ struct qlcnic_mac_statistics{
__le64 mac_rx_length_large;
__le64 mac_rx_jabber;
__le64 mac_rx_dropped;
- __le64 mac_rx_crc_error;
+ __le64 mac_FCS_error;
__le64 mac_align_error;
} __packed;
@@ -1358,13 +1349,13 @@ struct __queue {
struct qlcnic_dump_entry {
struct qlcnic_common_entry_hdr hdr;
union {
- struct __crb crb;
- struct __cache cache;
- struct __ocm ocm;
- struct __mem mem;
- struct __mux mux;
- struct __queue que;
- struct __ctrl ctrl;
+ struct __crb crb;
+ struct __cache cache;
+ struct __ocm ocm;
+ struct __mem mem;
+ struct __mux mux;
+ struct __queue que;
+ struct __ctrl ctrl;
} region;
} __packed;
@@ -1384,6 +1375,9 @@ enum op_codes {
QLCNIC_DUMP_L2_ITAG = 22,
QLCNIC_DUMP_L2_DATA = 23,
QLCNIC_DUMP_L2_INST = 24,
+ QLCNIC_DUMP_POLL_RD = 35,
+ QLCNIC_READ_MUX2 = 36,
+ QLCNIC_READ_POLLRDMWR = 37,
QLCNIC_DUMP_READ_ROM = 71,
QLCNIC_DUMP_READ_MEM = 72,
QLCNIC_DUMP_READ_CTRL = 98,
@@ -1408,8 +1402,8 @@ enum op_codes {
#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
#define QLCNIC_FORCE_FW_RESET 0xdeaddead
-#define QLCNIC_SET_QUIESCENT 0xadd00010
-#define QLCNIC_RESET_QUIESCENT 0xadd00020
+#define QLCNIC_SET_QUIESCENT 0xadd00010
+#define QLCNIC_RESET_QUIESCENT 0xadd00020
struct qlcnic_dump_operations {
enum op_codes opcode;
@@ -1418,10 +1412,8 @@ struct qlcnic_dump_operations {
};
struct _cdrp_cmd {
- u32 cmd;
- u32 arg1;
- u32 arg2;
- u32 arg3;
+ u32 num;
+ u32 *arg;
};
struct qlcnic_cmd_args {
@@ -1432,7 +1424,7 @@ struct qlcnic_cmd_args {
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
-u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
+u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *);
int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data);
int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data);
int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data);
@@ -1442,8 +1434,8 @@ void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64);
#define ADDR_IN_RANGE(addr, low, high) \
(((addr) < (high)) && ((addr) >= (low)))
-#define QLCRD32(adapter, off) \
- adapter->ahw->hw_ops->rdreg(adapter, off)
+#define QLCRD32(adapter, off, err) \
+ (adapter->ahw->hw_ops->rdreg)(adapter, off, err)
#define QLCWR32(adapter, off, val) \
adapter->ahw->hw_ops->wrtreg(adapter, off, val)
@@ -1458,10 +1450,6 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID)
#define qlcnic_phy_unlock(a) \
qlcnic_pcie_sem_unlock((a), 3)
-#define qlcnic_api_lock(a) \
- qlcnic_pcie_sem_lock((a), 5, 0)
-#define qlcnic_api_unlock(a) \
- qlcnic_pcie_sem_unlock((a), 5)
#define qlcnic_sw_lock(a) \
qlcnic_pcie_sem_lock((a), 6, 0)
#define qlcnic_sw_unlock(a) \
@@ -1474,120 +1462,171 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
#define __QLCNIC_MAX_LED_RATE 0xf
#define __QLCNIC_MAX_LED_STATE 0x2
-int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
-int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
-int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
-void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
-void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
+#ifndef SPEED_UNKNOWN
+#define SPEED_UNKNOWN 0x0
+#endif
+
+#ifndef DUPLEX_UNKNOWN
+#define DUPLEX_UNKNOWN 0xff
+#endif
+
+int qlcnic_get_board_info(struct qlcnic_adapter *);
+int qlcnic_wol_supported(struct qlcnic_adapter *);
+int qlcnic_config_led(struct qlcnic_adapter *, u32, u32);
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *);
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *);
int qlcnic_dump_fw(struct qlcnic_adapter *);
void qlcnic_get_ocm_win(struct qlcnic_hardware_context *);
void qlcnic_get_func_no(struct qlcnic_adapter *);
+int qlcnic_api_lock(struct qlcnic_adapter *);
+void qlcnic_api_unlock(struct qlcnic_adapter *);
/* Functions from qlcnic_init.c */
-int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
-int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter);
-void qlcnic_request_firmware(struct qlcnic_adapter *adapter);
-void qlcnic_release_firmware(struct qlcnic_adapter *adapter);
-int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter);
-int qlcnic_setup_idc_param(struct qlcnic_adapter *adapter);
-int qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter);
-
-int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp);
-int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
- u8 *bytes, size_t size);
-int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter);
-void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter);
-
+int qlcnic_attach(struct qlcnic_adapter *);
+void qlcnic_detach(struct qlcnic_adapter *);
+void qlcnic_down(struct qlcnic_adapter *, struct net_device *);
+int qlcnic_up(struct qlcnic_adapter *, struct net_device *);
+void qlcnic_restore_indev_addr(struct net_device *, unsigned long);
+void qlcnic_idc_exit(struct qlcnic_adapter *);
+void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int);
+int qlcnic_load_firmware(struct qlcnic_adapter *);
+int qlcnic_need_fw_reset(struct qlcnic_adapter *);
+void qlcnic_request_firmware(struct qlcnic_adapter *);
+void qlcnic_release_firmware(struct qlcnic_adapter *);
+int qlcnic_pinit_from_rom(struct qlcnic_adapter *);
+int qlcnic_setup_idc_param(struct qlcnic_adapter *);
+int qlcnic_check_flash_fw_ver(struct qlcnic_adapter *);
+int qlcnic_rom_fast_read(struct qlcnic_adapter *, u32, u32 *);
+int qlcnic_rom_fast_read_words(struct qlcnic_adapter *, int, u8 *, size_t);
+int qlcnic_alloc_sw_resources(struct qlcnic_adapter *);
+void qlcnic_free_sw_resources(struct qlcnic_adapter *);
void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *, u32);
-
-int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
-void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);
-
-int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter);
-void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter);
-
-void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter);
-void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter);
-void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);
-
-int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
-void qlcnic_watchdog_task(struct work_struct *work);
-void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring);
-int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
-void qlcnic_set_multi(struct net_device *netdev);
-void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
-int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
-int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
-int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
-int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
-
-int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
+int qlcnic_alloc_hw_resources(struct qlcnic_adapter *);
+void qlcnic_free_hw_resources(struct qlcnic_adapter *);
+int qlcnic_fw_create_ctx(struct qlcnic_adapter *);
+void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *);
+void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *);
+void qlcnic_release_rx_buffers(struct qlcnic_adapter *);
+void qlcnic_release_tx_buffers(struct qlcnic_adapter *);
+struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
+struct qlcnic_host_rds_ring *, u16, u16);
+int qlcnic_check_fw_status(struct qlcnic_adapter *);
+void qlcnic_watchdog_task(struct work_struct *);
+void qlcnic_post_rx_buffers(struct qlcnic_adapter *,
+ struct qlcnic_host_rds_ring *, u8);
+int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *, int);
+void qlcnic_set_multi(struct net_device *);
+void qlcnic_free_mac_list(struct qlcnic_adapter *);
+int qlcnic_nic_set_promisc(struct qlcnic_adapter *, u32);
+void qlcnic_config_intr_coalesce(struct qlcnic_adapter *);
+int qlcnic_config_rss(struct qlcnic_adapter *, int);
+void qlcnic_config_ipaddr(struct qlcnic_adapter *, __be32, int);
+int qlcnic_linkevent_request(struct qlcnic_adapter *, int);
+int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *, int);
+int qlcnic_change_mtu(struct net_device *, int);
int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
netdev_features_t qlcnic_fix_features(struct net_device *netdev,
- netdev_features_t features);
+ netdev_features_t features);
int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
-int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
-int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
-int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
-void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
-void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
-int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
-
-void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
-void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
-
+int qlcnic_config_hw_lro(struct qlcnic_adapter *, int);
+int qlcnic_config_bridged_mode(struct qlcnic_adapter *, u32);
+int qlcnic_send_lro_cleanup(struct qlcnic_adapter *);
+void qlcnic_update_cmd_producer(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *);
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *);
+int qlcnic_clear_lb_mode(struct qlcnic_adapter *, u8);
+int qlcnic_set_lb_mode(struct qlcnic_adapter *, u8);
+void qlcnic_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+void qlcnic_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+int qlcnic_set_fw_loopback(struct qlcnic_adapter *, u8);
+int qlcnic_nic_set_promisc(struct qlcnic_adapter *, u32);
+void qlcnic_change_filter(struct qlcnic_adapter *, u64 *, __le16);
/* Functions from qlcnic_ethtool.c */
int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
/* Functions from qlcnic_main.c */
int qlcnic_reset_context(struct qlcnic_adapter *);
-void qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *);
+int qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *);
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
-int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
-void qlcnic_dev_request_reset(struct qlcnic_adapter *);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
-
-int qlcnic_setup_intr(struct qlcnic_adapter *);
+void qlcnic_dev_request_reset(struct qlcnic_adapter *, u32);
+int qlcnic_validate_max_rss(u8, u8);
+int qlcnic_set_max_rss(struct qlcnic_adapter *, u8);
+int qlcnic_setup_intr(struct qlcnic_adapter *, u8);
+int qlcnic_msix_tx_poll(struct napi_struct *, int);
int qlcnic_poll(struct napi_struct *, int);
int qlcnic_rx_poll(struct napi_struct *, int);
void qlcnic_set_vlan_config(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
+
+int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
+void qlcnic_check_options(struct qlcnic_adapter *adapter);
+void qlcnic_handle_fw_message(int, int, struct qlcnic_host_sds_ring *);
+int qlcnic_alloc_rx_skb(struct qlcnic_adapter *,
+ struct qlcnic_host_rds_ring *, struct qlcnic_rx_buffer *);
+void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *,
+ struct qlcnic_host_rds_ring *, u8);
+int qlcnic_process_cmd_ring(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *, int);
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
+int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
+void qlcnic_process_rcv_diag(struct qlcnic_adapter *,
+ struct qlcnic_host_sds_ring *, int, u64);
+int qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *);
+int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *tx_ring, int);
+void qlcnic_handle_linkevent(struct qlcnic_adapter *, struct qlcnic_fw_msg *);
+void qlcnic_advert_link_change(struct qlcnic_adapter *, int);
+int qlcnic_check_rx_tagging(struct qlcnic_adapter *, struct sk_buff *, u16 *);
+int qlcnic_check_temp(struct qlcnic_adapter *adapter);
+/* Functions from qlcnic_io.c */
+void dump_skb(struct sk_buff *, struct qlcnic_adapter *);
+/* Functions from qlcnic_io.c */
+void dump_skb(struct sk_buff *, struct qlcnic_adapter *);
+
/* functions in qlcnic_sysfs.c */
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
void qlcnic_create_sysfs_entries(struct qlcnic_adapter *);
void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *);
void qlcnic_create_diag_entries(struct qlcnic_adapter *);
void qlcnic_remove_diag_entries(struct qlcnic_adapter *);
+void qlcnic_add_sysfs(struct qlcnic_adapter *);
+void qlcnic_remove_sysfs(struct qlcnic_adapter *);
+int qlcnic_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
int qlcnic_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*);
+int qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter);
/* eSwitch management functions */
int qlcnic_config_switch_port(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
+int qlcnic_get_mac_stats(struct qlcnic_adapter *,
+ struct qlcnic_mac_statistics *);
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
struct __qlcnic_esw_statistics *);
int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
struct __qlcnic_esw_statistics *);
-int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
-int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
-extern int qlcnic_config_tso;
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *, u8, u8, u8);
+int qlcnic_check_eswitch_mode(struct qlcnic_adapter *);
+int qlcnic_init_pci_info(struct qlcnic_adapter *);
+int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
+int qlcnic_reset_npar_config(struct qlcnic_adapter *);
+int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *,
+ struct qlcnic_adapter *, u32);
+int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
/*
* QLOGIC Board information
*/
@@ -1601,30 +1640,6 @@ struct qlcnic_brdinfo {
char short_name[QLCNIC_MAX_BOARD_NAME_LEN];
};
-static const struct qlcnic_brdinfo qlcnic_boards[] = {
- {0x1077, 0x8020, 0x1077, 0x203,
- "8200 Series Single Port 10GbE Converged Network Adapter "
- "(TCP/IP Networking)"},
- {0x1077, 0x8020, 0x1077, 0x207,
- "8200 Series Dual Port 10GbE Converged Network Adapter "
- "(TCP/IP Networking)"},
- {0x1077, 0x8020, 0x1077, 0x20b,
- "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x1077, 0x20c,
- "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x1077, 0x20f,
- "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
- {0x1077, 0x8020, 0x103c, 0x3733,
- "NC523SFP 10Gb 2-port Server Adapter"},
- {0x1077, 0x8020, 0x103c, 0x3346,
- "CN1000Q Dual Port Converged Network Adapter"},
- {0x1077, 0x8020, 0x1077, 0x210,
- "QME8242-k 10GbE Dual Port Mezzanine Card"},
- {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
-};
-
-#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
-
static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
{
if (likely(tx_ring->producer < tx_ring->sw_consumer))
@@ -1635,30 +1650,63 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
}
extern const struct ethtool_ops qlcnic_ethtool_ops;
-extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
struct qlcnic_nic_template {
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
+ int (*init_driver) (struct qlcnic_adapter *);
+ void (*request_reset) (struct qlcnic_adapter *, u32);
+ void (*cancel_idc_work) (struct qlcnic_adapter *);
+ int (*napi_add)(struct qlcnic_adapter *, struct net_device *);
+ void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int);
+ irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *);
};
+
/* function template for hardware ops based on different chip type */
struct qlcnic_hardware_ops {
void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
void (*write_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
- u32 (*rdreg) (struct qlcnic_adapter *, ulong);
+ u32 (*rdreg) (struct qlcnic_adapter *, ulong, int *);
int (*wrtreg) (struct qlcnic_adapter *, ulong, u32);
void (*get_ocm_win) (struct qlcnic_hardware_context *);
int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
- int (*setup_intr) (struct qlcnic_adapter *);
- void (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+ int (*setup_intr) (struct qlcnic_adapter *, u8);
+ int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
+ struct qlcnic_adapter *, u32);
+ int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void (*get_func_no) (struct qlcnic_adapter *);
+ int (*api_lock) (struct qlcnic_adapter *);
+ void (*api_unlock) (struct qlcnic_adapter *);
+ void (*add_sysfs) (struct qlcnic_adapter *);
+ void (*remove_sysfs) (struct qlcnic_adapter *);
+ void (*process_lb_rcv_ring_diag) (struct qlcnic_host_sds_ring *);
+ int (*create_rx_ctx) (struct qlcnic_adapter *);
+ int (*create_tx_ctx) (struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *, int);
+ int (*setup_link_event) (struct qlcnic_adapter *, int);
+ int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8);
+ int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *);
+ int (*set_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *);
+ int (*change_macvlan) (struct qlcnic_adapter *, u8*, __le16, u8);
+ void (*napi_enable) (struct qlcnic_adapter *);
+ void (*napi_disable) (struct qlcnic_adapter *);
+ void (*config_intr_coal) (struct qlcnic_adapter *);
+ int (*config_rss) (struct qlcnic_adapter *, int);
+ int (*config_hw_lro) (struct qlcnic_adapter *, int);
+ int (*config_loopback) (struct qlcnic_adapter *, u8);
+ int (*clear_loopback) (struct qlcnic_adapter *, u8);
+ int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
+ void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, __le16);
+ int (*get_board_info) (struct qlcnic_adapter *);
};
+extern struct qlcnic_nic_template qlcnic_vf_ops;
+
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
printk(KERN_INFO "%s: %s: " _fmt, \
- dev_name(&adapter->pdev->dev), \
+ dev_name(&adapter->pdev->dev), \
__func__, ##_args); \
} while (0)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index c79bc9a..b1f3a4a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -7,11 +7,91 @@
#include "qlcnic.h"
+/* Array of FW control command structs with command type and required
+ * number of input and output arguments respectively.
+*/
+static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
+ { QLCNIC_CMD_CREATE_RX_CTX, 4, 1 },
+ { QLCNIC_CMD_DESTROY_RX_CTX, 2, 1 },
+ { QLCNIC_CMD_CREATE_TX_CTX, 4, 1 },
+ { QLCNIC_CMD_DESTROY_TX_CTX, 2, 1 },
+ { QLCNIC_CMD_INTRPT_TEST, 4, 1 },
+ { QLCNIC_CMD_SET_MTU, 4, 1 },
+ { QLCNIC_CMD_READ_PHY, 4, 2 },
+ { QLCNIC_CMD_WRITE_PHY, 5, 1 },
+ { QLCNIC_CMD_READ_HW_REG, 4, 1 },
+ { QLCNIC_CMD_GET_FLOW_CTL, 4, 2 },
+ { QLCNIC_CMD_SET_FLOW_CTL, 4, 1 },
+ { QLCNIC_CMD_READ_MAX_MTU, 4, 2 },
+ { QLCNIC_CMD_READ_MAX_LRO, 4, 2 },
+ { QLCNIC_CMD_MAC_ADDRESS, 4, 3 },
+ { QLCNIC_CMD_GET_PCI_INFO, 4, 1 },
+ { QLCNIC_CMD_GET_NIC_INFO, 4, 1 },
+ { QLCNIC_CMD_SET_NIC_INFO, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3 },
+ { QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3 },
+ { QLCNIC_CMD_SET_PORTMIRRORING, 4, 1 },
+ { QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_MAC_STATS, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3 },
+ { QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1 },
+ { QLCNIC_CMD_CONFIG_PORT, 4, 1 },
+ { QLCNIC_CMD_TEMP_SIZE, 4, 4 },
+ { QLCNIC_CMD_GET_TEMP_HDR, 4, 1 },
+};
+
+/* Allocate mailbox incoming and outgoing registers. It should be used with a
+ * follow up call to qlcnic_free_mbx_args
+ */
+int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
+ struct qlcnic_adapter *adapter, u32 type)
+{
+ int i, size;
+ const struct qlcnic_mailbox_metadata *mbx_tbl;
+
+ mbx_tbl = qlcnic_mbx_tbl;
+ size = ARRAY_SIZE(qlcnic_mbx_tbl);
+ for (i = 0; i < size; i++) {
+ if (type == mbx_tbl[i].cmd) {
+ mbx->req.num = mbx_tbl[i].in_args;
+ mbx->rsp.num = mbx_tbl[i].out_args;
+ mbx->req.arg = kcalloc(mbx->req.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->req.arg)
+ return -ENOMEM;
+ mbx->rsp.arg = kcalloc(mbx->rsp.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->rsp.arg) {
+ kfree(mbx->req.arg);
+ mbx->req.arg = NULL;
+ return -ENOMEM;
+ }
+ memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
+ memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
+ mbx->req.arg[0] = type;
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Free up mailbox registers
+ * */
+void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
+{
+ kfree(cmd->req.arg);
+ cmd->req.arg = NULL;
+ kfree(cmd->rsp.arg);
+ cmd->rsp.arg = NULL;
+}
+
+
static u32
qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
{
u32 rsp;
- int timeout = 0;
+ int err, timeout = 0;
do {
/* give atleast 1ms for firmware to respond */
@@ -20,15 +100,16 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
return QLCNIC_CDRP_RSP_TIMEOUT;
- rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET);
+ rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET, &err);
} while (!QLCNIC_CDRP_IS_RSP(rsp));
return rsp;
}
-void
+int
qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
{
+ int i, err;
u32 rsp;
u32 signature;
struct pci_dev *pdev = adapter->pdev;
@@ -37,179 +118,60 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw);
/* Acquire semaphore before accessing CRB */
- if (qlcnic_api_lock(adapter)) {
- cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
- return;
+ if (ahw->hw_ops->api_lock(adapter)) {
+ cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
+ return cmd->rsp.arg[0];
}
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
- QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, cmd->req.arg1);
- QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, cmd->req.arg2);
- QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, cmd->req.arg3);
+ for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
+ QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
- QLCNIC_CDRP_FORM_CMD(cmd->req.cmd));
-
+ QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
- dev_err(&pdev->dev, "CDRP response timeout.\n");
- cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
+ dev_err(&pdev->dev, "card response timeout.\n");
+ cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
- cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- switch (cmd->rsp.cmd) {
- case QLCNIC_RCODE_INVALID_ARGS:
- dev_err(&pdev->dev, "CDRP invalid args: 0x%x.\n",
- cmd->rsp.cmd);
- break;
- case QLCNIC_RCODE_NOT_SUPPORTED:
- case QLCNIC_RCODE_NOT_IMPL:
- dev_err(&pdev->dev,
- "CDRP command not supported: 0x%x.\n",
- cmd->rsp.cmd);
- break;
- case QLCNIC_RCODE_NOT_PERMITTED:
- dev_err(&pdev->dev,
- "CDRP requested action not permitted: 0x%x.\n",
- cmd->rsp.cmd);
- break;
- case QLCNIC_RCODE_INVALID:
- dev_err(&pdev->dev,
- "CDRP invalid or unknown cmd received: 0x%x.\n",
- cmd->rsp.cmd);
- break;
- case QLCNIC_RCODE_TIMEOUT:
- dev_err(&pdev->dev, "CDRP command timeout: 0x%x.\n",
- cmd->rsp.cmd);
- break;
- default:
- dev_err(&pdev->dev, "CDRP command failed: 0x%x.\n",
- cmd->rsp.cmd);
- }
- } else if (rsp == QLCNIC_CDRP_RSP_OK) {
- cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS;
- if (cmd->rsp.arg2)
- cmd->rsp.arg2 = QLCRD32(adapter,
- QLCNIC_ARG2_CRB_OFFSET);
- if (cmd->rsp.arg3)
- cmd->rsp.arg3 = QLCRD32(adapter,
- QLCNIC_ARG3_CRB_OFFSET);
- }
- if (cmd->rsp.arg1)
- cmd->rsp.arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
+ cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
+ dev_err(&pdev->dev, "failed card response code:0x%x\n",
+ cmd->rsp.arg[0]);
+ } else if (rsp == QLCNIC_CDRP_RSP_OK)
+ cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
- /* Release semaphore */
- qlcnic_api_unlock(adapter);
+ for (i = 1; i < cmd->rsp.num; i++)
+ cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i), &err);
+ /* Release semaphore */
+ ahw->hw_ops->api_unlock(adapter);
+ return cmd->rsp.arg[0];
}
-static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
-{
- uint64_t sum = 0;
- int count = temp_size / sizeof(uint32_t);
- while (count-- > 0)
- sum += *temp_buffer++;
- while (sum >> 32)
- sum = (sum & 0xFFFFFFFF) + (sum >> 32);
- return ~sum;
-}
-
-int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
+int
+qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
{
- int err, i;
- u16 temp_size;
- void *tmp_addr;
- u32 version, csum, *template, *tmp_buf;
+ int err = 0;
struct qlcnic_cmd_args cmd;
- struct qlcnic_hardware_context *ahw;
- struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
- dma_addr_t tmp_addr_t = 0;
-
- ahw = adapter->ahw;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_TEMP_SIZE;
- memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
- ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (cmd.rsp.cmd != QLCNIC_RCODE_SUCCESS) {
- dev_info(&adapter->pdev->dev,
- "Can't get template size %d\n", cmd.rsp.cmd);
- err = -EIO;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
return err;
- }
- temp_size = cmd.rsp.arg2;
- version = cmd.rsp.arg3;
- if (!temp_size)
- return -EIO;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_MTU);
+ cmd.req.arg[1] = recv_ctx->context_id;
+ cmd.req.arg[2] = mtu;
- tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,
- &tmp_addr_t, GFP_KERNEL);
- if (!tmp_addr) {
- dev_err(&adapter->pdev->dev,
- "Can't get memory for FW dump template\n");
- return -ENOMEM;
- }
- memset(&cmd.rsp, 0, sizeof(struct _cdrp_cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_TEMP_HDR;
- cmd.req.arg1 = LSD(tmp_addr_t);
- cmd.req.arg2 = MSD(tmp_addr_t);
- cmd.req.arg3 = temp_size;
- ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- err = cmd.rsp.cmd;
- if (err != QLCNIC_RCODE_SUCCESS) {
- dev_err(&adapter->pdev->dev,
- "Failed to get mini dump template header %d\n", err);
- err = -EIO;
- goto error;
- }
- tmp_tmpl = tmp_addr;
- csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
- if (csum) {
- dev_err(&adapter->pdev->dev,
- "Template header checksum validation failed\n");
- err = -EIO;
- goto error;
- }
- ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
- if (!ahw->fw_dump.tmpl_hdr) {
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
err = -EIO;
- goto error;
}
- tmp_buf = tmp_addr;
- template = (u32 *) ahw->fw_dump.tmpl_hdr;
- for (i = 0; i < temp_size/sizeof(u32); i++)
- *template++ = __le32_to_cpu(*tmp_buf++);
-
- tmpl_hdr = ahw->fw_dump.tmpl_hdr;
- tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
- ahw->fw_dump.enable = 1;
-error:
- dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
+ qlcnic_free_mbx_args(&cmd);
return err;
}
int
-qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
-{
- struct qlcnic_cmd_args cmd;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_SET_MTU;
- cmd.req.arg1 = recv_ctx->context_id;
- cmd.req.arg2 = mtu;
- cmd.req.arg3 = 0;
- if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (cmd.rsp.cmd) {
- dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
- return -EIO;
- }
- }
-
- return 0;
-}
-
-static int
qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
{
void *addr;
@@ -263,9 +225,6 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
| QLCNIC_CAP0_VALIDOFF);
cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
- if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
- cap |= QLCNIC_CAP0_LRO_MSS;
-
prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
msix_handler);
prq->txrx_sds_binding = nsds_rings - 1;
@@ -313,20 +272,18 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
}
phys_addr = hostrq_phys_addr;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = (u32) (phys_addr >> 32);
- cmd.req.arg2 = (u32) (phys_addr & 0xffffffff);
- cmd.req.arg3 = rq_size;
- cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_RX_CTX;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_RX_CTX);
+ cmd.req.arg[1] = MSD(phys_addr);
+ cmd.req.arg[2] = LSD(phys_addr);
+ cmd.req.arg[3] = rq_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (err) {
dev_err(&adapter->pdev->dev,
"Failed to create rx ctx in firmware%d\n", err);
goto out_free_rsp;
}
-
prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
&prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
@@ -357,6 +314,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
out_free_rsp:
dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
cardrsp_phys_addr);
+ qlcnic_free_mbx_args(&cmd);
out_free_rq:
dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
return err;
@@ -365,24 +323,25 @@ out_free_rq:
static void
qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
{
+ int err;
struct qlcnic_cmd_args cmd;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = recv_ctx->context_id;
- cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
- cmd.req.arg3 = 0;
- cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_RX_CTX;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (cmd.rsp.cmd)
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_DESTROY_RX_CTX);
+ cmd.req.arg[1] = recv_ctx->context_id;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
dev_err(&adapter->pdev->dev,
"Failed to destroy rx ctx in firmware\n");
recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
+ qlcnic_free_mbx_args(&cmd);
}
-static int
-qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
+int
+qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring, int ring)
{
struct qlcnic_hostrq_tx_ctx *prq;
struct qlcnic_hostrq_cds_ring *prq_cds;
@@ -394,7 +353,6 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
int err;
u64 phys_addr;
dma_addr_t rq_phys_addr, rsp_phys_addr;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
/* reset host resources */
tx_ring->producer = 0;
@@ -429,9 +387,9 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
prq->host_int_crb_mode =
cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
+ prq->msi_index = 0;
prq->interrupt_ctl = 0;
- prq->msi_index = 0;
prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
prq_cds = &prq->cds_ring;
@@ -440,18 +398,17 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
phys_addr = rq_phys_addr;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = (u32)(phys_addr >> 32);
- cmd.req.arg2 = ((u32)phys_addr & 0xffffffff);
- cmd.req.arg3 = rq_size;
- cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_TX_CTX;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_TX_CTX);
+ cmd.req.arg[1] = MSD(phys_addr);
+ cmd.req.arg[2] = LSD(phys_addr);
+ cmd.req.arg[3] = rq_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (err == QLCNIC_RCODE_SUCCESS) {
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
-
tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
} else {
dev_err(&adapter->pdev->dev,
@@ -464,44 +421,44 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
out_free_rq:
dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
+ qlcnic_free_mbx_args(&cmd);
return err;
}
static void
-qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
+qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring)
{
struct qlcnic_cmd_args cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = adapter->tx_ring->ctx_id;
- cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
- cmd.req.arg3 = 0;
- cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (cmd.rsp.cmd)
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_DESTROY_TX_CTX);
+ cmd.req.arg[1] = tx_ring->ctx_id;
+ if (adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd))
dev_err(&adapter->pdev->dev,
"Failed to destroy tx ctx in firmware\n");
+ qlcnic_free_mbx_args(&cmd);
}
int
qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
{
+ int err;
struct qlcnic_cmd_args cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = config;
- cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIG_PORT;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- return cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIG_PORT);
+ cmd.req.arg[1] = config;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
}
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
{
void *addr;
- int err;
- int ring;
+ int err, ring;
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_sds_ring *sds_ring;
@@ -510,26 +467,28 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
recv_ctx = adapter->recv_ctx;
- tx_ring = adapter->tx_ring;
-
- tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
- sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
- if (tx_ring->hw_consumer == NULL) {
- dev_err(&pdev->dev, "failed to allocate tx consumer\n");
- return -ENOMEM;
- }
- /* cmd desc ring */
- addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
+ sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
+ if (tx_ring->hw_consumer == NULL) {
+ dev_err(&pdev->dev, "failed to allocate tx consumer\n");
+ return -ENOMEM;
+ }
+ /* cmd desc ring */
+ addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
&tx_ring->phys_addr, GFP_KERNEL);
- if (addr == NULL) {
- dev_err(&pdev->dev, "failed to allocate tx desc ring\n");
- err = -ENOMEM;
- goto err_out_free;
- }
+ if (addr == NULL) {
+ dev_err(&pdev->dev,
+ "failed to allocate tx desc ring\n");
+ err = -ENOMEM;
+ goto err_out_free;
+ }
- tx_ring->desc_head = addr;
+ tx_ring->desc_head = addr;
+ }
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -568,24 +527,31 @@ err_out_free:
return err;
}
-
int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
{
- int err;
+ int i, err, ring;
if (adapter->flags & QLCNIC_NEED_FLR) {
pci_reset_function(adapter->pdev);
adapter->flags &= ~QLCNIC_NEED_FLR;
}
- err = qlcnic_fw_cmd_create_rx_ctx(adapter);
+ err = adapter->ahw->hw_ops->create_rx_ctx(adapter);
if (err)
return err;
- err = qlcnic_fw_cmd_create_tx_ctx(adapter);
- if (err) {
- qlcnic_fw_cmd_destroy_rx_ctx(adapter);
- return err;
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ err = adapter->ahw->hw_ops->create_tx_ctx(adapter,
+ &adapter->tx_ring[ring], ring);
+ if (err) {
+ qlcnic_fw_cmd_destroy_rx_ctx(adapter);
+ if (ring == 0)
+ return err;
+ for (i = 0; i < ring; i++)
+ qlcnic_fw_cmd_destroy_tx_ctx(adapter,
+ &adapter->tx_ring[i]);
+ return err;
+ }
}
set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
@@ -594,9 +560,13 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
{
+ int ring;
+
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
qlcnic_fw_cmd_destroy_rx_ctx(adapter);
- qlcnic_fw_cmd_destroy_tx_ctx(adapter);
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
+ qlcnic_fw_cmd_destroy_tx_ctx(adapter,
+ &adapter->tx_ring[ring]);
/* Allow dma queues to drain after context reset */
msleep(20);
@@ -613,20 +583,22 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
recv_ctx = adapter->recv_ctx;
- tx_ring = adapter->tx_ring;
- if (tx_ring->hw_consumer != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- sizeof(u32),
- tx_ring->hw_consumer,
- tx_ring->hw_cons_phys_addr);
- tx_ring->hw_consumer = NULL;
- }
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ if (tx_ring->hw_consumer != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ sizeof(u32),
+ tx_ring->hw_consumer,
+ tx_ring->hw_cons_phys_addr);
+ tx_ring->hw_consumer = NULL;
+ }
- if (tx_ring->desc_head != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- TX_DESC_RINGSIZE(tx_ring),
- tx_ring->desc_head, tx_ring->phys_addr);
- tx_ring->desc_head = NULL;
+ if (tx_ring->desc_head != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ TX_DESC_RINGSIZE(tx_ring),
+ tx_ring->desc_head, tx_ring->phys_addr);
+ tx_ring->desc_head = NULL;
+ }
}
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
@@ -654,25 +626,21 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
}
}
-
/* Get MAC address of a NIC partition */
-
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
{
int err, i;
struct qlcnic_cmd_args cmd;
u32 mac_low, mac_high;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.arg1 = adapter->ahw->pci_func | BIT_8;
- cmd.req.cmd = QLCNIC_CDRP_CMD_MAC_ADDRESS;
- cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_MAC_ADDRESS);
+ cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (err == QLCNIC_RCODE_SUCCESS) {
- mac_low = cmd.rsp.arg1;
- mac_high = cmd.rsp.arg2;
+ mac_low = cmd.rsp.arg[1];
+ mac_high = cmd.rsp.arg[2];
for (i = 0; i < 2; i++)
mac[i] = (u8) (mac_high >> ((1 - i) * 8));
@@ -683,7 +651,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
"Failed to get mac address%d\n", err);
err = -EIO;
}
-
+ qlcnic_free_mbx_args(&cmd);
return err;
}
@@ -693,7 +661,7 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
{
int err;
dma_addr_t nic_dma_t;
- struct qlcnic_info *nic_info;
+ const struct qlcnic_info *nic_info;
void *nic_info_addr;
struct qlcnic_cmd_args cmd;
size_t nic_size = sizeof(struct qlcnic_info);
@@ -705,35 +673,14 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
memset(nic_info_addr, 0, nic_size);
nic_info = nic_info_addr;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_NIC_INFO;
- cmd.req.arg1 = MSD(nic_dma_t);
- cmd.req.arg2 = LSD(nic_dma_t);
- cmd.req.arg3 = (func_id << 16 | nic_size);
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
-
- if (err == QLCNIC_RCODE_SUCCESS) {
- npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
- npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
- npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
- npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
- npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
- npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
- npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
- npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
- npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
- npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
- dev_info(&adapter->pdev->dev,
- "phy port: %d switch_mode: %d,\n"
- "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n"
- "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n",
- npar_info->phys_port, npar_info->switch_mode,
- npar_info->max_tx_ques, npar_info->max_rx_ques,
- npar_info->min_tx_bw, npar_info->max_tx_bw,
- npar_info->max_mtu, npar_info->capabilities);
- } else {
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_NIC_INFO);
+ cmd.req.arg[1] = MSD(nic_dma_t);
+ cmd.req.arg[2] = LSD(nic_dma_t);
+ cmd.req.arg[3] = (func_id << 16 | nic_size);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to get nic info%d\n", err);
err = -EIO;
@@ -741,6 +688,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
nic_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
return err;
}
@@ -776,13 +725,12 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_SET_NIC_INFO;
- cmd.req.arg1 = MSD(nic_dma_t);
- cmd.req.arg2 = LSD(nic_dma_t);
- cmd.req.arg3 = ((nic->pci_func << 16) | nic_size);
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_NIC_INFO);
+ cmd.req.arg[1] = MSD(nic_dma_t);
+ cmd.req.arg[2] = LSD(nic_dma_t);
+ cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
@@ -792,6 +740,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
nic_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
return err;
}
@@ -814,19 +764,21 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
memset(pci_info_addr, 0, pci_size);
npar = pci_info_addr;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_PCI_INFO;
- cmd.req.arg1 = MSD(pci_info_dma_t);
- cmd.req.arg2 = LSD(pci_info_dma_t);
- cmd.req.arg3 = pci_size;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
-
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_PCI_INFO);
+ cmd.req.arg[1] = MSD(pci_info_dma_t);
+ cmd.req.arg[2] = LSD(pci_info_dma_t);
+ cmd.req.arg[3] = pci_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ adapter->ahw->act_pci_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
pci_info->id = le16_to_cpu(npar->id);
pci_info->active = le16_to_cpu(npar->active);
pci_info->type = le16_to_cpu(npar->type);
+ if (pci_info->type == QLCNIC_TYPE_NIC)
+ adapter->ahw->act_pci_func++;
pci_info->default_port =
le16_to_cpu(npar->default_port);
pci_info->tx_min_bw =
@@ -843,6 +795,8 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
pci_info_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
return err;
}
@@ -861,21 +815,20 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
arg1 = id | (enable_mirroring ? BIT_4 : 0);
arg1 |= pci_func << 8;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_SET_PORTMIRRORING;
- cmd.req.arg1 = arg1;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_PORTMIRRORING);
+ cmd.req.arg[1] = arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err != QLCNIC_RCODE_SUCCESS) {
+ if (err != QLCNIC_RCODE_SUCCESS)
dev_err(&adapter->pdev->dev,
"Failed to configure port mirroring%d on eswitch:%d\n",
pci_func, id);
- } else {
+ else
dev_info(&adapter->pdev->dev,
"Configured eSwitch %d for port mirroring:%d\n",
id, pci_func);
- }
+ qlcnic_free_mbx_args(&cmd);
return err;
}
@@ -912,13 +865,12 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
arg1 |= rx_tx << 15 | stats_size << 16;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS;
- cmd.req.arg1 = arg1;
- cmd.req.arg2 = MSD(stats_dma_t);
- cmd.req.arg3 = LSD(stats_dma_t);
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_STATS);
+ cmd.req.arg[1] = arg1;
+ cmd.req.arg[2] = MSD(stats_dma_t);
+ cmd.req.arg[3] = LSD(stats_dma_t);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (!err) {
stats = stats_addr;
@@ -938,6 +890,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
stats_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
return err;
}
@@ -952,6 +906,9 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
void *stats_addr;
int err;
+ if (mac_stats == NULL)
+ return -ENOMEM;
+
stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
&stats_dma_t, GFP_KERNEL);
if (!stats_addr) {
@@ -960,15 +917,12 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
return -ENOMEM;
}
memset(stats_addr, 0, stats_size);
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_MAC_STATS;
- cmd.req.arg1 = stats_size << 16;
- cmd.req.arg2 = MSD(stats_dma_t);
- cmd.req.arg3 = LSD(stats_dma_t);
-
- qlcnic_issue_cmd(adapter, &cmd);
- err = cmd.rsp.cmd;
-
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_MAC_STATS);
+ cmd.req.arg[1] = stats_size << 16;
+ cmd.req.arg[2] = MSD(stats_dma_t);
+ cmd.req.arg[3] = LSD(stats_dma_t);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (!err) {
stats = stats_addr;
mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
@@ -989,11 +943,15 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
le64_to_cpu(stats->mac_rx_length_large);
mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
- mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
+ mac_stats->mac_FCS_error = le64_to_cpu(stats->mac_FCS_error);
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "%s: Get mac stats failed, err=%d.\n", __func__, err);
}
dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
stats_dma_t);
+ qlcnic_free_mbx_args(&cmd);
return err;
}
@@ -1053,7 +1011,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
const u8 port, const u8 rx_tx)
{
-
+ int err;
u32 arg1;
struct qlcnic_cmd_args cmd;
@@ -1076,15 +1034,17 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
arg1 |= BIT_14 | rx_tx << 15;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS;
- cmd.req.arg1 = arg1;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- return cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_STATS);
+ cmd.req.arg[1] = arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
err_ret:
- dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
- "rx_ctx=%d\n", func_esw, port, rx_tx);
+ dev_err(&adapter->pdev->dev,
+ "Invalid args func_esw %d port %d rx_ctx %d\n",
+ func_esw, port, rx_tx);
return -EIO;
}
@@ -1097,22 +1057,21 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
u8 pci_func;
pci_func = (*arg1 >> 8);
- cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG;
- cmd.req.arg1 = *arg1;
- cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- *arg1 = cmd.rsp.arg1;
- *arg2 = cmd.rsp.arg2;
- err = cmd.rsp.cmd;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
+ cmd.req.arg[1] = *arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ *arg1 = cmd.rsp.arg[1];
+ *arg2 = cmd.rsp.arg[2];
+ qlcnic_free_mbx_args(&cmd);
- if (err == QLCNIC_RCODE_SUCCESS) {
+ if (err == QLCNIC_RCODE_SUCCESS)
dev_info(&adapter->pdev->dev,
"eSwitch port config for pci func %d\n", pci_func);
- } else {
+ else
dev_err(&adapter->pdev->dev,
"Failed to get eswitch port config for pci func %d\n",
pci_func);
- }
return err;
}
/* Configure eSwitch port
@@ -1174,20 +1133,19 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
return err;
}
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH;
- cmd.req.arg1 = arg1;
- cmd.req.arg2 = arg2;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_ESWITCH);
+ cmd.req.arg[1] = arg1;
+ cmd.req.arg[2] = arg2;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
- err = cmd.rsp.cmd;
- if (err != QLCNIC_RCODE_SUCCESS) {
+ if (err != QLCNIC_RCODE_SUCCESS)
dev_err(&adapter->pdev->dev,
"Failed to configure eswitch pci func %d\n", pci_func);
- } else {
+ else
dev_info(&adapter->pdev->dev,
"Configured eSwitch for pci func %d\n", pci_func);
- }
return err;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index ec2ad45..bf6b1db 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -78,53 +78,20 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx numbytes",
};
-static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
- "mac_tx_frames",
- "mac_tx_bytes",
- "mac_tx_mcast_pkts",
- "mac_tx_bcast_pkts",
- "mac_tx_pause_cnt",
- "mac_tx_ctrl_pkt",
- "mac_tx_lt_64b_pkts",
- "mac_tx_lt_127b_pkts",
- "mac_tx_lt_255b_pkts",
- "mac_tx_lt_511b_pkts",
- "mac_tx_lt_1023b_pkts",
- "mac_tx_lt_1518b_pkts",
- "mac_tx_gt_1518b_pkts",
- "mac_rx_frames",
- "mac_rx_bytes",
- "mac_rx_mcast_pkts",
- "mac_rx_bcast_pkts",
- "mac_rx_pause_cnt",
- "mac_rx_ctrl_pkt",
- "mac_rx_lt_64b_pkts",
- "mac_rx_lt_127b_pkts",
- "mac_rx_lt_255b_pkts",
- "mac_rx_lt_511b_pkts",
- "mac_rx_lt_1023b_pkts",
- "mac_rx_lt_1518b_pkts",
- "mac_rx_gt_1518b_pkts",
- "mac_rx_length_error",
- "mac_rx_length_small",
- "mac_rx_length_large",
- "mac_rx_jabber",
- "mac_rx_dropped",
- "mac_rx_crc_error",
- "mac_align_error",
-};
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
-#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
-#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
-#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
+#define QLCNIC_82XX_STATS QLCNIC_STATS_LEN
+#define QLCNIC_DEVICE_STATS_LEN(adapter) \
+ ARRAY_SIZE(qlcnic_device_gstrings_stats)
+
+
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
"Link_Test_on_offline",
"Interrupt_Test_offline",
"Internal_Loopback_offline",
- "External_Loopback_offline"
+ "EEPROM_Test_offline"
};
#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
@@ -134,11 +101,9 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
#define QLCNIC_MAX_EEPROM_LEN 1024
static const u32 diag_registers[] = {
- CRB_CMDPEG_STATE,
- CRB_RCVPEG_STATE,
- CRB_XG_STATE_P3P,
- CRB_FW_CAPABILITIES_1,
- ISR_INT_STATE_REG,
+ QLCNIC_CMDPEG_STATE,
+ QLCNIC_RCVPEG_STATE,
+ QLCNIC_FW_CAPABILITIES,
QLCNIC_CRB_DRV_ACTIVE,
QLCNIC_CRB_DEV_STATE,
QLCNIC_CRB_DRV_STATE,
@@ -148,6 +113,12 @@ static const u32 diag_registers[] = {
QLCNIC_PEG_ALIVE_COUNTER,
QLCNIC_PEG_HALT_STATUS1,
QLCNIC_PEG_HALT_STATUS2,
+ -1
+};
+
+static const u32 ext_diag_registers[] = {
+ CRB_XG_STATE_P3P,
+ ISR_INT_STATE_REG,
QLCNIC_CRB_PEG_NET_0+0x3c,
QLCNIC_CRB_PEG_NET_1+0x3c,
QLCNIC_CRB_PEG_NET_2+0x3c,
@@ -156,12 +127,15 @@ static const u32 diag_registers[] = {
};
#define QLCNIC_MGMT_API_VERSION 2
-#define QLCNIC_DEV_INFO_SIZE 1
#define QLCNIC_ETHTOOL_REGS_VER 2
+
static int qlcnic_get_regs_len(struct net_device *dev)
{
- return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
- QLCNIC_DEV_INFO_SIZE + 1;
+ u32 len;
+
+ len = sizeof(ext_diag_registers) + sizeof(diag_registers);
+
+ return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1;
}
static int qlcnic_get_eeprom_len(struct net_device *dev)
@@ -174,10 +148,9 @@ qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 fw_major, fw_minor, fw_build;
-
- fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
- fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
- fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
+ fw_major = QLCRD(adapter, QLCNIC_FW_VERSION_MAJOR);
+ fw_minor = QLCRD(adapter, QLCNIC_FW_VERSION_MINOR);
+ fw_build = QLCRD(adapter, QLCNIC_FW_VERSION_SUB);
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
"%d.%d.%d", fw_major, fw_minor, fw_build);
@@ -193,7 +166,8 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
- int check_sfp_module = 0;
+ int err, check_sfp_module = 0;
+ u16 pcifn = ahw->pci_func;
/* read which mode */
if (ahw->port_type == QLCNIC_GBE) {
@@ -214,9 +188,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->autoneg = ahw->link_autoneg;
} else if (ahw->port_type == QLCNIC_XGBE) {
- u32 val;
+ u32 val = 0;
+ val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
- val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
if (val == QLCNIC_PORT_MODE_802_3_AP) {
ecmd->supported = SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_1000baseT_Full;
@@ -226,6 +200,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
}
if (netif_running(dev) && ahw->has_link_events) {
+ if (QLCNIC_IS_82XX(adapter))
+ ahw->link_speed =
+ QLCNIC_READ_LINK_SPEED(adapter,
+ pcifn, &err);
ethtool_cmd_speed_set(ecmd, ahw->link_speed);
ecmd->autoneg = ahw->link_autoneg;
ecmd->duplex = ahw->link_duplex;
@@ -323,15 +301,10 @@ skip:
}
static int
-qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+qlcnic_set_port_config(struct qlcnic_adapter *adapter,
+ struct ethtool_cmd *ecmd)
{
- u32 config = 0;
- u32 ret = 0;
- struct qlcnic_adapter *adapter = netdev_priv(dev);
-
- if (adapter->ahw->port_type != QLCNIC_GBE)
- return -EOPNOTSUPP;
-
+ u32 ret = 0, config = 0;
/* read which mode */
if (ecmd->duplex)
config |= 0x1;
@@ -359,6 +332,22 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EOPNOTSUPP;
else if (ret)
return -EIO;
+ return ret;
+}
+
+static int
+qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ u32 ret = 0;
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if (adapter->ahw->port_type != QLCNIC_GBE)
+ return -EOPNOTSUPP;
+
+ ret = qlcnic_set_port_config(adapter, ecmd);
+
+ if (!ret)
+ return ret;
adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
adapter->ahw->link_duplex = ecmd->duplex;
@@ -371,6 +360,20 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return dev->netdev_ops->ndo_open(dev);
}
+static int
+qlcnic_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
+{
+ int err, i, j = 0;
+
+ for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
+ regs_buff[i] = QLCRD(adapter, diag_registers[j]);
+ j = 0;
+ while (ext_diag_registers[j] != -1)
+ regs_buff[i++] = QLCRD32(adapter,
+ ext_diag_registers[j++], &err);
+ return i;
+}
+
static void
qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
@@ -379,17 +382,18 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 *regs_buff = p;
- int ring, i = 0, j = 0;
+ int ring, i = 0;
memset(p, 0, qlcnic_get_regs_len(dev));
+
regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
(ahw->revision_id << 16) | (adapter->pdev)->device;
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
regs_buff[1] = QLCNIC_MGMT_API_VERSION;
- for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
- regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
+ if (QLCNIC_IS_82XX(adapter))
+ i = qlcnic_get_registers(adapter, regs_buff);
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;
@@ -414,10 +418,11 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
static u32 qlcnic_test_link(struct net_device *dev)
{
+ int err;
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 val;
- val = QLCRD32(adapter, CRB_XG_STATE_P3P);
+ val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err);
val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
return (val == XG_LINK_UP_P3P) ? 0 : 1;
}
@@ -428,7 +433,7 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
int offset;
- int ret;
+ int ret = -1;
if (eeprom->len == 0)
return -EINVAL;
@@ -437,7 +442,8 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
((adapter->pdev)->device << 16);
offset = eeprom->offset;
- ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
+ if (QLCNIC_IS_82XX(adapter))
+ ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
eeprom->len);
if (ret < 0)
return ret;
@@ -507,43 +513,11 @@ qlcnic_set_ringparam(struct net_device *dev,
return qlcnic_reset_context(adapter);
}
-static void qlcnic_get_channels(struct net_device *dev,
- struct ethtool_channels *channel)
-{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
-
- channel->max_rx = rounddown_pow_of_two(min_t(int,
- adapter->ahw->max_rx_ques, num_online_cpus()));
- channel->max_tx = adapter->ahw->max_tx_ques;
-
- channel->rx_count = adapter->max_sds_rings;
- channel->tx_count = adapter->ahw->max_tx_ques;
-}
-
-static int qlcnic_set_channels(struct net_device *dev,
- struct ethtool_channels *channel)
-{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
- int err;
-
- if (channel->other_count || channel->combined_count ||
- channel->tx_count != channel->max_tx)
- return -EINVAL;
-
- err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
- if (err)
- return err;
-
- err = qlcnic_set_max_rss(adapter, channel->rx_count);
- netdev_info(dev, "allocated 0x%x sds rings\n",
- adapter->max_sds_rings);
- return err;
-}
-
static void
qlcnic_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
+ int err;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
int port = adapter->ahw->physical_port;
@@ -553,9 +527,9 @@ qlcnic_get_pauseparam(struct net_device *netdev,
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
return;
/* get flow control settings */
- val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
+ val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
- val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
+ val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
switch (port) {
case 0:
pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
@@ -575,7 +549,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return;
pause->rx_pause = 1;
- val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
+ val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
if (port == 0)
pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
else
@@ -592,15 +566,16 @@ qlcnic_set_pauseparam(struct net_device *netdev,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
- int port = adapter->ahw->physical_port;
+ int err, port = adapter->ahw->physical_port;
__u32 val;
+
/* read mode */
if (ahw->port_type == QLCNIC_GBE) {
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
return -EIO;
/* set flow control */
- val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
+ val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
if (pause->rx_pause)
qlcnic_gb_rx_flowctl(val);
@@ -609,7 +584,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
/* set autoneg */
- val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
+ val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
switch (port) {
case 0:
if (pause->tx_pause)
@@ -645,7 +620,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return -EIO;
- val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
+ val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
if (port == 0) {
if (pause->tx_pause)
qlcnic_xg_unset_xg0_mask(val);
@@ -667,26 +642,28 @@ qlcnic_set_pauseparam(struct net_device *netdev,
static int qlcnic_reg_test(struct net_device *dev)
{
+ int err;
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 data_read;
- data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
+
+ data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err);
if ((data_read & 0xffff) != adapter->pdev->vendor)
return 1;
return 0;
}
+static int qlcnic_eeprom_test(struct net_device *dev)
+{
+ return 0;
+}
+
static int qlcnic_get_sset_count(struct net_device *dev, int sset)
{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
switch (sset) {
case ETH_SS_TEST:
return QLCNIC_TEST_LEN;
- case ETH_SS_STATS:
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
- return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
- return QLCNIC_TOTAL_STATS_LEN;
default:
return -EOPNOTSUPP;
}
@@ -694,39 +671,7 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
static int qlcnic_irq_test(struct net_device *netdev)
{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- int max_sds_rings = adapter->max_sds_rings;
- int ret;
- struct qlcnic_cmd_args cmd;
-
- if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
- return -EIO;
-
- ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
- if (ret)
- goto clear_it;
-
- adapter->ahw->diag_cnt = 0;
- memset(&cmd, 0, sizeof(cmd));
- cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
- cmd.req.arg1 = adapter->ahw->pci_func;
- adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- ret = cmd.rsp.cmd;
-
- if (ret)
- goto done;
-
- msleep(10);
-
- ret = !adapter->ahw->diag_cnt;
-
-done:
- qlcnic_diag_free_res(netdev, max_sds_rings);
-
-clear_it:
- adapter->max_sds_rings = max_sds_rings;
- clear_bit(__QLCNIC_RESETTING, &adapter->state);
- return ret;
+ return 0;
}
#define QLCNIC_ILB_PKT_SIZE 64
@@ -756,28 +701,29 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
{
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
struct sk_buff *skb;
int i, loop, cnt = 0;
for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
- skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
+ skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
- adapter->ahw->diag_cnt = 0;
+ ahw->diag_cnt = 0;
qlcnic_xmit_frame(skb, adapter->netdev);
loop = 0;
do {
msleep(1);
- qlcnic_process_rcv_ring_diag(sds_ring);
+ ahw->hw_ops->process_lb_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
break;
- } while (!adapter->ahw->diag_cnt);
+ } while (!ahw->diag_cnt);
dev_kfree_skb_any(skb);
- if (!adapter->ahw->diag_cnt)
+ if (!ahw->diag_cnt)
QLCDB(adapter, DRV,
"LB Test: packet #%d was not received\n", i + 1);
else
@@ -787,8 +733,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
dev_warn(&adapter->pdev->dev, "LB Test failed\n");
if (mode != QLCNIC_ILB_MODE) {
dev_warn(&adapter->pdev->dev,
- "WARNING: Please make sure external"
- "loopback connector is plugged in\n");
+ "Check loopback connector\n");
}
return -1;
}
@@ -799,21 +744,21 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int max_sds_rings = adapter->max_sds_rings;
- struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
int loop = 0;
int ret;
if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
- netdev_info(netdev, "Firmware is not loopback test capable\n");
+ dev_info(&adapter->pdev->dev,
+ "Firmware is not loopback test capable\n");
return -EOPNOTSUPP;
}
-
QLCDB(adapter, DRV, "%s loopback test in progress\n",
- mode == QLCNIC_ILB_MODE ? "internal" : "external");
+ mode == QLCNIC_ILB_MODE ? "internal" : "external");
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
- netdev_warn(netdev, "Loopback test not supported for non "
- "privilege function\n");
+ dev_warn(&adapter->pdev->dev,
+ "Loopback test invalid for non privileged function\n");
return 0;
}
@@ -825,18 +770,17 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
goto clear_it;
sds_ring = &adapter->recv_ctx->sds_rings[0];
-
- ret = qlcnic_set_lb_mode(adapter, mode);
+ ret = ahw->hw_ops->config_loopback(adapter, mode);
if (ret)
goto free_res;
ahw->diag_cnt = 0;
do {
msleep(500);
- qlcnic_process_rcv_ring_diag(sds_ring);
+ ahw->hw_ops->process_lb_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
- netdev_info(netdev, "firmware didnt respond to loopback"
- " configure request\n");
+ dev_info(&adapter->pdev->dev,
+ "No response for loopback configure request\n");
ret = -QLCNIC_FW_NOT_RESPOND;
goto free_res;
} else if (ahw->diag_cnt) {
@@ -844,10 +788,11 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
goto free_res;
}
} while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
-
+ /* allowing firmware to settle before running traffic */
+ msleep(2000);
ret = qlcnic_do_lb_test(adapter, mode);
- qlcnic_clear_lb_mode(adapter);
+ ahw->hw_ops->clear_loopback(adapter, mode);
free_res:
qlcnic_diag_free_res(netdev, max_sds_rings);
@@ -880,149 +825,100 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
if (data[3])
eth_test->flags |= ETH_TEST_FL_FAILED;
- if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
- data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
- if (data[4])
- eth_test->flags |= ETH_TEST_FL_FAILED;
- eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
- }
+
+ data[4] = qlcnic_eeprom_test(dev);
+ if (data[4])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
}
}
static void
-qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
- int index, i, j;
switch (stringset) {
case ETH_SS_TEST:
memcpy(data, *qlcnic_gstrings_test,
QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
break;
- case ETH_SS_STATS:
- for (index = 0; index < QLCNIC_STATS_LEN; index++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_gstrings_stats[index].stat_string,
- ETH_GSTRING_LEN);
- }
- for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_mac_stats_strings[j],
- ETH_GSTRING_LEN);
- }
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
- for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_device_gstrings_stats[i],
- ETH_GSTRING_LEN);
- }
}
}
-static void
-qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
+static void qlcnic_get_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
{
- int ind = *index;
-
- if (type == QLCNIC_MAC_STATS) {
- struct qlcnic_mac_statistics *mac_stats =
- (struct qlcnic_mac_statistics *)stats;
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
- data[ind++] =
- QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
- data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
- } else if (type == QLCNIC_ESW_STATS) {
- struct __qlcnic_esw_statistics *esw_stats =
- (struct __qlcnic_esw_statistics *)stats;
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
- data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
- }
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ channel->max_rx = rounddown_pow_of_two(min_t(int,
+ adapter->ahw->max_rx_ques, num_online_cpus()));
+ channel->max_tx = adapter->ahw->max_tx_ques;
+
+ channel->rx_count = adapter->max_sds_rings;
+ channel->tx_count = adapter->ahw->max_tx_ques;
+}
+
+static int qlcnic_set_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+ int err;
+
+ if (channel->other_count || channel->combined_count ||
+ channel->tx_count != channel->max_tx)
+ return -EINVAL;
+
+ err = qlcnic_validate_max_rss(channel->max_rx, channel->rx_count);
+ if (err)
+ return err;
- *index = ind;
+ err = qlcnic_set_max_rss(adapter, channel->rx_count);
+ netdev_info(dev, "allocated 0x%x sds rings\n",
+ adapter->max_sds_rings);
+ return err;
}
static void
-qlcnic_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 * data)
+qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
+ int err;
struct qlcnic_adapter *adapter = netdev_priv(dev);
- struct qlcnic_esw_statistics port_stats;
- struct qlcnic_mac_statistics mac_stats;
- int index, ret;
-
- for (index = 0; index < QLCNIC_STATS_LEN; index++) {
- char *p =
- (char *)adapter +
- qlcnic_gstrings_stats[index].stat_offset;
- data[index] =
- (qlcnic_gstrings_stats[index].sizeof_stat ==
- sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
- }
+ u32 wol_cfg;
- /* Retrieve MAC statistics from firmware */
- memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
- qlcnic_get_mac_stats(adapter, &mac_stats);
- qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
+ wol->supported = 0;
+ wol->wolopts = 0;
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
- return;
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
+ if (wol_cfg & (1UL << adapter->portnum))
+ wol->supported |= WAKE_MAGIC;
- memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
- ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
- QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
- if (ret)
- return;
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
+ if (wol_cfg & (1UL << adapter->portnum))
+ wol->wolopts |= WAKE_MAGIC;
+}
- qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
+static int
+qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ int err;
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+ u32 wol_cfg;
- ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
- QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
- if (ret)
- return;
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EOPNOTSUPP;
+
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
+ if (!(wol_cfg & (1 << adapter->portnum)))
+ return -EOPNOTSUPP;
- qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
+ if (wol->wolopts & WAKE_MAGIC)
+ wol_cfg |= 1UL << adapter->portnum;
+ else
+ wol_cfg &= ~(1UL << adapter->portnum);
+
+ QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
+
+ return 0;
}
static int qlcnic_set_led(struct net_device *dev,
@@ -1092,48 +988,6 @@ static int qlcnic_set_led(struct net_device *dev,
return err;
}
-static void
-qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
- u32 wol_cfg;
-
- wol->supported = 0;
- wol->wolopts = 0;
-
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
- if (wol_cfg & (1UL << adapter->portnum))
- wol->supported |= WAKE_MAGIC;
-
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
- if (wol_cfg & (1UL << adapter->portnum))
- wol->wolopts |= WAKE_MAGIC;
-}
-
-static int
-qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
- struct qlcnic_adapter *adapter = netdev_priv(dev);
- u32 wol_cfg;
-
- if (wol->wolopts & ~WAKE_MAGIC)
- return -EOPNOTSUPP;
-
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
- if (!(wol_cfg & (1 << adapter->portnum)))
- return -EOPNOTSUPP;
-
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
- if (wol->wolopts & WAKE_MAGIC)
- wol_cfg |= 1UL << adapter->portnum;
- else
- wol_cfg &= ~(1UL << adapter->portnum);
-
- QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
-
- return 0;
-}
-
/*
* Set the coalescing parameters. Currently only normal is supported.
* If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
@@ -1188,7 +1042,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
ethcoal->rx_max_coalesced_frames;
}
- qlcnic_config_intr_coalesce(adapter);
+ adapter->ahw->hw_ops->config_intr_coal(adapter);
return 0;
}
@@ -1287,7 +1141,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
static int
qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
{
- int i;
+ int i, err;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
u32 state;
@@ -1308,7 +1162,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return 0;
}
netdev_info(netdev, "Forcing a FW dump\n");
- qlcnic_dev_request_reset(adapter);
+ adapter->nic_ops->request_reset(adapter, val->flag);
break;
case QLCNIC_DISABLE_FW_DUMP:
if (fw_dump->enable && fw_dump->tmpl_hdr) {
@@ -1328,12 +1182,12 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return 0;
case QLCNIC_FORCE_FW_RESET:
netdev_info(netdev, "Forcing a FW reset\n");
- qlcnic_dev_request_reset(adapter);
+ adapter->nic_ops->request_reset(adapter, val->flag);
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
return 0;
case QLCNIC_SET_QUIESCENT:
case QLCNIC_RESET_QUIESCENT:
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE, &err);
if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
netdev_info(netdev, "Device in FAILED state\n");
return 0;
@@ -1376,7 +1230,6 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.set_wol = qlcnic_set_wol,
.self_test = qlcnic_diag_test,
.get_strings = qlcnic_get_strings,
- .get_ethtool_stats = qlcnic_get_ethtool_stats,
.get_sset_count = qlcnic_get_sset_count,
.get_coalesce = qlcnic_get_intr_coalesce,
.set_coalesce = qlcnic_set_intr_coalesce,
@@ -1387,10 +1240,3 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.get_dump_data = qlcnic_get_dump_data,
.set_dump = qlcnic_set_dump,
};
-
-const struct ethtool_ops qlcnic_ethtool_failed_ops = {
- .get_settings = qlcnic_get_settings,
- .get_drvinfo = qlcnic_get_drvinfo,
- .set_msglevel = qlcnic_set_msglevel,
- .get_msglevel = qlcnic_get_msglevel,
-};
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 92cd3c3..72615d1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -11,6 +11,8 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#include "qlcnic_hw.h"
+
/*
* The basic unit of access when reading/writing control registers.
*/
@@ -387,9 +389,6 @@ enum {
#define QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014)
#define QLCNIC_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018)
-/* Lock IDs for ROM lock */
-#define ROM_LOCK_DRIVER 0x0d417340
-
/******************************************************************************
*
* Definitions specific to M25P flash
@@ -488,7 +487,7 @@ enum {
#define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \
(QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000)
-
+#define MAX_CTL_CHECK 1000
#define TEST_AGT_CTRL (0x00)
#define TA_CTL_START BIT_0
@@ -496,26 +495,26 @@ enum {
#define TA_CTL_WRITE BIT_2
#define TA_CTL_BUSY BIT_3
-/*
- * Register offsets for MN
- */
-#define MIU_TEST_AGT_BASE (0x90)
-
-#define MIU_TEST_AGT_ADDR_LO (0x04)
-#define MIU_TEST_AGT_ADDR_HI (0x08)
-#define MIU_TEST_AGT_WRDATA_LO (0x10)
-#define MIU_TEST_AGT_WRDATA_HI (0x14)
-#define MIU_TEST_AGT_WRDATA_UPPER_LO (0x20)
-#define MIU_TEST_AGT_WRDATA_UPPER_HI (0x24)
-#define MIU_TEST_AGT_WRDATA(i) (0x10+(0x10*((i)>>1))+(4*((i)&1)))
-#define MIU_TEST_AGT_RDDATA_LO (0x18)
-#define MIU_TEST_AGT_RDDATA_HI (0x1c)
-#define MIU_TEST_AGT_RDDATA_UPPER_LO (0x28)
-#define MIU_TEST_AGT_RDDATA_UPPER_HI (0x2c)
-#define MIU_TEST_AGT_RDDATA(i) (0x18+(0x10*((i)>>1))+(4*((i)&1)))
-
-#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
-#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+#define QLCNIC_MS_CTRL 0x41000090
+#define QLCNIC_MS_ADDR_LO 0x41000094
+#define QLCNIC_MS_ADDR_HI 0x41000098
+
+#define QLCNIC_MS_WRTDATA_LO 0x410000A0
+#define QLCNIC_MS_WRTDATA_HI 0x410000A4
+#define QLCNIC_MS_WRTDATA_ULO 0x410000B0
+#define QLCNIC_MS_WRTDATA_UHI 0x410000B4
+
+#define QLCNIC_MS_RDDATA_LO 0x410000A8
+#define QLCNIC_MS_RDDATA_HI 0x410000AC
+#define QLCNIC_MS_RDDATA_ULO 0x410000B8
+#define QLCNIC_MS_RDDATA_UHI 0x410000BC
+
+static const u32 QLCNIC_MS_READ_DATA[] = {
+ 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, };
+
+#define QLC_TA_WRITE_ENABLE (TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLC_TA_WRITE_START (TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLC_TA_START_ENABLE (TA_CTL_START | TA_CTL_ENABLE)
/* XG Link status */
#define XG_LINK_UP 0x10
@@ -536,9 +535,6 @@ enum {
#define QLCNIC_CAM_RAM_BASE (QLCNIC_CRB_CAM + 0x02000)
#define QLCNIC_CAM_RAM(reg) (QLCNIC_CAM_RAM_BASE + (reg))
-#define QLCNIC_FW_VERSION_MAJOR (QLCNIC_CAM_RAM(0x150))
-#define QLCNIC_FW_VERSION_MINOR (QLCNIC_CAM_RAM(0x154))
-#define QLCNIC_FW_VERSION_SUB (QLCNIC_CAM_RAM(0x158))
#define QLCNIC_ROM_LOCK_ID (QLCNIC_CAM_RAM(0x100))
#define QLCNIC_PHY_LOCK_ID (QLCNIC_CAM_RAM(0x120))
#define QLCNIC_CRB_WIN_LOCK_ID (QLCNIC_CAM_RAM(0x124))
@@ -548,23 +544,19 @@ enum {
#define QLCNIC_REG(X) (NIC_CRB_BASE+(X))
#define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X))
+#define QLCNIC_CDRP_MAX_ARGS 4
+#define QLCNIC_CDRP_ARG(i) (QLCNIC_REG(0x18 + ((i) * 4)))
+
#define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18))
-#define QLCNIC_ARG1_CRB_OFFSET (QLCNIC_REG(0x1c))
-#define QLCNIC_ARG2_CRB_OFFSET (QLCNIC_REG(0x20))
-#define QLCNIC_ARG3_CRB_OFFSET (QLCNIC_REG(0x24))
#define QLCNIC_SIGN_CRB_OFFSET (QLCNIC_REG(0x28))
-#define CRB_CMDPEG_STATE (QLCNIC_REG(0x50))
-#define CRB_RCVPEG_STATE (QLCNIC_REG(0x13c))
#define CRB_XG_STATE_P3P (QLCNIC_REG(0x98))
#define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8))
-#define CRB_TEMP_STATE (QLCNIC_REG(0x1b4))
#define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0))
-#define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128))
#define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c))
/*
@@ -653,17 +645,6 @@ enum {
#define QLCNIC_PEG_TUNE_CAPABILITY (QLCNIC_CAM_RAM(0x02c))
#define QLCNIC_DMA_WATCHDOG_CTRL (QLCNIC_CAM_RAM(0x14))
-#define QLCNIC_PEG_ALIVE_COUNTER (QLCNIC_CAM_RAM(0xb0))
-#define QLCNIC_PEG_HALT_STATUS1 (QLCNIC_CAM_RAM(0xa8))
-#define QLCNIC_PEG_HALT_STATUS2 (QLCNIC_CAM_RAM(0xac))
-#define QLCNIC_CRB_DRV_ACTIVE (QLCNIC_CAM_RAM(0x138))
-#define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140))
-
-#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144))
-#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148))
-#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c))
-#define QLCNIC_CRB_DRV_IDC_VER (QLCNIC_CAM_RAM(0x174))
-#define QLCNIC_CRB_DEV_NPAR_STATE (QLCNIC_CAM_RAM(0x19c))
#define QLCNIC_ROM_DEV_INIT_TIMEOUT (0x3e885c)
#define QLCNIC_ROM_DRV_RESET_TIMEOUT (0x3e8860)
@@ -682,7 +663,6 @@ enum {
#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */
#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */
-#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) & (1 << (FN * 4)))
#define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4)))
#define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4)))
#define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4)))
@@ -739,16 +719,11 @@ struct qlcnic_legacy_intr_set {
u32 tgt_mask_reg;
};
-#define QLCNIC_FW_API 0x1b216c
-#define QLCNIC_DRV_OP_MODE 0x1b2170
#define QLCNIC_MSIX_BASE 0x132110
#define QLCNIC_MAX_PCI_FUNC 8
#define QLCNIC_MAX_VLAN_FILTERS 64
/* FW dump defines */
-#define MIU_TEST_CTR 0x41000090
-#define MIU_TEST_ADDR_LO 0x41000094
-#define MIU_TEST_ADDR_HI 0x41000098
#define FLASH_ROM_WINDOW 0x42110030
#define FLASH_ROM_DATA 0x42150000
@@ -756,36 +731,18 @@ struct qlcnic_legacy_intr_set {
static const u32 FW_DUMP_LEVELS[] = {
0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
-static const u32 MIU_TEST_READ_DATA[] = {
- 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, };
-
#define QLCNIC_FW_DUMP_REG1 0x00130060
#define QLCNIC_FW_DUMP_REG2 0x001e0000
#define QLCNIC_FLASH_SEM2_LK 0x0013C010
#define QLCNIC_FLASH_SEM2_ULK 0x0013C014
#define QLCNIC_FLASH_LOCK_ID 0x001B2100
-#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do { \
- writel((addr & 0xFFFF0000), (void *) (bar0 + \
- QLCNIC_FW_DUMP_REG1)); \
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \
- *data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + \
- LSW(addr))); \
-} while (0)
-
-#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do { \
- writel((addr & 0xFFFF0000), (void *) (bar0 + \
- QLCNIC_FW_DUMP_REG1)); \
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \
- writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\
- readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr))); \
-} while (0)
-
/* PCI function operational mode */
enum {
QLCNIC_MGMT_FUNC = 0,
QLCNIC_PRIV_FUNC = 1,
- QLCNIC_NON_PRIV_FUNC = 2
+ QLCNIC_NON_PRIV_FUNC = 2,
+ QLCNIC_UNKNOWN_FUNC_MODE = 3
};
enum {
@@ -986,6 +943,8 @@ enum {
#define QLCNIC_NIU_PROMISC_MODE 1
#define QLCNIC_NIU_ALLMULTI_MODE 2
+#define QLCNIC_PCIE_SEM_TIMEOUT 10000
+
struct crb_128M_2M_sub_block_map {
unsigned valid;
unsigned start_128M;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 3ec03e1..fb7a0b7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -7,23 +7,12 @@
#include "qlcnic.h"
#include "qlcnic_hdr.h"
+#include "qlcnic_hw.h"
#include <linux/slab.h>
#include <net/ip.h>
#include <linux/bitops.h>
-#define MASK(n) ((1ULL<<(n))-1)
-#define OCM_WIN_P3P(addr) (addr & 0xffc0000)
-
-#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
-
-#define CRB_BLK(off) ((off >> 20) & 0x3f)
-#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
-#define CRB_WINDOW_2M (0x130060)
-#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
-#define CRB_INDIRECT_2M (0x1e0000UL)
-
-
#ifndef readq
static inline u64 readq(void __iomem *addr)
{
@@ -276,21 +265,50 @@ static const u32 msi_tgt_status[8] = {
/* PCI Windowing for DDR regions. */
-#define QLCNIC_PCIE_SEM_TIMEOUT 10000
+static void
+qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ *data = readl(val);
+}
+
+static void
+qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_FW_DUMP_REG1;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+ writel(data, val);
+ readl(val);
+}
int
qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
{
- int done = 0, timeout = 0;
+ int err, done = 0, timeout = 0;
while (!done) {
- done = QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)));
+ done = QLCRD32(adapter,
+ QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)), &err);
if (done == 1)
break;
if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
dev_err(&adapter->pdev->dev,
- "Failed to acquire sem=%d lock; holdby=%d\n",
- sem, id_reg ? QLCRD32(adapter, id_reg) : -1);
+ "Failed to acquire sem=%d lock; held by=%d\n",
+ sem,
+ id_reg ? QLCRD32(adapter, id_reg, &err) : -1);
return -EIO;
}
msleep(1);
@@ -302,10 +320,28 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
return 0;
}
+u32 qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
+{
+ u32 data;
+
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_read_dump_reg(addr, adapter->ahw->pci_base0, &data);
+ else
+ return -EIO;
+ return data;
+}
+
+void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
+{
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_write_dump_reg(addr, adapter->ahw->pci_base0, data);
+}
+
void
qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem)
{
- QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
+ int err;
+ QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)), &err);
}
static int
@@ -365,9 +401,9 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
return 0;
}
-static int
+int
qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
- __le16 vlan_id, unsigned op)
+ __le16 vlan_id, u8 op)
{
struct qlcnic_nic_req req;
struct qlcnic_mac_req *mac_req;
@@ -410,7 +446,7 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
}
memcpy(cur->mac_addr, addr, ETH_ALEN);
- if (qlcnic_sre_macaddr_change(adapter,
+ if (adapter->ahw->hw_ops->change_macvlan(adapter,
cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
kfree(cur);
return -EIO;
@@ -461,7 +497,7 @@ send_fw_cmd:
adapter->mac_learn = 0;
}
- qlcnic_nic_set_promisc(adapter, mode);
+ adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
}
int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
@@ -490,7 +526,7 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
- qlcnic_sre_macaddr_change(adapter,
+ adapter->ahw->hw_ops->change_macvlan(adapter,
cur->mac_addr, 0, QLCNIC_MAC_DEL);
list_del(&cur->list);
kfree(cur);
@@ -511,7 +547,7 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
{
if (jiffies >
(QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
- qlcnic_sre_macaddr_change(adapter,
+ adapter->ahw->hw_ops->change_macvlan(adapter,
tmp_fil->faddr, tmp_fil->vlan_id,
tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
QLCNIC_MAC_DEL);
@@ -536,9 +572,10 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
head = &(adapter->fhash.fhead[i]);
hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
- qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr,
- tmp_fil->vlan_id, tmp_fil->vlan_id ?
- QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL);
+ adapter->ahw->hw_ops->change_macvlan(adapter,
+ tmp_fil->faddr, tmp_fil->vlan_id,
+ tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+ QLCNIC_MAC_DEL);
spin_lock_bh(&adapter->mac_learn_lock);
adapter->fhash.fnum--;
hlist_del(&tmp_fil->fnode);
@@ -573,7 +610,8 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
if (qlcnic_set_fw_loopback(adapter, mode))
return -EIO;
- if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
+ if (adapter->ahw->hw_ops->config_promisc_mode(adapter,
+ VPORT_MISS_MODE_ACCEPT_ALL)) {
qlcnic_set_fw_loopback(adapter, 0);
return -EIO;
}
@@ -582,11 +620,11 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
return 0;
}
-void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
+int qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
{
- int mode = VPORT_MISS_MODE_DROP;
struct net_device *netdev = adapter->netdev;
+ mode = VPORT_MISS_MODE_DROP;
qlcnic_set_fw_loopback(adapter, 0);
if (netdev->flags & IFF_PROMISC)
@@ -594,14 +632,15 @@ void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
else if (netdev->flags & IFF_ALLMULTI)
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
- qlcnic_nic_set_promisc(adapter, mode);
+ adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
msleep(1000);
+ return 0;
}
/*
* Send the interrupt coalescing parameter set by ethtool to the card.
*/
-int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
+void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
{
struct qlcnic_nic_req req;
int rv;
@@ -623,7 +662,6 @@ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
if (rv != 0)
dev_err(&adapter->netdev->dev,
"Could not send interrupt coalescing parameters\n");
- return rv;
}
int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
@@ -681,9 +719,6 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
return rv;
}
-
-#define RSS_HASHTYPE_IP_TCP 0x3
-
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
{
struct qlcnic_nic_req req;
@@ -727,7 +762,7 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
return rv;
}
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
+void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
{
struct qlcnic_nic_req req;
struct qlcnic_ipaddr *ipa;
@@ -747,10 +782,8 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0)
dev_err(&adapter->netdev->dev,
- "could not notify %s IP 0x%x reuqest\n",
+ "could not notify %s IP 0x%x request\n",
(cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
-
- return rv;
}
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable)
@@ -758,14 +791,12 @@ int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable)
struct qlcnic_nic_req req;
u64 word;
int rv;
-
memset(&req, 0, sizeof(struct qlcnic_nic_req));
req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(enable | (enable << 8));
-
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0)
dev_err(&adapter->netdev->dev,
@@ -963,7 +994,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
}
u32
-qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
+qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *err)
{
unsigned long flags;
int rv;
@@ -989,6 +1020,9 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
dev_err(&adapter->pdev->dev,
"%s: invalid offset: 0x%016lx\n", __func__, off);
dump_stack();
+ if (err)
+ *err = -1;
+
return -1;
}
@@ -1003,36 +1037,19 @@ qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, u32 offset)
return addr;
}
-
-static int
-qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter,
- u64 addr, u32 *start)
-{
- u32 window;
-
- window = OCM_WIN_P3P(addr);
-
- writel(window, adapter->ahw->ocm_win_crb);
- /* read back to flush */
- readl(adapter->ahw->ocm_win_crb);
-
- *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);
- return 0;
-}
-
static int
-qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
- u64 *data, int op)
+qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u32 window,
+ u64 off, u64 *data, int op)
{
void __iomem *addr;
- int ret;
u32 start;
mutex_lock(&adapter->ahw->mem_lock);
- ret = qlcnic_pci_set_window_2M(adapter, off, &start);
- if (ret != 0)
- goto unlock;
+ writel(window, adapter->ahw->ocm_win_crb);
+ /* read back to flush */
+ readl(adapter->ahw->ocm_win_crb);
+ start = QLCNIC_PCI_OCM0_2M + off;
addr = adapter->ahw->pci_base0 + start;
@@ -1041,10 +1058,12 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
else /* write */
writeq(*data, addr);
-unlock:
- mutex_unlock(&adapter->ahw->mem_lock);
+ /* Set window to 0 */
+ writel(0, adapter->ahw->ocm_win_crb);
+ readl(adapter->ahw->ocm_win_crb);
- return ret;
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return 0;
}
void
@@ -1071,52 +1090,79 @@ qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
#define MAX_CTL_CHECK 1000
+/* Set MS memory control data for different chip type*/
+static void
+qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off,
+ struct qlcnic_ms_reg_ctrl *ms)
+{
+ ms->control = QLCNIC_MS_CTRL;
+ ms->low = QLCNIC_MS_ADDR_LO;
+ ms->hi = QLCNIC_MS_ADDR_HI;
+ if (off & 0xf) {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_LO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_LO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_HI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_ULO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_ULO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_UHI;
+ } else {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_ULO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_ULO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_UHI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_LO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_LO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_HI;
+ }
+ if (QLCNIC_IS_83XX(adapter)) {
+ ms->ocm_window = OCM_WIN_83XX(off);
+ ms->off = GET_83XX_OCM_OFFSET(off);
+ } else {
+ ms->ocm_window = OCM_WIN_P3P(off);
+ ms->off = GET_MEM_OFFS_2M(off);
+ }
+}
+
int
qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
u64 off, u64 data)
{
- int i, j, ret;
+ int j, ret = 0;
u32 temp, off8;
- void __iomem *mem_crb;
+ struct qlcnic_ms_reg_ctrl ms;
/* Only 64-bit aligned access */
if (off & 7)
return -EIO;
- /* P3 onward, test agent base for MIU and SIU is same */
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter->ahw,
- QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX)) ||
+ (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX))))
+ return -EIO;
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter->ahw,
- QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ qlcnic_set_ms_controls(adapter, off, &ms);
if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
- return qlcnic_pci_mem_access_direct(adapter, off, &data, 1);
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, &data, 1);
- return -EIO;
-
-correct:
off8 = off & ~0xf;
mutex_lock(&adapter->ahw->mem_lock);
- writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
- writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
- i = 0;
- writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE),
- (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1126,24 +1172,18 @@ correct:
goto done;
}
- i = (off & 0xf) ? 0 : 2;
- writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)),
- mem_crb + MIU_TEST_AGT_WRDATA(i));
- writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)),
- mem_crb + MIU_TEST_AGT_WRDATA(i+1));
- i = (off & 0xf) ? 2 : 0;
+ /* This is the modify part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0]));
+ qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1]));
+ /* This is the write part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff);
+ qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff);
- writel(data & 0xffffffff,
- mem_crb + MIU_TEST_AGT_WRDATA(i));
- writel((data >> 32) & 0xffffffff,
- mem_crb + MIU_TEST_AGT_WRDATA(i+1));
-
- writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
- (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_START);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1169,45 +1209,36 @@ qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
int j, ret;
u32 temp, off8;
u64 val;
- void __iomem *mem_crb;
+ struct qlcnic_ms_reg_ctrl ms;
/* Only 64-bit aligned access */
if (off & 7)
return -EIO;
+ if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX)) ||
+ (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX))))
+ return -EIO ;
- /* P3 onward, test agent base for MIU and SIU is same */
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter->ahw,
- QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
-
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
- mem_crb = qlcnic_get_ioaddr(adapter->ahw,
- QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
- goto correct;
- }
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ qlcnic_set_ms_controls(adapter, off, &ms);
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) {
- return qlcnic_pci_mem_access_direct(adapter,
- off, data, 0);
- }
+ if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, data, 0);
- return -EIO;
+ mutex_lock(&adapter->ahw->mem_lock);
-correct:
off8 = off & ~0xf;
- mutex_lock(&adapter->ahw->mem_lock);
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
- writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
- writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
- writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
- writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = readl(mem_crb + TEST_AGT_CTRL);
+ temp = qlcnic_ind_rd(adapter, ms.control);
if ((temp & TA_CTL_BUSY) == 0)
break;
}
@@ -1218,13 +1249,10 @@ correct:
"failed to read through agent\n");
ret = -EIO;
} else {
- off8 = MIU_TEST_AGT_RDDATA_LO;
- if (off & 0xf)
- off8 = MIU_TEST_AGT_RDDATA_UPPER_LO;
- temp = readl(mem_crb + off8 + 4);
+ temp = qlcnic_ind_rd(adapter, ms.rd[3]);
val = (u64)temp << 32;
- val |= readl(mem_crb + off8);
+ val |= qlcnic_ind_rd(adapter, ms.rd[2]);
*data = val;
ret = 0;
}
@@ -1236,7 +1264,7 @@ correct:
int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
{
- int offset, board_type, magic;
+ int offset, board_type, magic, err;
struct pci_dev *pdev = adapter->pdev;
struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -1257,7 +1285,7 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
ahw->board_type = board_type;
if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
- u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I);
+ u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I, &err);
if ((gpio & 0x8000) == 0)
board_type = QLCNIC_BRDTYPE_P3P_10G_TP;
}
@@ -1296,11 +1324,12 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
int
qlcnic_wol_supported(struct qlcnic_adapter *adapter)
{
+ int err;
u32 wol_cfg;
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
if (wol_cfg & (1UL << adapter->portnum)) {
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
if (wol_cfg & (1 << adapter->portnum))
return 1;
}
@@ -1349,9 +1378,10 @@ void qlcnic_get_ocm_win(struct qlcnic_hardware_context *ahw)
PCIX_OCM_WINDOW_REG(ahw->pci_func)));
}
-void qlcnic_82xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
+void qlcnic_read_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
+ int err;
u32 data;
u64 qmdata;
@@ -1359,12 +1389,12 @@ void qlcnic_82xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
memcpy(buf, &qmdata, size);
} else {
- data = QLCRD32(adapter, offset);
+ data = QLCRD32(adapter, offset, &err);
memcpy(buf, &data, size);
}
}
-void qlcnic_82xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
+void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
u32 data;
@@ -1378,3 +1408,23 @@ void qlcnic_82xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
QLCWR32(adapter, offset, data);
}
}
+
+int qlcnic_api_lock(struct qlcnic_adapter *adapter)
+{
+ return qlcnic_pcie_sem_lock(adapter, 5, 0);
+}
+
+void qlcnic_api_unlock(struct qlcnic_adapter *adapter)
+{
+ qlcnic_pcie_sem_unlock(adapter, 5);
+}
+
+void qlcnic_add_sysfs(struct qlcnic_adapter *adapter)
+{
+ qlcnic_create_diag_entries(adapter);
+}
+
+void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter)
+{
+ qlcnic_remove_diag_entries(adapter);
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 82c466c..2f3966e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -3,18 +3,195 @@
#include "qlcnic.h"
+#define MASK(n) ((1ULL<<(n))-1)
+#define OCM_WIN_P3P(addr) (addr & 0xffc0000)
+#define OCM_WIN_83XX(addr) (addr & 0xFFE0000)
+
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+#define GET_83XX_OCM_OFFSET(addr) (addr & MASK(17))
+
+#define CRB_BLK(off) ((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
+#define CRB_WINDOW_2M (0x130060)
+#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define CRB_INDIRECT_2M (0x1e0000UL)
+
+
+
/* List of PCI device IDs */
-#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
-#define QLCNIC_P3P_BAR0_LENGTH 0x00200000UL
+#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
+#define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030
+#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
+#define QLCNIC_83XX_BAR0_LENGTH 0x4000
+
+#define QLCNIC_IS_83XX(adapter) \
+ (((adapter)->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? 1 : 0)
+
+#define QLCNIC_IS_82XX(adapter) \
+ (((adapter)->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? 1 : 0)
+
+/* Existing registers in 83xx and 82xx */
+enum qlcnic_regs {
+ QLCNIC_PEG_HALT_STATUS1 = 0,
+ QLCNIC_PEG_HALT_STATUS2,
+ QLCNIC_PEG_ALIVE_COUNTER,
+ QLCNIC_FLASH_LOCK_OWNER,
+ QLCNIC_FW_CAPABILITIES,
+ QLCNIC_CRB_DRV_ACTIVE,
+ QLCNIC_CRB_DEV_STATE,
+ QLCNIC_CRB_DRV_STATE,
+ QLCNIC_CRB_DRV_SCRATCH,
+ QLCNIC_CRB_DEV_PARTITION_INFO,
+ QLCNIC_CRB_DRV_IDC_VER,
+ QLCNIC_FW_VERSION_MAJOR,
+ QLCNIC_FW_VERSION_MINOR,
+ QLCNIC_FW_VERSION_SUB,
+ QLCNIC_CRB_DEV_NPAR_STATE,
+ QLCNIC_FW_IMG_VALID,
+ QLCNIC_CMDPEG_STATE,
+ QLCNIC_RCVPEG_STATE,
+ QLCNIC_ASIC_TEMP,
+ QLCNIC_FW_API,
+ QLCNIC_DRV_OP_MODE,
+ QLCNIC_FLASH_LOCK,
+ QLCNIC_FLASH_UNLOCK,
+};
+
+struct qlcnic_ms_reg_ctrl {
+ u32 ocm_window;
+ u32 control;
+ u32 hi;
+ u32 low;
+ u32 rd[4];
+ u32 wd[4];
+ u64 off;
+};
+
+/* Read from an address offset from BAR0, existing registers */
+#define QLCRD(a, addr) \
+ readl(((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr]))
+/* Write to an address offset from BAR0, existing registers */
+#define QLCWR(a, addr, value) \
+ writel(value, ((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr]))
+
+/* Read from a direct address offset from BAR0, additional registers */
+#define QLCRDX(ahw, addr) \
+ readl(((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr]))
+/* Write to a direct address offset from BAR0, additional registers */
+#define QLCWRX(ahw, addr, value) \
+ writel(value, (((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr])))
+
+#define QLCNIC_READ_LINK_SPEED(adapter, pcifn, err)\
+ QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn), err)
+
+/* Mailbox ownership */
+#define QLCNIC_GET_OWNER(val) \
+ ((val) & (BIT_0 | BIT_1))
+#define QLCNIC_SET_OWNER 1
+#define QLCNIC_CLR_OWNER 0
+#define QLCNIC_MBX_TIMEOUT 10000
+
+#define QLCNIC_CMD_CONFIGURE_IP_ADDR 0x1
+#define QLCNIC_CMD_CONFIG_INTRPT 0x2
+#define QLCNIC_CMD_CREATE_RX_CTX 0x7
+#define QLCNIC_CMD_DESTROY_RX_CTX 0x8
+#define QLCNIC_CMD_CREATE_TX_CTX 0x9
+#define QLCNIC_CMD_DESTROY_TX_CTX 0xa
+#define QLCNIC_CMD_CONFIGURE_LRO 0xC
+#define QLCNIC_CMD_CONFIGURE_MAC_LEARNING 0xD
+#define QLCNIC_CMD_GET_STATISTICS 0xF
+#define QLCNIC_CMD_INTRPT_TEST 0x11
+#define QLCNIC_CMD_SET_MTU 0x12
+#define QLCNIC_CMD_READ_PHY 0x13
+#define QLCNIC_CMD_WRITE_PHY 0x14
+#define QLCNIC_CMD_READ_HW_REG 0x15
+#define QLCNIC_CMD_GET_FLOW_CTL 0x16
+#define QLCNIC_CMD_SET_FLOW_CTL 0x17
+#define QLCNIC_CMD_READ_MAX_MTU 0x18
+#define QLCNIC_CMD_READ_MAX_LRO 0x19
+#define QLCNIC_CMD_MAC_ADDRESS 0x1f
+#define QLCNIC_CMD_GET_PCI_INFO 0x20
+#define QLCNIC_CMD_GET_NIC_INFO 0x21
+#define QLCNIC_CMD_SET_NIC_INFO 0x22
+#define QLCNIC_CMD_GET_ESWITCH_CAPABILITY 0x24
+#define QLCNIC_CMD_TOGGLE_ESWITCH 0x25
+#define QLCNIC_CMD_GET_ESWITCH_STATUS 0x26
+#define QLCNIC_CMD_SET_PORTMIRRORING 0x27
+#define QLCNIC_CMD_CONFIGURE_ESWITCH 0x28
+#define QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG 0x29
+#define QLCNIC_CMD_GET_ESWITCH_STATS 0x2a
+#define QLCNIC_CMD_CONFIG_PORT 0x2e
+#define QLCNIC_CMD_TEMP_SIZE 0x2f
+#define QLCNIC_CMD_GET_TEMP_HDR 0x30
+#define QLCNIC_CMD_GET_MAC_STATS 0x37
+#define QLCNIC_CMD_CONFIGURE_RSS 0x41
+#define QLCNIC_CMD_CONFIG_INTR_COAL 0x43
+#define QLCNIC_CMD_CONFIGURE_LED 0x44
+#define QLCNIC_CMD_CONFIG_MAC_VLAN 0x45
+#define QLCNIC_CMD_GET_LINK_EVENT 0x48
+#define QLCNIC_CMD_CONFIGURE_MAC_RX_MODE 0x49
+#define QLCNIC_CMD_CONFIGURE_HW_LRO 0x4A
+#define QLCNIC_CMD_INIT_NIC_FUNC 0x60
+#define QLCNIC_CMD_STOP_NIC_FUNC 0x61
+#define QLCNIC_CMD_IDC_ACK 0x63
+#define QLCNIC_CMD_SET_PORT_CONFIG 0x66
+#define QLCNIC_CMD_GET_PORT_CONFIG 0x67
+#define QLCNIC_CMD_GET_LINK_STATUS 0x68
+#define QLCNIC_CMD_SET_LED_CONFIG 0x69
+#define QLCNIC_CMD_GET_LED_CONFIG 0x6A
+
+#define QLC_TCP_HDR_SIZE 20
+#define QLC_TCP_TS_OPTION_SIZE 12
+#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
+
+#define QLCNIC_INTRPT_INTX 1
+#define QLCNIC_INTRPT_MSIX 3
+#define QLCNIC_INTRPT_ADD 1
+#define QLCNIC_INTRPT_DEL 2
+
+#define QLCNIC_GET_CURRENT_MAC 1
+#define QLCNIC_SET_STATION_MAC 2
+#define QLCNIC_GET_DEFAULT_MAC 3
+#define QLCNIC_GET_FAC_DEF_MAC 4
+#define QLCNIC_SET_FAC_DEF_MAC 5
+
+#define QLCNIC_MBX_LINK_EVENT 0x8001
+#define QLCNIC_MBX_COMP_EVENT 0x8100
+#define QLCNIC_MBX_REQUEST_EVENT 0x8101
+#define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102
+#define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130
+#define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131
+
+struct qlcnic_mailbox_metadata {
+ u32 cmd;
+ u32 in_args;
+ u32 out_args;
+};
#define QLCNIC_BAR_LENGTH(dev_id, bar) \
do { \
- if (dev_id == PCI_DEVICE_ID_QLOGIC_QLE824X)\
- *bar = QLCNIC_P3P_BAR0_LENGTH; \
- else \
+ switch (dev_id) { \
+ case PCI_DEVICE_ID_QLOGIC_QLE824X: \
+ *bar = QLCNIC_82XX_BAR0_LENGTH; \
+ break; \
+ case PCI_DEVICE_ID_QLOGIC_QLE834X: \
+ *bar = QLCNIC_83XX_BAR0_LENGTH; \
+ break; \
+ default: \
*bar = 0; \
+ } \
} while (0)
+/* Make a handle with reference handle (0:14) and RDS ring
+ * number (15).
+ */
+#define QLCNIC_MAKE_REF_HANDLE(adapter, handle, ring_id) \
+ ((adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? \
+ ((handle) | ((ring_id) << 15)) : handle)
+
+#define QLCNIC_FETCH_RING_ID(handle) \
+ ((handle) >> 63)
+
#define QLCNIC_ENABLE_INTR(adapter, crb) { \
writel(1, crb); \
if (!QLCNIC_IS_MSI_FAMILY(adapter)) \
@@ -25,4 +202,28 @@ do { \
writel(0, crb); \
}
+#define QLCNIC_MBX_RSP_OK 1
+#define QLCNIC_MBX_PORT_RSP_OK 0x1a
+
+#define QLCNIC_MBX_RSP(reg)\
+ LSW(reg)
+#define QLCNIC_MBX_NUM_REGS(reg)\
+ (MSW(reg) & 0x1FF)
+#define QLCNIC_MBX_STATUS(reg) \
+ (((reg) >> 25) & 0x7F)
+
+/* Mailbox registers*/
+#define QLCNIC_MBX_HOST(ahw, i) \
+ ((ahw)->pci_base0 + ((i) * 4))
+#define QLCNIC_MBX_FW(ahw, i) \
+ ((ahw)->pci_base0 + 0x800 + ((i) * 4))
+
+#define QLCNIC_IS_TSO_CAPABLE(adapter)\
+ ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+
+#define QLCNIC_IS_VLAN_TX_CAPABLE(adapter) \
+ ((QLCNIC_IS_82XX(adapter)) ?\
+ ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) :\
+ 1)
+
#endif /* __QLCNIC_HDR_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 5a1704e..737adea 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -6,6 +6,7 @@
*/
#include "qlcnic.h"
+#include "qlcnic_hw.h"
struct crb_addr_pair {
u32 addr;
@@ -162,13 +163,12 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
{
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
int ring;
recv_ctx = adapter->recv_ctx;
if (recv_ctx->rds_rings == NULL)
- goto skip_rds;
+ return;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
@@ -176,16 +176,6 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
rds_ring->rx_buf_arr = NULL;
}
kfree(recv_ctx->rds_rings);
-
-skip_rds:
- if (adapter->tx_ring == NULL)
- return;
-
- tx_ring = adapter->tx_ring;
- vfree(tx_ring->cmd_buf_arr);
- tx_ring->cmd_buf_arr = NULL;
- kfree(adapter->tx_ring);
- adapter->tx_ring = NULL;
}
int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
@@ -193,32 +183,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
struct qlcnic_rx_buffer *rx_buf;
int ring, i, size;
- struct qlcnic_cmd_buffer *cmd_buf_arr;
struct net_device *netdev = adapter->netdev;
struct qlcnic_hardware_context *ahw = adapter->ahw;
- size = sizeof(struct qlcnic_host_tx_ring);
- tx_ring = kzalloc(size, GFP_KERNEL);
- if (tx_ring == NULL) {
- dev_err(&netdev->dev, "failed to allocate tx ring struct\n");
- return -ENOMEM;
- }
- adapter->tx_ring = tx_ring;
-
- tx_ring->num_desc = adapter->num_txd;
- tx_ring->txq = netdev_get_tx_queue(netdev, 0);
-
- cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
- if (cmd_buf_arr == NULL) {
- dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n");
- goto err_out;
- }
- tx_ring->cmd_buf_arr = cmd_buf_arr;
-
recv_ctx = adapter->recv_ctx;
size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring);
@@ -250,12 +220,14 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
rds_ring->dma_size + NET_IP_ALIGN;
break;
}
- rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
+ rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
+ vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
if (rds_ring->rx_buf_arr == NULL) {
- dev_err(&netdev->dev, "Failed to allocate "
- "rx buffer ring %d\n", ring);
+ dev_err(&netdev->dev,
+ "Failed to allocate rx buffer ring %d\n", ring);
goto err_out;
}
+ memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
INIT_LIST_HEAD(&rds_ring->free_list);
/*
* Now go through all of them, set reference handles
@@ -321,11 +293,12 @@ static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter)
{
long timeout = 0;
long done = 0;
+ int err;
cond_resched();
while (done == 0) {
- done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS);
+ done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS, &err);
done &= 2;
if (++timeout >= QLCNIC_MAX_ROM_WAIT_USEC) {
dev_err(&adapter->pdev->dev,
@@ -340,6 +313,8 @@ static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter)
static int do_rom_fast_read(struct qlcnic_adapter *adapter,
u32 addr, u32 *valp)
{
+ int err;
+
QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr);
QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 3);
@@ -353,7 +328,7 @@ static int do_rom_fast_read(struct qlcnic_adapter *adapter,
udelay(10);
QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
- *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA);
+ *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA, &err);
return 0;
}
@@ -405,15 +380,15 @@ int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp)
int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
{
- int addr, val;
+ int addr, val, err;
int i, n, init_delay;
struct crb_addr_pair *buf;
unsigned offset;
u32 off;
struct pci_dev *pdev = adapter->pdev;
- QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
- QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, 0);
+ QLCWR(adapter, QLCNIC_RCVPEG_STATE, 0);
/* Halt all the indiviual PEGs and other blocks */
/* disable all I2Q */
@@ -438,7 +413,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, QLCNIC_CRB_NIU + 0xb0000, 0x00);
/* halt sre */
- val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000);
+ val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000, &err);
QLCWR32(adapter, QLCNIC_CRB_SRE + 0x1000, val & (~(0x1)));
/* halt epg */
@@ -560,8 +535,8 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
msleep(1);
- QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
- QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
+ QLCWR(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
+ QLCWR(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
return 0;
}
@@ -572,7 +547,7 @@ static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
do {
- val = QLCRD32(adapter, CRB_CMDPEG_STATE);
+ val = QLCRD(adapter, QLCNIC_CMDPEG_STATE);
switch (val) {
case PHAN_INITIALIZE_COMPLETE:
@@ -588,7 +563,7 @@ static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
} while (--retries);
- QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
out_err:
dev_err(&adapter->pdev->dev, "Command Peg initialization not "
@@ -603,7 +578,7 @@ qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
do {
- val = QLCRD32(adapter, CRB_RCVPEG_STATE);
+ val = QLCRD(adapter, QLCNIC_RCVPEG_STATE);
if (val == PHAN_PEG_RCV_INITIALIZED)
return 0;
@@ -634,7 +609,7 @@ qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
if (err)
return err;
- QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
return err;
}
@@ -645,7 +620,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
int timeo;
u32 val;
- val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
+ val = QLCRD(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
val = QLC_DEV_GET_DRV(val, adapter->portnum);
if ((val & 0x3) != QLCNIC_TYPE_NIC) {
dev_err(&adapter->pdev->dev,
@@ -685,11 +660,12 @@ static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
}
entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
- flt_entry = (struct qlcnic_flt_entry *)vzalloc(entry_size);
+ flt_entry = vmalloc(entry_size);
if (flt_entry == NULL) {
dev_warn(&adapter->pdev->dev, "error allocating memory\n");
return -EIO;
}
+ memset(flt_entry, 0, entry_size);
ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
sizeof(struct qlcnic_flt_header),
@@ -758,10 +734,11 @@ qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
static int
qlcnic_has_mn(struct qlcnic_adapter *adapter)
{
+ int err;
u32 capability;
capability = 0;
- capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY);
+ capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY, &err);
if (capability & QLCNIC_PEG_TUNE_MN_PRESENT)
return 1;
@@ -1084,11 +1061,11 @@ qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
u32 heartbeat, ret = -EIO;
int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
- adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ adapter->heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
do {
msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
- heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
if (heartbeat != adapter->heartbeat) {
ret = QLCNIC_RCODE_SUCCESS;
break;
@@ -1258,7 +1235,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
return -EINVAL;
}
- QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID, QLCNIC_BDINFO_MAGIC);
return 0;
}
@@ -1314,6 +1291,7 @@ next:
void
qlcnic_release_firmware(struct qlcnic_adapter *adapter)
{
- release_firmware(adapter->fw);
+ if (adapter->fw)
+ release_firmware(adapter->fw);
adapter->fw = NULL;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 03b5e3e..1c384f1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -6,17 +6,14 @@
#include "qlcnic.h"
#include "qlcnic_hw.h"
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring);
-
-static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
- u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+ u64 *uaddr, __le16 vlan_id)
{
struct cmd_desc_type0 *hwdesc;
struct qlcnic_nic_req *req;
struct qlcnic_mac_req *mac_req;
struct qlcnic_vlan_req *vlan_req;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
u32 producer;
u64 word;
@@ -54,6 +51,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct qlcnic_filter *fil, *tmp_fil;
struct hlist_node *tmp_hnode, *n;
struct hlist_head *head;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
u64 src_addr = 0;
__le16 vlan_id = 0;
u8 hindex;
@@ -77,8 +75,8 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
if (jiffies >
(QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
- qlcnic_change_filter(adapter, src_addr, vlan_id,
- tx_ring);
+ ahw->hw_ops->change_l2_filter(adapter,
+ &src_addr, vlan_id);
tmp_fil->ftime = jiffies;
return;
}
@@ -88,7 +86,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
if (!fil)
return;
- qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+ ahw->hw_ops->change_l2_filter(adapter, &src_addr, vlan_id);
fil->ftime = jiffies;
fil->vlan_id = vlan_id;
@@ -435,7 +433,6 @@ drop_packet:
void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
{
struct net_device *netdev = adapter->netdev;
-
if (adapter->ahw->linkup && !linkup) {
netdev_info(netdev, "NIC Link is down\n");
adapter->ahw->linkup = 0;
@@ -453,7 +450,8 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
}
}
-static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring, int budget)
{
u32 sw_consumer, hw_consumer;
int count = 0, i;
@@ -462,7 +460,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct qlcnic_skb_frag *frag;
int done;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
if (!spin_trylock(&adapter->tx_clean_lock))
return 1;
@@ -490,7 +487,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
}
sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
- if (++count >= MAX_STATUS_HANDLE)
+ if (++count >= budget)
break;
}
@@ -537,7 +534,8 @@ int qlcnic_poll(struct napi_struct *napi, int budget)
int tx_complete;
int work_done;
- tx_complete = qlcnic_process_cmd_ring(adapter);
+ tx_complete = qlcnic_process_cmd_ring(adapter, adapter->tx_ring,
+ budget);
work_done = qlcnic_process_rcv_ring(sds_ring, budget);
@@ -569,7 +567,7 @@ int qlcnic_rx_poll(struct napi_struct *napi, int budget)
return work_done;
}
-static void
+void
qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
struct qlcnic_fw_msg *msg)
{
@@ -581,7 +579,6 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
struct net_device *netdev = adapter->netdev;
adapter->ahw->has_link_events = 1;
-
cable_OUI = msg->body[1] & 0xffffffff;
cable_len = (msg->body[1] >> 32) & 0xffff;
link_speed = (msg->body[1] >> 48) & 0xffff;
@@ -616,7 +613,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
adapter->ahw->link_speed = link_speed;
}
-static void
+void
qlcnic_handle_fw_message(int desc_cnt, int index,
struct qlcnic_host_sds_ring *sds_ring)
{
@@ -638,7 +635,6 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
adapter = sds_ring->adapter;
dev = &adapter->pdev->dev;
opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
-
switch (opcode) {
case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
qlcnic_handle_linkevent(adapter, &msg);
@@ -670,7 +666,7 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
}
}
-static int
+int
qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
struct qlcnic_host_rds_ring *rds_ring,
struct qlcnic_rx_buffer *buffer)
@@ -702,7 +698,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
return 0;
}
-static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
{
struct qlcnic_rx_buffer *buffer;
@@ -735,7 +731,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
return skb;
}
-static inline int
+inline int
qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
u16 *vlan_tag)
{
@@ -819,10 +815,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
return buffer;
}
-#define QLC_TCP_HDR_SIZE 20
-#define QLC_TCP_TS_OPTION_SIZE 12
-#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
-
static struct qlcnic_rx_buffer *
qlcnic_process_lro(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring,
@@ -913,7 +905,8 @@ qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
u64 sts_data0, sts_data1;
int count = 0;
- int opcode, ring, desc_cnt;
+ int opcode, desc_cnt;
+ u8 ring;
u32 consumer = sds_ring->consumer;
while (count < max) {
@@ -979,7 +972,6 @@ skip:
spin_unlock(&rds_ring->lock);
}
- qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
}
if (count) {
@@ -992,7 +984,7 @@ skip:
void
qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
+ struct qlcnic_host_rds_ring *rds_ring, u8 ring_id)
{
struct rcv_desc *pdesc;
struct qlcnic_rx_buffer *buffer;
@@ -1018,9 +1010,9 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
/* make a rcv descriptor */
pdesc = &rds_ring->desc_head[producer];
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->reference_handle = cpu_to_le16(QLCNIC_MAKE_REF_HANDLE(
+ adapter, buffer->ref_handle, ring_id));
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-
producer = get_next_index(producer, rds_ring->num_desc);
}
@@ -1031,9 +1023,9 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
}
}
-static void
+void
qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *rds_ring)
+ struct qlcnic_host_rds_ring *rds_ring, u8 ring_id)
{
struct rcv_desc *pdesc;
struct qlcnic_rx_buffer *buffer;
@@ -1061,10 +1053,10 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
/* make a rcv descriptor */
pdesc = &rds_ring->desc_head[producer];
- pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->reference_handle = cpu_to_le16(QLCNIC_MAKE_REF_HANDLE(
+ adapter, buffer->ref_handle, ring_id));
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-
producer = get_next_index(producer, rds_ring->num_desc);
}
@@ -1076,7 +1068,7 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
spin_unlock(&rds_ring->lock);
}
-static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
+void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
{
int i;
unsigned char *data = skb->data;
@@ -1172,24 +1164,3 @@ qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
sds_ring->consumer = consumer;
writel(consumer, sds_ring->crb_sts_consumer);
}
-
-void
-qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
- u8 alt_mac, u8 *mac)
-{
- u32 mac_low, mac_high;
- int i;
-
- mac_low = off1;
- mac_high = off2;
-
- if (alt_mac) {
- mac_low |= (mac_low >> 16) | (mac_high << 16);
- mac_high >>= 16;
- }
-
- for (i = 0; i < 2; i++)
- mac[i] = (u8)(mac_high >> ((1 - i) * 8));
- for (i = 2; i < 6; i++)
- mac[i] = (u8)(mac_low >> ((5 - i) * 8));
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 56c03f5..829dfa5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2,10 +2,15 @@
* QLogic qlcnic NIC Driver
* Copyright (c) 2009-2010 QLogic Corporation
*
+ * PCI searching functions pci_get_domain_bus_and_slot & pci_channel_offline
+ * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
+ * David Mosberger-Tang
+ * Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
+ * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>.
+ *
* See LICENSE.qlcnic for copyright and licensing details.
*/
-#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
@@ -14,6 +19,7 @@
#include <linux/swab.h>
#include <linux/dma-mapping.h>
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
@@ -34,23 +40,23 @@ static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0444);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
-static int use_msi = 1;
+int use_msi = 1;
module_param(use_msi, int, 0444);
MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
-static int use_msi_x = 1;
+int use_msi_x = 1;
module_param(use_msi_x, int, 0444);
MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
-static int auto_fw_reset = 1;
+int auto_fw_reset = 1;
module_param(auto_fw_reset, int, 0644);
MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
-static int load_fw_file;
+int load_fw_file;
module_param(load_fw_file, int, 0444);
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
-static int qlcnic_config_npars;
+int qlcnic_config_npars;
module_param(qlcnic_config_npars, int, 0444);
MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
@@ -63,9 +69,6 @@ static void qlcnic_tx_timeout(struct net_device *netdev);
static void qlcnic_attach_work(struct work_struct *work);
static void qlcnic_fwinit_work(struct work_struct *work);
static void qlcnic_fw_poll_work(struct work_struct *work);
-static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
- work_func_t func, int delay);
-static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev);
#endif
@@ -78,9 +81,10 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
static irqreturn_t qlcnic_intr(int irq, void *data);
static irqreturn_t qlcnic_msi_intr(int irq, void *data);
static irqreturn_t qlcnic_msix_intr(int irq, void *data);
+static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data);
+static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *);
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
-static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
static int qlcnic_start_firmware(struct qlcnic_adapter *);
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
@@ -90,9 +94,6 @@ static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
-static int qlcnic_vlan_rx_add(struct net_device *, u16);
-static int qlcnic_vlan_rx_del(struct net_device *, u16);
-
/* PCI Device ID Table */
#define ENTRY(device) \
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -100,6 +101,7 @@ static int qlcnic_vlan_rx_del(struct net_device *, u16);
static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
+ ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
{0,}
};
@@ -120,10 +122,60 @@ static const u32 msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};
+static const u32 qlcnic_reg_tbl[] = {
+ 0x1B20A8, /* PEG_HALT_STAT1 */
+ 0x1B20AC, /* PEG_HALT_STAT2 */
+ 0x1B20B0, /* FW_HEARTBEAT */
+ 0x1B2100, /* LOCK ID */
+ 0x1B2128, /* FW_CAPABILITIES */
+ 0x1B2138, /* drv active */
+ 0x1B2140, /* dev state */
+ 0x1B2144, /* drv state */
+ 0x1B2148, /* drv scratch */
+ 0x1B214C, /* dev partition info */
+ 0x1B2174, /* drv idc ver */
+ 0x1B2150, /* fw version major */
+ 0x1B2154, /* fw version minor */
+ 0x1B2158, /* fw version sub */
+ 0x1B019C, /* npar state */
+ 0x1B21FC, /* FW_IMG_VALID */
+ 0x1B2250, /* CMD_PEG_STATE */
+ 0x1B233C, /* RCV_PEG_STATE */
+ 0x1B23B4, /* ASIC TEMP */
+ 0x1B216C, /* FW api */
+ 0x1B2170, /* drv op mode */
+ 0x13C010, /* flash lock */
+ 0x13C014, /* flash unlock */
+};
+
+static const struct qlcnic_brdinfo qlcnic_boards[] = {
+ {0x1077, 0x8020, 0x1077, 0x203,
+ "8200 Series Single Port 10GbE Converged Network Adapter "
+ "(TCP/IP Networking)"},
+ {0x1077, 0x8020, 0x1077, 0x207,
+ "8200 Series Dual Port 10GbE Converged Network Adapter "
+ "(TCP/IP Networking)"},
+ {0x1077, 0x8020, 0x1077, 0x20b,
+ "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x20c,
+ "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x20f,
+ "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x103c, 0x3733,
+ "NC523SFP 10Gb 2-port Server Adapter"},
+ {0x1077, 0x8020, 0x103c, 0x3346,
+ "CN1000Q Dual Port Converged Network Adapter"},
+ {0x1077, 0x8020, 0x1077, 0x210,
+ "QME8242-k 10GbE Dual Port Mezzanine Card"},
+ {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
+};
+
+#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
+
static const
struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
-static int
+int
qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
{
int size = sizeof(struct qlcnic_host_sds_ring) * count;
@@ -133,7 +185,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
return recv_ctx->sds_rings == NULL;
}
-static void
+void
qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
{
if (recv_ctx->sds_rings != NULL)
@@ -142,6 +194,65 @@ qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
recv_ctx->sds_rings = NULL;
}
+static void
+qlcnic_free_tx_rings(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ if (tx_ring && tx_ring->cmd_buf_arr != NULL) {
+ vfree(tx_ring->cmd_buf_arr);
+ tx_ring->cmd_buf_arr = NULL;
+ }
+ }
+ if (adapter->tx_ring != NULL)
+ kfree(adapter->tx_ring);
+}
+
+int
+qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+ int ring, size;
+ struct qlcnic_host_tx_ring *tx_ring;
+ struct qlcnic_cmd_buffer *cmd_buf_arr;
+
+ size = adapter->max_drv_tx_rings * sizeof(struct qlcnic_host_tx_ring);
+ tx_ring = kzalloc(size, GFP_KERNEL);
+ if (tx_ring == NULL) {
+ dev_err(&netdev->dev, "failed to allocate tx rings\n");
+ return -ENOMEM;
+ }
+ adapter->tx_ring = tx_ring;
+
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ tx_ring->num_desc = adapter->num_txd;
+ tx_ring->txq = netdev_get_tx_queue(netdev, ring);
+ cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
+ if (cmd_buf_arr == NULL) {
+ dev_err(&netdev->dev,
+ "failed to allocate cmd buffer ring\n");
+ qlcnic_free_tx_rings(adapter);
+ return -ENOMEM;
+ }
+ memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
+ tx_ring->cmd_buf_arr = cmd_buf_arr;
+ }
+
+ if (QLCNIC_IS_83XX(adapter)) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ tx_ring->adapter = adapter;
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ tx_ring->irq = adapter->msix_entries[adapter->
+ max_sds_rings + ring].vector;
+ }
+ }
+ return 0;
+}
+
static int
qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
@@ -154,13 +265,17 @@ qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
-
if (ring == adapter->max_sds_rings - 1)
netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
- QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
+ QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
else
- netif_napi_add(netdev, &sds_ring->napi,
- qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2);
+ netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
+ QLCNIC_NETDEV_WEIGHT*2);
+ }
+
+ if (qlcnic_alloc_tx_rings(adapter, netdev)) {
+ qlcnic_free_sds_rings(recv_ctx);
+ return -ENOMEM;
}
return 0;
@@ -172,6 +287,7 @@ qlcnic_napi_del(struct qlcnic_adapter *adapter)
int ring;
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_host_tx_ring *tx_ring;
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
@@ -179,6 +295,16 @@ qlcnic_napi_del(struct qlcnic_adapter *adapter)
}
qlcnic_free_sds_rings(adapter->recv_ctx);
+
+ if (QLCNIC_IS_83XX(adapter) &&
+ (adapter->flags & QLCNIC_MSIX_ENABLED)) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ netif_napi_del(&tx_ring->napi);
+ }
+ }
+
+ qlcnic_free_tx_rings(adapter);
}
static void
@@ -248,11 +374,11 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
return -EOPNOTSUPP;
if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
+ return -EINVAL;
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
netif_device_detach(netdev);
- qlcnic_napi_disable(adapter);
+ adapter->ahw->hw_ops->napi_disable(adapter);
}
memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len);
@@ -261,11 +387,38 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
netif_device_attach(netdev);
- qlcnic_napi_enable(adapter);
+ adapter->ahw->hw_ops->napi_enable(adapter);
}
return 0;
}
+static int
+qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ set_bit(vid, adapter->vlans);
+ return 0;
+}
+
+static int
+qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+
+ qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
+ clear_bit(vid, adapter->vlans);
+ return 0;
+}
+
+static void
+qlcnic_cancel_idc_work(struct qlcnic_adapter *adapter)
+{
+ while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ usleep_range(10000, 11000);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+}
+
static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_open = qlcnic_open,
.ndo_stop = qlcnic_close,
@@ -278,41 +431,65 @@ static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_fix_features = qlcnic_fix_features,
.ndo_set_features = qlcnic_set_features,
.ndo_tx_timeout = qlcnic_tx_timeout,
- .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add,
- .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del,
+ .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add,
+ .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = qlcnic_poll_controller,
#endif
};
-static const struct net_device_ops qlcnic_netdev_failed_ops = {
- .ndo_open = qlcnic_open,
-};
-
static struct qlcnic_nic_template qlcnic_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
- .start_firmware = qlcnic_start_firmware
+ .start_firmware = qlcnic_start_firmware,
+ .request_reset = qlcnic_dev_request_reset,
+ .cancel_idc_work = qlcnic_cancel_idc_work,
+ .napi_add = qlcnic_napi_add,
+ .config_ipaddr = qlcnic_config_ipaddr,
+ .clear_legacy_intr = qlcnic_clear_legacy_intr,
};
-static struct qlcnic_nic_template qlcnic_vf_ops = {
+struct qlcnic_nic_template qlcnic_vf_ops = {
.config_bridged_mode = qlcnicvf_config_bridged_mode,
.config_led = qlcnicvf_config_led,
.start_firmware = qlcnicvf_start_firmware
};
-static struct qlcnic_hardware_ops qlcnic_82xx_ops = {
- .read_crb = qlcnic_82xx_read_crb,
- .write_crb = qlcnic_82xx_write_crb,
+static struct qlcnic_hardware_ops qlcnic_hw_ops = {
+ .read_crb = qlcnic_read_crb,
+ .write_crb = qlcnic_write_crb,
.rdreg = qlcnic_hw_read_wx_2M,
.wrtreg = qlcnic_hw_write_wx_2M,
.get_mac_address = qlcnic_get_mac_address,
.setup_intr = qlcnic_setup_intr,
+ .alloc_mbx_args = qlcnic_alloc_mbx_args,
.mbx_cmd = qlcnic_issue_cmd,
.get_func_no = qlcnic_get_func_no,
+ .api_lock = qlcnic_api_lock,
+ .api_unlock = qlcnic_api_unlock,
+ .add_sysfs = qlcnic_add_sysfs,
+ .remove_sysfs = qlcnic_remove_sysfs,
+ .process_lb_rcv_ring_diag = qlcnic_process_rcv_ring_diag,
+ .create_rx_ctx = qlcnic_fw_cmd_create_rx_ctx,
+ .create_tx_ctx = qlcnic_fw_cmd_create_tx_ctx,
+ .setup_link_event = qlcnic_linkevent_request,
+ .get_nic_info = qlcnic_get_nic_info,
+ .get_pci_info = qlcnic_get_pci_info,
+ .set_nic_info = qlcnic_set_nic_info,
+ .change_macvlan = qlcnic_sre_macaddr_change,
+ .napi_enable = qlcnic_napi_enable,
+ .napi_disable = qlcnic_napi_disable,
+ .config_intr_coal = qlcnic_config_intr_coalesce,
+ .config_rss = qlcnic_config_rss,
+ .config_hw_lro = qlcnic_config_hw_lro,
+ .config_loopback = qlcnic_set_lb_mode,
+ .clear_loopback = qlcnic_clear_lb_mode,
+ .config_promisc_mode = qlcnic_nic_set_promisc,
+ .change_l2_filter = qlcnic_change_filter,
+ .get_board_info = qlcnic_get_board_info,
};
-static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
+int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
{
struct pci_dev *pdev = adapter->pdev;
int err = -1, i;
@@ -333,24 +510,34 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
enable_msix:
for (i = 0; i < num_msix; i++)
adapter->msix_entries[i].entry = i;
-
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
if (err == 0) {
adapter->flags |= QLCNIC_MSIX_ENABLED;
- adapter->max_sds_rings = num_msix;
-
+ if (QLCNIC_IS_83XX(adapter)) {
+ adapter->ahw->num_msix = num_msix;
+ /* subtract 2 as 2 vectors are required for
+ mail box and tx ring */
+ adapter->max_sds_rings = num_msix - 2;
+ } else
+ adapter->max_sds_rings = num_msix;
dev_info(&pdev->dev, "using msi-x interrupts\n");
return err;
} else if (err > 0) {
+ dev_info(&pdev->dev, "Didn't get %d vectors\n",
+ num_msix);
num_msix = rounddown_pow_of_two(err);
if (num_msix) {
- dev_info(&pdev->dev,
- "Can't get %d vectors,trying %d vectors\n",
- err, num_msix);
+ if (QLCNIC_IS_83XX(adapter))
+ num_msix += 1;
+ dev_info(&pdev->dev, "Trying %d vectors\n",
+ num_msix);
goto enable_msix;
}
- }
+ } else
+ dev_info(&pdev->dev, "Failed to get %d vectors\n",
+ num_msix);
}
+
return err;
}
@@ -379,18 +566,22 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter->ahw,
ISR_INT_STATE_REG);
+
dev_info(&pdev->dev, "using legacy interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
}
int
-qlcnic_setup_intr(struct qlcnic_adapter *adapter)
+qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
{
int num_msix, err;
+ if (!num_intr)
+ num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
+
if (adapter->ahw->msix_supported)
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
- QLCNIC_DEF_NUM_STS_DESC_RINGS));
+ num_intr));
else
num_msix = 1;
@@ -409,6 +600,13 @@ qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
pci_disable_msix(adapter->pdev);
if (adapter->flags & QLCNIC_MSI_ENABLED)
pci_disable_msi(adapter->pdev);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+
+ if (adapter->ahw->intr_tbl) {
+ vfree(adapter->ahw->intr_tbl);
+ adapter->ahw->intr_tbl = NULL;
+ }
}
static void
@@ -418,19 +616,27 @@ qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
iounmap(ahw->pci_base0);
}
-static int
+int
qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{
struct qlcnic_pci_info *pci_info;
- int i, ret = 0;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ int i, ret = 0, j = 0;
+ u16 act_pci_func;
u8 pfn;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info)
return -ENOMEM;
+ ret = ahw->hw_ops->get_pci_info(adapter, pci_info);
+ if (ret)
+ goto err_pci_info;
+
+ act_pci_func = adapter->ahw->act_pci_func;
+
adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
- QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
+ act_pci_func, GFP_KERNEL);
if (!adapter->npars) {
ret = -ENOMEM;
goto err_pci_info;
@@ -443,21 +649,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
goto err_npars;
}
- ret = qlcnic_get_pci_info(adapter, pci_info);
- if (ret)
- goto err_eswitch;
-
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
pfn = pci_info[i].id;
- if (pfn >= QLCNIC_MAX_PCI_FUNC) {
+
+ if (pfn > QLCNIC_MAX_PCI_FUNC) {
ret = QL_STATUS_INVALID_PARAM;
goto err_eswitch;
}
- adapter->npars[pfn].active = (u8)pci_info[i].active;
- adapter->npars[pfn].type = (u8)pci_info[i].type;
- adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
- adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
- adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
+
+ if (!pci_info[i].active ||
+ (pci_info[i].type != QLCNIC_TYPE_NIC))
+ continue;
+
+ adapter->npars[j].pci_func = pfn;
+ adapter->npars[j].active = (u8)pci_info[i].active;
+ adapter->npars[j].type = (u8)pci_info[i].type;
+ adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
+ adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
+ adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
+ j++;
}
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -485,52 +695,49 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
u32 ref_count;
int i, ret = 1;
u32 data = QLCNIC_MGMT_FUNC;
- void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
/* If other drivers are not in use set their privilege level */
- ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
- ret = qlcnic_api_lock(adapter);
+ ref_count = QLCRD(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ ret = ahw->hw_ops->api_lock(adapter);
if (ret)
goto err_lock;
if (qlcnic_config_npars) {
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- id = i;
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
- id == adapter->ahw->pci_func)
+ for (i = 0; i < ahw->act_pci_func; i++) {
+ id = adapter->npars[i].pci_func;
+ if (id == ahw->pci_func)
continue;
data |= (qlcnic_config_npars &
QLC_DEV_SET_DRV(0xf, id));
}
} else {
- data = readl(priv_op);
- data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) |
+ data = QLCRD(adapter, QLCNIC_DRV_OP_MODE);
+ data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
(QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
- adapter->ahw->pci_func));
+ ahw->pci_func));
}
- writel(data, priv_op);
- qlcnic_api_unlock(adapter);
+ QLCWR(adapter, QLCNIC_DRV_OP_MODE, data);
+ ahw->hw_ops->api_unlock(adapter);
err_lock:
return ret;
}
static void
-qlcnic_check_vf(struct qlcnic_adapter *adapter)
+qlcnic_check_vf(struct qlcnic_adapter *adapter, const struct pci_device_id *ent)
{
void __iomem *priv_op;
u32 op_mode, priv_level;
struct qlcnic_hardware_context *ahw = adapter->ahw;
/* Determine FW API version */
- ahw->fw_hal_version = readl(adapter->ahw->pci_base0 +
- QLCNIC_FW_API);
-
+ ahw->fw_hal_version = QLCRD(adapter, QLCNIC_FW_API);
/* Find PCI function number */
ahw->hw_ops->get_func_no(adapter);
/* Determine function privilege level */
priv_op = ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
- op_mode = readl(priv_op);
+ op_mode = QLCRD(adapter, QLCNIC_DRV_OP_MODE);
if (op_mode == QLC_DEV_DRV_DEFAULT)
priv_level = QLCNIC_MGMT_FUNC;
else
@@ -542,8 +749,9 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
"HAL Version: %d Non Privileged function\n",
ahw->fw_hal_version);
adapter->nic_ops = &qlcnic_vf_ops;
- } else
+ } else {
adapter->nic_ops = &qlcnic_ops;
+ }
}
static int
@@ -559,7 +767,7 @@ qlcnic_setup_pci_map(struct pci_dev *pdev,
mem_len = pci_resource_len(pdev, 0);
QLCNIC_BAR_LENGTH(pdev->device, &bar0_len);
- if (mem_len == bar0_len) {
+ if (mem_len >= bar0_len) {
mem_ptr0 = pci_ioremap_bar(pdev, 0);
if (mem_ptr0 == NULL) {
@@ -570,7 +778,6 @@ qlcnic_setup_pci_map(struct pci_dev *pdev,
} else {
return -EIO;
}
-
dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
ahw->pci_base0 = mem_ptr0;
@@ -605,9 +812,10 @@ static void qlcnic_get_brd_name(struct qlcnic_adapter *adapter, char *name)
sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
}
-static void
+void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
+ int err;
u32 fw_major, fw_minor, fw_build, prev_fw_version;
struct pci_dev *pdev = adapter->pdev;
struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -615,20 +823,22 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
prev_fw_version = adapter->fw_version;
- fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
- fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
- fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
+ fw_major = QLCRD(adapter, QLCNIC_FW_VERSION_MAJOR);
+ fw_minor = QLCRD(adapter, QLCNIC_FW_VERSION_MINOR);
+ fw_build = QLCRD(adapter, QLCNIC_FW_VERSION_SUB);
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
+ err = adapter->ahw->hw_ops->get_board_info(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Error getting board config info.\n");
+ return;
+ }
if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
if (fw_dump->tmpl_hdr == NULL ||
adapter->fw_version > prev_fw_version) {
if (fw_dump->tmpl_hdr)
vfree(fw_dump->tmpl_hdr);
- if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
- dev_info(&pdev->dev,
- "Supports FW dump capability\n");
}
}
@@ -665,20 +875,25 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
{
int err;
struct qlcnic_info nic_info;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
- err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
+ err = ahw->hw_ops->get_nic_info(adapter, &nic_info, ahw->pci_func);
if (err)
return err;
- adapter->ahw->physical_port = (u8)nic_info.phys_port;
- adapter->ahw->switch_mode = nic_info.switch_mode;
- adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
- adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
- adapter->ahw->capabilities = nic_info.capabilities;
- adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
- adapter->ahw->max_mtu = nic_info.max_mtu;
+ ahw->physical_port = (u8) nic_info.phys_port;
+ ahw->switch_mode = nic_info.switch_mode;
+ ahw->max_tx_ques = nic_info.max_tx_ques;
+ ahw->max_rx_ques = nic_info.max_rx_ques;
+ ahw->capabilities = nic_info.capabilities;
+ ahw->max_mac_filters = nic_info.max_mac_filters;
+ ahw->max_mtu = nic_info.max_mtu;
+
+ /* Disable NPAR for 83XX */
+ if (QLCNIC_IS_83XX(adapter))
+ return err;
- if (adapter->ahw->capabilities & BIT_6)
+ if (ahw->capabilities & BIT_6)
adapter->flags |= QLCNIC_ESWITCH_ENABLED;
else
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
@@ -701,24 +916,6 @@ qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
adapter->pvid = 0;
}
-static int
-qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- set_bit(vid, adapter->vlans);
- return 0;
-}
-
-static int
-qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
-
- qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
- clear_bit(vid, adapter->vlans);
- return 0;
-}
-
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
@@ -758,14 +955,17 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
struct net_device *netdev = adapter->netdev;
- netdev_features_t features, vlan_features;
+ unsigned long features, vlan_features;
- features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ if (QLCNIC_IS_83XX(adapter))
+ return;
+
+ features = (NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_GRO);
vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);
+ NETIF_F_IPV6_CSUM);
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+ if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
features |= (NETIF_F_TSO | NETIF_F_TSO6);
vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
}
@@ -775,18 +975,20 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
if (esw_cfg->offload_flags & BIT_0) {
netdev->features |= features;
+ adapter->rx_csum = 1;
if (!(esw_cfg->offload_flags & BIT_1))
netdev->features &= ~NETIF_F_TSO;
if (!(esw_cfg->offload_flags & BIT_2))
netdev->features &= ~NETIF_F_TSO6;
} else {
netdev->features &= ~features;
+ adapter->rx_csum = 0;
}
netdev->vlan_features = (features & vlan_features);
}
-static int
+int
qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
{
void __iomem *priv_op;
@@ -802,7 +1004,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
return 0;
priv_op = ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
- op_mode = readl(priv_op);
+ op_mode = QLCRD(adapter, QLCNIC_DRV_OP_MODE);
priv_level = QLC_DEV_GET_DRV(op_mode, ahw->pci_func);
if (op_mode == QLC_DEV_DRV_DEFAULT)
@@ -834,7 +1036,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
return err;
}
-static int
+int
qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
{
struct qlcnic_esw_func_cfg esw_cfg;
@@ -844,16 +1046,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
return 0;
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
- esw_cfg.pci_func = i;
- esw_cfg.offload_flags = BIT_0;
+ esw_cfg.pci_func = adapter->npars[i].pci_func;
esw_cfg.mac_override = BIT_0;
esw_cfg.promisc_mode = BIT_0;
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
- esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+ if (QLCNIC_IS_82XX(adapter)) {
+ esw_cfg.offload_flags = BIT_0;
+ if (QLCNIC_IS_TSO_CAPABLE(adapter))
+ esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+ }
if (qlcnic_config_switch_port(adapter, &esw_cfg))
return -EIO;
npar = &adapter->npars[i];
@@ -868,6 +1070,7 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
return 0;
}
+
static int
qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
struct qlcnic_npar_info *npar, int pci_func)
@@ -891,37 +1094,39 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
return 0;
}
-static int
+int
qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
{
int i, err;
struct qlcnic_npar_info *npar;
struct qlcnic_info nic_info;
+ u8 pci_func;
- if (!adapter->need_fw_reset)
- return 0;
+ if (QLCNIC_IS_82XX(adapter))
+ if (!adapter->need_fw_reset)
+ return 0;
/* Set the NPAR config data after FW reset */
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
npar = &adapter->npars[i];
- if (npar->type != QLCNIC_TYPE_NIC)
- continue;
- err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ pci_func = npar->pci_func;
+ err = adapter->ahw->hw_ops->get_nic_info(adapter,
+ &nic_info, pci_func);
if (err)
return err;
nic_info.min_tx_bw = npar->min_bw;
nic_info.max_tx_bw = npar->max_bw;
- err = qlcnic_set_nic_info(adapter, &nic_info);
+ err = adapter->ahw->hw_ops->set_nic_info(adapter, &nic_info);
if (err)
return err;
if (npar->enable_pm) {
err = qlcnic_config_port_mirroring(adapter,
- npar->dest_npar, 1, i);
+ npar->dest_npar, 1, pci_func);
if (err)
return err;
}
- err = qlcnic_reset_eswitch_config(adapter, npar, i);
+ err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
if (err)
return err;
}
@@ -936,10 +1141,10 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
return 0;
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ npar_state = QLCRD(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
msleep(1000);
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ npar_state = QLCRD(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
}
if (!npar_opt_timeo) {
dev_err(&adapter->pdev->dev,
@@ -949,7 +1154,7 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
return 0;
}
-static int
+int
qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
{
int err;
@@ -1012,9 +1217,8 @@ check_fw_status:
if (err)
goto err_out;
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
qlcnic_idc_debug_info(adapter, 1);
-
err = qlcnic_check_eswitch_mode(adapter);
if (err) {
dev_err(&adapter->pdev->dev,
@@ -1032,7 +1236,7 @@ check_fw_status:
return 0;
err_out:
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
dev_err(&adapter->pdev->dev, "Device state set to failed\n");
qlcnic_release_firmware(adapter);
@@ -1044,6 +1248,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
{
irq_handler_t handler;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
int err, ring;
unsigned long flags = 0;
@@ -1051,7 +1256,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
- handler = qlcnic_tmp_intr;
+ if (QLCNIC_IS_82XX(adapter))
+ handler = qlcnic_tmp_intr;
if (!QLCNIC_IS_MSI_FAMILY(adapter))
flags |= IRQF_SHARED;
@@ -1067,15 +1273,32 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
}
adapter->irq = netdev->irq;
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
- err = request_irq(sds_ring->irq, handler,
- flags, sds_ring->name, sds_ring);
- if (err)
- return err;
- }
+ if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ sprintf(sds_ring->name, "%s[%d]",
+ netdev->name, ring);
+ err = request_irq(sds_ring->irq, handler, flags,
+ sds_ring->name, sds_ring);
+ if (err)
+ return err;
+ }
+ if (QLCNIC_IS_83XX(adapter) &&
+ adapter->flags & QLCNIC_MSIX_ENABLED) {
+ handler = qlcnic_msix_tx_intr;
+ for (ring = 0; ring < adapter->max_drv_tx_rings;
+ ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ sprintf(tx_ring->name, "%s[%d]", netdev->name,
+ adapter->max_sds_rings + ring);
+ err = request_irq(tx_ring->irq, handler, flags,
+ tx_ring->name, tx_ring);
+ if (err)
+ return err;
+ }
+ }
+ }
return 0;
}
@@ -1084,70 +1307,75 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
{
int ring;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- free_irq(sds_ring->irq, sds_ring);
+ if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ free_irq(sds_ring->irq, sds_ring);
+ }
+ if (QLCNIC_IS_83XX(adapter)) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings;
+ ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ if (tx_ring->irq)
+ free_irq(tx_ring->irq, tx_ring);
+ }
+ }
}
}
static int
__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
- int ring;
- u32 capab2;
-
+ u8 ring;
struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
return -EIO;
if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
return 0;
+
if (qlcnic_set_eswitch_port_config(adapter))
return -EIO;
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
- capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
- if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
- adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
- }
-
if (qlcnic_fw_create_ctx(adapter))
return -EIO;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx->rds_rings[ring];
- qlcnic_post_rx_buffers(adapter, rds_ring);
+ qlcnic_post_rx_buffers(adapter, rds_ring, ring);
}
qlcnic_set_multi(netdev);
qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);
- adapter->ahw->linkup = 0;
+ ahw->linkup = 0;
if (adapter->max_sds_rings > 1)
- qlcnic_config_rss(adapter, 1);
+ ahw->hw_ops->config_rss(adapter, 1);
- qlcnic_config_intr_coalesce(adapter);
+ ahw->hw_ops->config_intr_coal(adapter);
if (netdev->features & NETIF_F_LRO)
- qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
+ ahw->hw_ops->config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
- qlcnic_napi_enable(adapter);
+ ahw->hw_ops->napi_enable(adapter);
- qlcnic_linkevent_request(adapter, 1);
-
- adapter->ahw->reset_context = 0;
+ ahw->reset_context = 0;
set_bit(__QLCNIC_DEV_UP, &adapter->state);
+
+ ahw->hw_ops->setup_link_event(adapter, 1);
return 0;
}
/* Usage: During resume and firmware recovery module.*/
-static int
+int
qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
int err = 0;
@@ -1179,12 +1407,12 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (adapter->fhash.fnum)
qlcnic_delete_lb_filters(adapter);
- qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
+ adapter->ahw->hw_ops->config_promisc_mode(adapter,
+ QLCNIC_NIU_NON_PROMISC_MODE);
- qlcnic_napi_disable(adapter);
+ adapter->ahw->hw_ops->napi_disable(adapter);
qlcnic_fw_destroy_ctx(adapter);
- adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP;
qlcnic_reset_rx_buffers_list(adapter);
qlcnic_release_tx_buffers(adapter);
@@ -1193,27 +1421,26 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
/* Usage: During suspend and firmware recovery module */
-static void
+void
qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
rtnl_lock();
if (netif_running(netdev))
__qlcnic_down(adapter, netdev);
rtnl_unlock();
-
}
-static int
+int
qlcnic_attach(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- int err;
+ int err = -1;
if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
return 0;
- err = qlcnic_napi_add(adapter, netdev);
+ err = adapter->nic_ops->napi_add(adapter, netdev);
if (err)
return err;
@@ -1249,7 +1476,7 @@ err_out_napi_del:
return err;
}
-static void
+void
qlcnic_detach(struct qlcnic_adapter *adapter)
{
if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
@@ -1276,7 +1503,10 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
- QLCNIC_DISABLE_INTR(sds_ring->crb_intr_mask);
+ if (QLCNIC_IS_83XX(adapter))
+ writel(1, sds_ring->crb_intr_mask);
+ else
+ QLCNIC_DISABLE_INTR(sds_ring->crb_intr_mask);
}
}
@@ -1326,6 +1556,8 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
vfree(adapter->ahw->fw_dump.tmpl_hdr);
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
+
+ adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
@@ -1333,7 +1565,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_rds_ring *rds_ring;
- int ring;
+ u8 ring;
int ret;
netif_device_detach(netdev);
@@ -1361,19 +1593,22 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx->rds_rings[ring];
- qlcnic_post_rx_buffers(adapter, rds_ring);
+ qlcnic_post_rx_buffers(adapter, rds_ring, ring);
}
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx->sds_rings[ring];
- QLCNIC_ENABLE_INTR(adapter, sds_ring->crb_intr_mask);
+ if (QLCNIC_IS_82XX(adapter)) {
+ QLCNIC_ENABLE_INTR(adapter,
+ sds_ring->crb_intr_mask);
+ }
}
}
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
adapter->ahw->loopback_state = 0;
- qlcnic_linkevent_request(adapter, 1);
+ adapter->ahw->hw_ops->setup_link_event(adapter, 1);
}
set_bit(__QLCNIC_DEV_UP, &adapter->state);
@@ -1399,6 +1634,7 @@ qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
netif_device_attach(netdev);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ dev_err(&adapter->pdev->dev, "%s:\n", __func__);
return 0;
}
@@ -1442,33 +1678,37 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
int err;
struct pci_dev *pdev = adapter->pdev;
+ adapter->rx_csum = 1;
adapter->ahw->mc_enabled = 0;
adapter->ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
netdev->netdev_ops = &qlcnic_netdev_ops;
- netdev->watchdog_timeo = QLCNIC_WATCHDOG_TIMEOUTVALUE*HZ;
+ netdev->watchdog_timeo = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ;
qlcnic_change_mtu(netdev, netdev->mtu);
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
- netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
+ netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX);
+ netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM);
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
- netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
- if (pci_using_dac)
- netdev->hw_features |= NETIF_F_HIGHDMA;
+ if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
+ netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
+ netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
+ }
- netdev->vlan_features = netdev->hw_features;
+ if (pci_using_dac) {
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
- netdev->hw_features |= NETIF_F_HW_VLAN_TX;
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
- netdev->hw_features |= NETIF_F_LRO;
+ if (QLCNIC_IS_VLAN_TX_CAPABLE(adapter))
+ netdev->features |= (NETIF_F_HW_VLAN_TX);
- netdev->features |= netdev->hw_features |
- NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ netdev->features |= NETIF_F_LRO;
netdev->irq = adapter->msix_entries[0].vector;
@@ -1497,6 +1737,17 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
return 0;
}
+int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
+{
+ int i;
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+ if (adapter->npars[i].pci_func == pci_func)
+ return i;
+ }
+
+ return -1;
+}
+
static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1531,10 +1782,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!ahw)
goto err_out_free_res;
- if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X)
- ahw->hw_ops = &qlcnic_82xx_ops;
- else
- goto err_out_free_hw_res;
+ if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) {
+ ahw->hw_ops = &qlcnic_hw_ops;
+ ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
+ }
err = qlcnic_setup_pci_map(pdev, ahw);
if (err)
@@ -1559,6 +1810,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->dev_rst_time = jiffies;
adapter->ahw->revision_id = pdev->revision;
adapter->mac_learn = qlcnic_mac_learn;
+ adapter->max_drv_tx_rings = 1;
rwlock_init(&adapter->ahw->crb_lock);
mutex_init(&adapter->ahw->mem_lock);
@@ -1566,28 +1818,21 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list);
- qlcnic_check_vf(adapter);
-
- /* This will be reset for mezz cards */
- adapter->portnum = adapter->ahw->pci_func;
-
- err = qlcnic_get_board_info(adapter);
- if (err) {
- dev_err(&pdev->dev, "Error getting board config info.\n");
- goto err_out_free_hw;
- }
-
- err = qlcnic_setup_idc_param(adapter);
- if (err)
- goto err_out_free_hw;
+ /* hilda workaorund */
+ if (QLCNIC_IS_82XX(adapter)) {
+ qlcnic_check_vf(adapter, ent);
+ adapter->portnum = adapter->ahw->pci_func;
+ err = adapter->nic_ops->start_firmware(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "FW load failed. Please Reboot\n");
+ goto err_out_free_hw;
+ }
- adapter->flags |= QLCNIC_NEED_FLR;
+ err = qlcnic_setup_idc_param(adapter);
+ if (err)
+ goto err_out_free_hw;
- err = adapter->nic_ops->start_firmware(adapter);
- if (err) {
- dev_err(&pdev->dev, "Loading fw failed. Please Reboot\n"
- "\t\tIf reboot doesn't help, try flashing the card\n");
- goto err_out_maintenance_mode;
+ adapter->flags |= QLCNIC_NEED_FLR;
}
if (qlcnic_read_mac_addr(adapter))
@@ -1600,18 +1845,21 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
module_name(THIS_MODULE),
brd_name, adapter->ahw->revision_id);
}
+ err = ahw->hw_ops->setup_intr(adapter, 0);
+ if (err)
+ goto err_out_disable_msi;
- err = ahw->hw_ops->setup_intr(adapter);
- if (err == -ENOMEM)
- goto err_out_decr_ref;
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
if (err)
- goto err_out_disable_msi;
+ goto err_out_disable_mbx_intr;
pci_set_drvdata(pdev, adapter);
- qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+ if (QLCNIC_IS_82XX(adapter)) {
+ qlcnic_schedule_work(adapter,
+ qlcnic_fw_poll_work, FW_POLL_DELAY);
+ }
switch (adapter->ahw->port_type) {
case QLCNIC_GBE:
@@ -1627,15 +1875,15 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (adapter->mac_learn)
qlcnic_alloc_lb_filters_mem(adapter);
- qlcnic_create_diag_entries(adapter);
+ adapter->ahw->hw_ops->add_sysfs(adapter);
return 0;
+err_out_disable_mbx_intr:
+
err_out_disable_msi:
qlcnic_teardown_intr(adapter);
- kfree(adapter->msix_entries);
-
-err_out_decr_ref:
+ adapter->nic_ops->cancel_idc_work(adapter);
qlcnic_clr_all_drv_state(adapter, 0);
err_out_free_hw:
@@ -1657,18 +1905,6 @@ err_out_disable_pdev:
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
-
-err_out_maintenance_mode:
- netdev->netdev_ops = &qlcnic_netdev_failed_ops;
- SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
- err = register_netdev(netdev);
- if (err) {
- dev_err(&pdev->dev, "failed to register net device\n");
- goto err_out_decr_ref;
- }
- pci_set_drvdata(pdev, adapter);
- qlcnic_create_diag_entries(adapter);
- return 0;
}
static void __devexit qlcnic_remove(struct pci_dev *pdev)
@@ -1683,28 +1919,27 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
netdev = adapter->netdev;
ahw = adapter->ahw;
-
- qlcnic_cancel_fw_work(adapter);
+ adapter->nic_ops->cancel_idc_work(adapter);
unregister_netdev(netdev);
- qlcnic_detach(adapter);
+ qlcnic_detach(adapter);
if (adapter->npars != NULL)
kfree(adapter->npars);
if (adapter->eswitch != NULL)
kfree(adapter->eswitch);
- qlcnic_clr_all_drv_state(adapter, 0);
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
qlcnic_free_lb_filters_mem(adapter);
qlcnic_teardown_intr(adapter);
- kfree(adapter->msix_entries);
- qlcnic_remove_diag_entries(adapter);
+ adapter->ahw->hw_ops->remove_sysfs(adapter);
qlcnic_cleanup_pci_map(ahw);
@@ -1726,13 +1961,13 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
int retval;
netif_device_detach(netdev);
-
- qlcnic_cancel_fw_work(adapter);
+ adapter->nic_ops->cancel_idc_work(adapter);
if (netif_running(netdev))
qlcnic_down(adapter, netdev);
- qlcnic_clr_all_drv_state(adapter, 0);
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1740,9 +1975,11 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
if (retval)
return retval;
- if (qlcnic_wol_supported(adapter)) {
- pci_enable_wake(pdev, PCI_D3cold, 1);
- pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (QLCNIC_IS_82XX(adapter)) {
+ if (qlcnic_wol_supported(adapter)) {
+ pci_enable_wake(pdev, PCI_D3cold, 1);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ }
}
return 0;
@@ -1808,16 +2045,9 @@ done:
static int qlcnic_open(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
int err;
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
- netdev_err(netdev, "Device in FAILED state\n");
- return -EIO;
- }
-
netif_carrier_off(netdev);
-
err = qlcnic_attach(adapter);
if (err)
return err;
@@ -1877,13 +2107,16 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
adapter->fhash.fmax = 0;
}
-static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
+int qlcnic_check_temp(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
u32 temp, temp_state, temp_val;
int rv = 0;
- temp = QLCRD32(adapter, CRB_TEMP_STATE);
+ temp = 0;
+
+ if (QLCNIC_IS_82XX(adapter))
+ temp = QLCRD(adapter, QLCNIC_ASIC_TEMP);
temp_state = qlcnic_get_temp_state(temp);
temp_val = qlcnic_get_temp_val(temp);
@@ -1977,7 +2210,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
goto done;
}
- if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+ if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
return IRQ_NONE;
done:
@@ -1991,7 +2224,7 @@ static irqreturn_t qlcnic_intr(int irq, void *data)
struct qlcnic_host_sds_ring *sds_ring = data;
struct qlcnic_adapter *adapter = sds_ring->adapter;
- if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+ if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
return IRQ_NONE;
napi_schedule(&sds_ring->napi);
@@ -2019,6 +2252,14 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data)
+{
+ struct qlcnic_host_tx_ring *tx_ring = data;
+
+ napi_schedule(&tx_ring->napi);
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev)
{
@@ -2045,7 +2286,7 @@ qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
val |= encoding << 7;
val |= (jiffies - adapter->dev_rst_time) << 8;
- QLCWR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_SCRATCH, val);
adapter->dev_rst_time = jiffies;
}
@@ -2057,19 +2298,19 @@ qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state)
WARN_ON(state != QLCNIC_DEV_NEED_RESET &&
state != QLCNIC_DEV_NEED_QUISCENT);
- if (qlcnic_api_lock(adapter))
+ if (adapter->ahw->hw_ops->api_lock(adapter))
return -EIO;
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
if (state == QLCNIC_DEV_NEED_RESET)
QLC_DEV_SET_RST_RDY(val, adapter->portnum);
else if (state == QLCNIC_DEV_NEED_QUISCENT)
QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
- qlcnic_api_unlock(adapter);
+ adapter->ahw->hw_ops->api_unlock(adapter);
return 0;
}
@@ -2079,14 +2320,14 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
{
u32 val;
- if (qlcnic_api_lock(adapter))
+ if (adapter->ahw->hw_ops->api_lock(adapter))
return -EBUSY;
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
- qlcnic_api_unlock(adapter);
+ adapter->ahw->hw_ops->api_unlock(adapter);
return 0;
}
@@ -2096,25 +2337,25 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
{
u32 val;
- if (qlcnic_api_lock(adapter))
+ if (adapter->ahw->hw_ops->api_lock(adapter))
goto err;
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_ACTIVE);
QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
if (failed) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
dev_info(&adapter->pdev->dev,
"Device state set to Failed. Please Reboot\n");
} else if (!(val & 0x11111111))
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
- qlcnic_api_unlock(adapter);
+ adapter->ahw->hw_ops->api_unlock(adapter);
err:
adapter->fw_fail_cnt = 0;
adapter->flags &= ~QLCNIC_FW_HANG;
@@ -2129,8 +2370,8 @@ qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
int act, state, active_mask;
struct qlcnic_hardware_context *ahw = adapter->ahw;
- state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
- act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ state = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
+ act = QLCRD(adapter, QLCNIC_CRB_DRV_ACTIVE);
if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
active_mask = (~(1 << (ahw->pci_func * 4)));
@@ -2146,7 +2387,7 @@ qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter)
{
- u32 val = QLCRD32(adapter, QLCNIC_CRB_DRV_IDC_VER);
+ u32 val = QLCRD(adapter, QLCNIC_CRB_DRV_IDC_VER);
if (val != QLCNIC_DRV_IDC_VER) {
dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's"
@@ -2163,50 +2404,51 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
u8 dev_init_timeo = adapter->dev_init_timeo;
u8 portnum = adapter->portnum;
u8 ret;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
return 1;
- if (qlcnic_api_lock(adapter))
+ if (ahw->hw_ops->api_lock(adapter))
return -1;
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_ACTIVE);
if (!(val & (1 << (portnum * 4)))) {
QLC_DEV_SET_REF_CNT(val, portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
}
- prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ prev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
QLCDB(adapter, HW, "Device state = %u\n", prev_state);
switch (prev_state) {
case QLCNIC_DEV_COLD:
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
- QLCWR32(adapter, QLCNIC_CRB_DRV_IDC_VER, QLCNIC_DRV_IDC_VER);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
+ QLCWR(adapter, QLCNIC_CRB_DRV_IDC_VER, QLCNIC_DRV_IDC_VER);
qlcnic_idc_debug_info(adapter, 0);
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
return 1;
case QLCNIC_DEV_READY:
ret = qlcnic_check_idc_ver(adapter);
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
return ret;
case QLCNIC_DEV_NEED_RESET:
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_SET_RST_RDY(val, portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
break;
case QLCNIC_DEV_NEED_QUISCENT:
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_SET_QSCNT_RDY(val, portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
break;
case QLCNIC_DEV_FAILED:
dev_err(&adapter->pdev->dev, "Device in failed state.\n");
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
return -1;
case QLCNIC_DEV_INITIALIZING:
@@ -2214,11 +2456,11 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
break;
}
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
do {
msleep(1000);
- prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ prev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
if (prev_state == QLCNIC_DEV_QUISCENT)
continue;
@@ -2230,15 +2472,15 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
return -1;
}
- if (qlcnic_api_lock(adapter))
+ if (ahw->hw_ops->api_lock(adapter))
return -1;
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_CLR_RST_QSCNT(val, portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
ret = qlcnic_check_idc_ver(adapter);
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
return ret;
}
@@ -2252,20 +2494,20 @@ qlcnic_fwinit_work(struct work_struct *work)
u32 val;
struct qlcnic_hardware_context *ahw = adapter->ahw;
- if (qlcnic_api_lock(adapter))
+ if (ahw->hw_ops->api_lock(adapter))
goto err_ret;
- dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ dev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
if (dev_state == QLCNIC_DEV_QUISCENT ||
dev_state == QLCNIC_DEV_NEED_QUISCENT) {
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
FW_POLL_DELAY * 2);
return;
}
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
goto wait_npar;
}
@@ -2284,28 +2526,21 @@ qlcnic_fwinit_work(struct work_struct *work)
if (!qlcnic_check_drv_state(adapter)) {
skip_ack_check:
- dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ dev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
if (dev_state == QLCNIC_DEV_NEED_RESET) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE,
QLCNIC_DEV_INITIALIZING);
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCDB(adapter, DRV, "Restarting fw\n");
qlcnic_idc_debug_info(adapter, 0);
- val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+ val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_SET_RST_RDY(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+ QLCWR(adapter, QLCNIC_CRB_DRV_STATE, val);
}
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
- rtnl_lock();
- if (ahw->fw_dump.enable &&
- (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
- QLCDB(adapter, DRV, "Take FW dump\n");
- adapter->flags |= QLCNIC_FW_HANG;
- }
- rtnl_unlock();
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
if (!adapter->nic_ops->start_firmware(adapter)) {
@@ -2316,10 +2551,10 @@ skip_ack_check:
goto err_ret;
}
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
wait_npar:
- dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ dev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
switch (dev_state) {
@@ -2361,7 +2596,7 @@ qlcnic_detach_work(struct work_struct *work)
} else
qlcnic_down(adapter, netdev);
- status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
+ status = QLCRD(adapter, QLCNIC_PEG_HALT_STATUS1);
if (status & QLCNIC_RCODE_FATAL_ERROR) {
dev_err(&adapter->pdev->dev,
@@ -2412,19 +2647,19 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
{
u32 state;
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ state = QLCRD(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
if (state == QLCNIC_DEV_NPAR_NON_OPER)
return;
- if (qlcnic_api_lock(adapter))
+ if (adapter->ahw->hw_ops->api_lock(adapter))
return;
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
- qlcnic_api_unlock(adapter);
+ QLCWR(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ adapter->ahw->hw_ops->api_unlock(adapter);
}
/*Transit to RESET state from READY state only */
void
-qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
+qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
{
u32 state, xg_val = 0, gb_val = 0;
@@ -2436,46 +2671,41 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
qlcnic_gb_set_gb2_mask(gb_val);
qlcnic_gb_set_gb3_mask(gb_val);
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val);
- dev_info(&adapter->pdev->dev, "Pause control frames disabled"
- " on all ports\n");
+ dev_info(&adapter->pdev->dev,
+ "Pause control frames disabled on all ports\n");
adapter->need_fw_reset = 1;
- if (qlcnic_api_lock(adapter))
- return;
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
- netdev_err(adapter->netdev,
- "Device is in FAILED state, Please Reboot\n");
- qlcnic_api_unlock(adapter);
+ if (adapter->ahw->hw_ops->api_lock(adapter))
return;
- }
+
+ state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
if (state == QLCNIC_DEV_READY) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
adapter->flags |= QLCNIC_FW_RESET_OWNER;
QLCDB(adapter, DRV, "NEED_RESET state set\n");
qlcnic_idc_debug_info(adapter, 0);
}
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
+ QLCWR(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
QLCNIC_DEV_NPAR_NON_OPER);
- qlcnic_api_unlock(adapter);
+ adapter->ahw->hw_ops->api_unlock(adapter);
}
/* Transit to NPAR READY state from NPAR NOT READY state */
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
- if (qlcnic_api_lock(adapter))
+ if (adapter->ahw->hw_ops->api_lock(adapter))
return;
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+ QLCWR(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
QLCDB(adapter, DRV, "NPAR operational state set\n");
- qlcnic_api_unlock(adapter);
+ adapter->ahw->hw_ops->api_unlock(adapter);
}
-static void
+void
qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay)
{
@@ -2484,19 +2714,7 @@ qlcnic_schedule_work(struct qlcnic_adapter *adapter,
INIT_DELAYED_WORK(&adapter->fw_work, func);
queue_delayed_work(qlcnic_wq, &adapter->fw_work,
- round_jiffies_relative(delay));
-}
-
-static void
-qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter)
-{
- while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
- msleep(10);
-
- if (!adapter->fw_work.work.func)
- return;
-
- cancel_delayed_work_sync(&adapter->fw_work);
+ round_jiffies_relative(delay));
}
static void
@@ -2508,7 +2726,7 @@ qlcnic_attach_work(struct work_struct *work)
u32 npar_state;
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ npar_state = QLCRD(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
qlcnic_clr_all_drv_state(adapter, 0);
else if (npar_state != QLCNIC_DEV_NPAR_OPER)
@@ -2541,6 +2759,7 @@ done:
static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
+ int err;
u32 state = 0, heartbeat;
u32 peg_status;
@@ -2548,16 +2767,16 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
goto detach;
if (adapter->need_fw_reset)
- qlcnic_dev_request_reset(adapter);
+ adapter->nic_ops->request_reset(adapter, 0);
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
if (state == QLCNIC_DEV_NEED_RESET) {
qlcnic_set_npar_non_operational(adapter);
adapter->need_fw_reset = 1;
} else if (state == QLCNIC_DEV_NEED_QUISCENT)
goto detach;
- heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
if (heartbeat != adapter->heartbeat) {
adapter->heartbeat = heartbeat;
adapter->fw_fail_cnt = 0;
@@ -2577,25 +2796,25 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
adapter->flags |= QLCNIC_FW_HANG;
- qlcnic_dev_request_reset(adapter);
+ adapter->nic_ops->request_reset(adapter, 0);
if (auto_fw_reset)
clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
dev_err(&adapter->pdev->dev, "firmware hang detected\n");
+ peg_status = QLCRD(adapter, QLCNIC_PEG_HALT_STATUS1);
dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
"PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
"PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
"PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
"PEG_NET_4_PC: 0x%x\n",
- QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1),
- QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS2),
- QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c),
- QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c),
- QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c),
- QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
- QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
- peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
+ peg_status,
+ QLCRD(adapter, QLCNIC_PEG_HALT_STATUS2),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, &err),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, &err),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, &err),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, &err),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, &err));
if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
dev_err(&adapter->pdev->dev,
"Firmware aborted with error code 0x00006700. "
@@ -2634,6 +2853,19 @@ reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
+struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
+ unsigned int devfn)
+{
+ struct pci_dev *dev = NULL;
+
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ if (pci_domain_nr(dev->bus) == domain &&
+ (dev->bus->number == bus && dev->devfn == devfn))
+ return dev;
+ }
+ return NULL;
+}
+
static int qlcnic_is_first_func(struct pci_dev *pdev)
{
struct pci_dev *oth_pdev;
@@ -2674,16 +2906,16 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
first_func = qlcnic_is_first_func(pdev);
- if (qlcnic_api_lock(adapter))
+ if (ahw->hw_ops->api_lock(adapter))
return -EINVAL;
if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
+ QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
QLCDB(adapter, DRV, "Restarting fw\n");
}
- qlcnic_api_unlock(adapter);
+ ahw->hw_ops->api_unlock(adapter);
err = adapter->nic_ops->start_firmware(adapter);
if (err)
@@ -2692,7 +2924,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
qlcnic_clr_drv_state(adapter);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
- err = ahw->hw_ops->setup_intr(adapter);
+ err = ahw->hw_ops->setup_intr(adapter, 0);
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
@@ -2757,7 +2989,7 @@ static void qlcnic_io_resume(struct pci_dev *pdev)
pci_cleanup_aer_uncorrect_error_status(pdev);
- if (QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY &&
+ if (QLCRD(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY &&
test_and_clear_bit(__QLCNIC_AER, &adapter->state))
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
FW_POLL_DELAY);
@@ -2803,20 +3035,17 @@ qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return -EOPNOTSUPP;
}
-int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
+int qlcnic_validate_max_rss(u8 max_hw, u8 val)
{
- if (!use_msi_x && !use_msi) {
- netdev_info(netdev, "no msix or msi support, hence no rss\n");
- return -EINVAL;
- }
+ u32 max_allowed = rounddown_pow_of_two(
+ min_t(int, max_hw, num_online_cpus()));
- if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) {
- netdev_info(netdev, "rss_ring valid range [2 - %x] in "
- " powers of 2\n", max_hw);
+ if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) {
+ pr_info("rss_ring valid range [2 - %x] in powers of 2\n",
+ max_allowed);
return -EINVAL;
}
return 0;
-
}
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
@@ -2832,13 +3061,10 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
__qlcnic_down(adapter, netdev);
qlcnic_detach(adapter);
qlcnic_teardown_intr(adapter);
- kfree(adapter->msix_entries);
- adapter->msix_entries = NULL;
- if (qlcnic_enable_msix(adapter, data)) {
+ err = adapter->ahw->hw_ops->setup_intr(adapter, data);
+ if (err)
netdev_info(netdev, "failed setting max_rss; rss disabled\n");
- qlcnic_enable_msi_legacy(adapter);
- }
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
@@ -2872,12 +3098,12 @@ qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
for_ifa(indev) {
switch (event) {
case NETDEV_UP:
- qlcnic_config_ipaddr(adapter,
- ifa->ifa_address, QLCNIC_IP_UP);
+ adapter->nic_ops->config_ipaddr(adapter,
+ ifa->ifa_address, QLCNIC_IP_UP);
break;
case NETDEV_DOWN:
- qlcnic_config_ipaddr(adapter,
- ifa->ifa_address, QLCNIC_IP_DOWN);
+ adapter->nic_ops->config_ipaddr(adapter,
+ ifa->ifa_address, QLCNIC_IP_DOWN);
break;
default:
break;
@@ -2887,7 +3113,7 @@ qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
in_dev_put(indev);
}
-static void
+void
qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -2968,10 +3194,12 @@ recheck:
switch (event) {
case NETDEV_UP:
- qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP);
+ adapter->nic_ops->config_ipaddr(adapter, ifa->ifa_address,
+ QLCNIC_IP_UP);
break;
case NETDEV_DOWN:
- qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN);
+ adapter->nic_ops->config_ipaddr(adapter, ifa->ifa_address,
+ QLCNIC_IP_DOWN);
break;
default:
break;
@@ -2989,7 +3217,7 @@ static struct notifier_block qlcnic_inetaddr_cb = {
.notifier_call = qlcnic_inetaddr_event,
};
#else
-static void
+void
qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index a9f8836..c77a016 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -1,5 +1,5 @@
-#include <linux/sysfs.h>
#include "qlcnic.h"
+#include <linux/sysfs.h>
static ssize_t
qlcnic_store_bridged_mode(struct device *dev,
@@ -308,14 +308,11 @@ validate_pm_config(struct qlcnic_adapter *adapter,
for (i = 0; i < count; i++) {
src_pci_func = pm_cfg[i].pci_func;
dest_pci_func = pm_cfg[i].dest_npar;
- if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
- || dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
- if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
+ if (qlcnic_is_valid_nic_func(adapter, src_pci_func) < 0)
return QL_STATUS_INVALID_PARAM;
- if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
+ if (qlcnic_is_valid_nic_func(adapter, dest_pci_func) < 0)
return QL_STATUS_INVALID_PARAM;
s_esw_id = adapter->npars[src_pci_func].phy_port;
@@ -337,7 +334,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_pm_func_cfg *pm_cfg;
u32 id, action, pci_func;
- int count, rem, i, ret;
+ int count, rem, i, ret, index;
count = size / sizeof(struct qlcnic_pm_func_cfg);
rem = size % sizeof(struct qlcnic_pm_func_cfg);
@@ -351,6 +348,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
return ret;
for (i = 0; i < count; i++) {
pci_func = pm_cfg[i].pci_func;
+
action = !!pm_cfg[i].action;
id = adapter->npars[pci_func].phy_port;
ret = qlcnic_config_port_mirroring(adapter, id,
@@ -361,9 +359,10 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = pm_cfg[i].pci_func;
+ index = qlcnic_is_valid_nic_func(adapter, pci_func);
id = adapter->npars[pci_func].phy_port;
- adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
- adapter->npars[pci_func].dest_npar = id;
+ adapter->npars[index].enable_pm = !!pm_cfg[i].action;
+ adapter->npars[index].dest_npar = id;
}
return size;
}
@@ -376,16 +375,16 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
int i;
+ u8 pci_func;
if (size != sizeof(pm_cfg))
return QL_STATUS_INVALID_PARAM;
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- pm_cfg[i].action = adapter->npars[i].enable_pm;
- pm_cfg[i].dest_npar = 0;
- pm_cfg[i].pci_func = i;
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+ pci_func = adapter->npars[i].pci_func;
+ pm_cfg[pci_func].action = adapter->npars[i].enable_pm;
+ pm_cfg[pci_func].dest_npar = 0;
+ pm_cfg[pci_func].pci_func = i;
}
memcpy(buf, &pm_cfg, size);
@@ -398,9 +397,10 @@ validate_esw_config(struct qlcnic_adapter *adapter,
{
u32 op_mode;
u8 pci_func;
- int i;
+ int i, ret;
- op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+ if (QLCNIC_IS_82XX(adapter))
+ op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
@@ -408,13 +408,16 @@ validate_esw_config(struct qlcnic_adapter *adapter,
return QL_STATUS_INVALID_PARAM;
if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
return QL_STATUS_INVALID_PARAM;
switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS:
- if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
- QLCNIC_NON_PRIV_FUNC) {
+ if (QLCNIC_IS_82XX(adapter)) {
+ ret = QLC_DEV_GET_DRV(op_mode, pci_func);
+ }
+
+ if (ret != QLCNIC_NON_PRIV_FUNC) {
if (esw_cfg[i].mac_anti_spoof != 0)
return QL_STATUS_INVALID_PARAM;
if (esw_cfg[i].mac_override != 1)
@@ -449,7 +452,8 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
struct qlcnic_esw_func_cfg *esw_cfg;
struct qlcnic_npar_info *npar;
int count, rem, i, ret;
- u8 pci_func, op_mode = 0;
+ int index;
+ u8 op_mode = 0, pci_func;
count = size / sizeof(struct qlcnic_esw_func_cfg);
rem = size % sizeof(struct qlcnic_esw_func_cfg);
@@ -493,7 +497,8 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
- npar = &adapter->npars[pci_func];
+ index = qlcnic_is_valid_nic_func(adapter, pci_func);
+ npar = &adapter->npars[index];
switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS:
npar->promisc_mode = esw_cfg[i].promisc_mode;
@@ -521,16 +526,15 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
- u8 i;
+ u8 i, pci_func;
if (size != sizeof(esw_cfg))
return QL_STATUS_INVALID_PARAM;
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- continue;
- esw_cfg[i].pci_func = i;
- if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+ for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+ pci_func = adapter->npars[i].pci_func;
+ esw_cfg[pci_func].pci_func = pci_func;
+ if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
return QL_STATUS_INVALID_PARAM;
}
memcpy(buf, &esw_cfg, size);
@@ -546,11 +550,8 @@ validate_npar_config(struct qlcnic_adapter *adapter,
for (i = 0; i < count; i++) {
pci_func = np_cfg[i].pci_func;
- if (pci_func >= QLCNIC_MAX_PCI_FUNC)
- return QL_STATUS_INVALID_PARAM;
-
- if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
+ if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
+ return QL_STATUS_INVALID_PARAM;
if (!IS_VALID_BW(np_cfg[i].min_bw) ||
!IS_VALID_BW(np_cfg[i].max_bw))
@@ -567,7 +568,7 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_info nic_info;
struct qlcnic_npar_func_cfg *np_cfg;
- int i, count, rem, ret;
+ int i, count, rem, ret, index;
u8 pci_func;
count = size / sizeof(struct qlcnic_npar_func_cfg);
@@ -582,22 +583,25 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count ; i++) {
pci_func = np_cfg[i].pci_func;
- ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+ ret = adapter->ahw->hw_ops->get_nic_info(adapter,
+ &nic_info, pci_func);
if (ret)
return ret;
nic_info.pci_func = pci_func;
nic_info.min_tx_bw = np_cfg[i].min_bw;
nic_info.max_tx_bw = np_cfg[i].max_bw;
- ret = qlcnic_set_nic_info(adapter, &nic_info);
+ ret = adapter->ahw->hw_ops->set_nic_info(adapter, &nic_info);
if (ret)
return ret;
- adapter->npars[i].min_bw = nic_info.min_tx_bw;
- adapter->npars[i].max_bw = nic_info.max_tx_bw;
+ index = qlcnic_is_valid_nic_func(adapter, pci_func);
+ adapter->npars[index].min_bw = nic_info.min_tx_bw;
+ adapter->npars[index].max_bw = nic_info.max_tx_bw;
}
return size;
}
+
static ssize_t
qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
@@ -612,9 +616,10 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
return QL_STATUS_INVALID_PARAM;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ if (qlcnic_is_valid_nic_func(adapter, i) < 0)
continue;
- ret = qlcnic_get_nic_info(adapter, &nic_info, i);
+ ret = adapter->ahw->hw_ops->get_nic_info(adapter,
+ &nic_info, i);
if (ret)
return ret;
@@ -748,6 +753,7 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
struct qlcnic_pci_info *pci_info;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
int i, ret;
if (size != sizeof(pci_cfg))
@@ -757,7 +763,7 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
if (!pci_info)
return -ENOMEM;
- ret = qlcnic_get_pci_info(adapter, pci_info);
+ ret = ahw->hw_ops->get_pci_info(adapter, pci_info);
if (ret) {
kfree(pci_info);
return ret;
@@ -775,6 +781,7 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
kfree(pci_info);
return size;
}
+
static struct bin_attribute bin_attr_npar_config = {
.attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
.size = 0,
@@ -894,3 +901,84 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
device_remove_bin_file(dev, &bin_attr_pm_config);
device_remove_bin_file(dev, &bin_attr_esw_stats);
}
+
+static int
+qlcnic_sysfs_validate_bar(struct qlcnic_adapter *adapter, loff_t offset,
+ size_t size)
+{
+ size_t bar = 4;
+
+ if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+ return -EIO;
+
+ if (offset >= QLCNIC_83XX_BAR0_LENGTH || (offset & (bar - 1)) ||
+ (size != bar))
+ return -EINVAL;
+ return 0;
+}
+
+static ssize_t
+qlcnic_sysfs_read_bar(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ u32 data;
+ int ret;
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ ret = qlcnic_sysfs_validate_bar(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ mutex_lock(&adapter->ahw->mem_lock);
+ data = readl(adapter->ahw->pci_base0 + offset);
+ mutex_unlock(&adapter->ahw->mem_lock);
+
+ memcpy(buf, &data, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_write_bar(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ u32 data;
+ int ret;
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+ ret = qlcnic_sysfs_validate_bar(adapter, offset, size);
+ if (ret != 0)
+ return ret;
+
+ memcpy(&data, buf, size);
+ mutex_lock(&adapter->ahw->mem_lock);
+ writel(data, adapter->ahw->pci_base0 + offset);
+ mutex_unlock(&adapter->ahw->mem_lock);
+
+ return size;
+}
+
+static struct bin_attribute bin_attr_bar = {
+ .attr = {.name = "membar", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_read_bar,
+ .write = qlcnic_sysfs_write_bar,
+};
+
+void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ qlcnic_create_diag_entries(adapter);
+ if (sysfs_create_bin_file(&dev->kobj, &bin_attr_bar))
+ dev_info(dev, "failed to create mem bar sysfs entry\n");
+}
+
+void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ qlcnic_remove_diag_entries(adapter);
+ sysfs_remove_bin_file(&dev->kobj, &bin_attr_bar);
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 08/15] qlcnic: register dump utility
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Common register dump utility for 82xx and 83xx adapters
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Manish chopra <manish.chopra@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 2 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 9 +
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 860 ++++++++++++++++++++
4 files changed, 872 insertions(+), 1 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index 2968c57..f87d98f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
- qlcnic_sysfs.o qlcnic_83xx_hw.o
+ qlcnic_sysfs.o qlcnic_83xx_hw.o qlcnic_minidump.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 3886e17..9e46670 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1465,6 +1465,7 @@ struct qlcnic_cmd_args {
struct _cdrp_cmd rsp;
};
+int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *);
@@ -1518,6 +1519,7 @@ int qlcnic_wol_supported(struct qlcnic_adapter *);
int qlcnic_config_led(struct qlcnic_adapter *, u32, u32);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *);
+int qlcnic_dump_fw(struct qlcnic_adapter *);
void qlcnic_get_ocm_win(struct qlcnic_hardware_context *);
void qlcnic_get_func_no(struct qlcnic_adapter *);
int qlcnic_api_lock(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index fa7f3e5..9304e71 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -839,6 +839,9 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->fw_version > prev_fw_version) {
if (fw_dump->tmpl_hdr)
vfree(fw_dump->tmpl_hdr);
+ if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+ dev_info(&pdev->dev,
+ "Supports FW dump capability\n");
}
}
@@ -2540,6 +2543,12 @@ skip_ack_check:
}
ahw->hw_ops->api_unlock(adapter);
+ rtnl_lock();
+ if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
+ qlcnic_dump_fw(adapter);
+ adapter->flags |= QLCNIC_FW_HANG;
+ }
+ rtnl_unlock();
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
if (!adapter->nic_ops->start_firmware(adapter)) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
new file mode 100644
index 0000000..c1d5a6a
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -0,0 +1,860 @@
+
+#include "qlcnic.h"
+#include "qlcnic_hdr.h"
+#include "qlcnic_83xx_hw.h"
+#include "qlcnic_hw.h"
+
+#include <net/ip.h>
+
+#define QLC_83XX_MINIDUMP_FLASH 0x520000
+#define QLC_83XX_OCM_INDEX 3
+#define QLC_83XX_PCI_INDEX 0
+
+static u32
+qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
+ u32 *buffer)
+{
+ int i;
+ u32 addr, data;
+ struct __crb *crb = &entry->region.crb;
+
+ addr = crb->addr;
+
+ for (i = 0; i < crb->no_ops; i++) {
+ data = qlcnic_ind_rd(adapter, addr);
+ *buffer++ = cpu_to_le32(addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += crb->stride;
+ }
+ return crb->no_ops * 2 * sizeof(u32);
+}
+
+static u32
+qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ int i, k, timeout = 0;
+ u32 addr, data;
+ u8 opcode, no_ops;
+ struct __ctrl *ctr = &entry->region.ctrl;
+ struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
+
+ addr = ctr->addr;
+ no_ops = ctr->no_ops;
+
+ for (i = 0; i < no_ops; i++) {
+ k = 0;
+ opcode = 0;
+ for (k = 0; k < 8; k++) {
+ if (!(ctr->opcode & (1 << k)))
+ continue;
+ switch (1 << k) {
+ case QLCNIC_DUMP_WCRB:
+ qlcnic_ind_wr(adapter, addr, ctr->val1);
+ break;
+ case QLCNIC_DUMP_RWCRB:
+ data = qlcnic_ind_rd(adapter, addr);
+ qlcnic_ind_wr(adapter, addr, data);
+ break;
+ case QLCNIC_DUMP_ANDCRB:
+ data = qlcnic_ind_rd(adapter, addr);
+ qlcnic_ind_wr(adapter, addr,
+ (data & ctr->val2));
+ break;
+ case QLCNIC_DUMP_ORCRB:
+ data = qlcnic_ind_rd(adapter, addr);
+ qlcnic_ind_wr(adapter, addr,
+ (data | ctr->val3));
+ break;
+ case QLCNIC_DUMP_POLLCRB:
+ while (timeout <= ctr->timeout) {
+ data = qlcnic_ind_rd(adapter, addr);
+ if ((data & ctr->val2) == ctr->val1)
+ break;
+ usleep_range(1000, 2000);
+ timeout++;
+ }
+ if (timeout > ctr->timeout) {
+ dev_info(&adapter->pdev->dev,
+ "Timed out, aborting poll CRB\n");
+ return 0;
+ }
+ break;
+ case QLCNIC_DUMP_RD_SAVE:
+ if (ctr->index_a)
+ addr = t_hdr->saved_state[ctr->index_a];
+ data = qlcnic_ind_rd(adapter, addr);
+ t_hdr->saved_state[ctr->index_v] = data;
+ break;
+ case QLCNIC_DUMP_WRT_SAVED:
+ if (ctr->index_v)
+ data = t_hdr->saved_state[ctr->index_v];
+ else
+ data = ctr->val1;
+ if (ctr->index_a)
+ addr = t_hdr->saved_state[ctr->index_a];
+ qlcnic_ind_wr(adapter, addr, data);
+ break;
+ case QLCNIC_DUMP_MOD_SAVE_ST:
+ data = t_hdr->saved_state[ctr->index_v];
+ data <<= ctr->shl_val;
+ data >>= ctr->shr_val;
+ if (ctr->val2)
+ data &= ctr->val2;
+ data |= ctr->val3;
+ data += ctr->val1;
+ t_hdr->saved_state[ctr->index_v] = data;
+ break;
+ default:
+ dev_info(&adapter->pdev->dev,
+ "Unknown opcode\n");
+ break;
+ }
+ }
+ addr += ctr->stride;
+ }
+ return 0;
+}
+
+static u32
+qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
+ u32 *buffer)
+{
+ int loop;
+ u32 val, data = 0;
+ struct __mux *mux = &entry->region.mux;
+
+ val = mux->val;
+ for (loop = 0; loop < mux->no_ops; loop++) {
+ qlcnic_ind_wr(adapter, mux->addr, val);
+ data = qlcnic_ind_rd(adapter, mux->read_addr);
+ *buffer++ = cpu_to_le32(val);
+ *buffer++ = cpu_to_le32(data);
+ val += mux->val_stride;
+ }
+ return 2 * mux->no_ops * sizeof(u32);
+}
+
+static u32
+qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
+ u32 *buffer)
+{
+ int i, loop;
+ u32 cnt, addr, data, que_id = 0;
+ struct __queue *que = &entry->region.que;
+
+ addr = que->read_addr;
+ cnt = que->read_addr_cnt;
+
+ for (loop = 0; loop < que->no_ops; loop++) {
+ qlcnic_ind_wr(adapter, que->sel_addr, que_id);
+ addr = que->read_addr;
+ for (i = 0; i < cnt; i++) {
+ data = qlcnic_ind_rd(adapter, addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += que->read_addr_stride;
+ }
+ que_id += que->stride;
+ }
+ return que->no_ops * cnt * sizeof(u32);
+}
+
+static u32
+qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
+ u32 *buffer)
+{
+ int i;
+ u32 data;
+ void __iomem *addr;
+ struct __ocm *ocm = &entry->region.ocm;
+
+ addr = adapter->ahw->pci_base0 + ocm->read_addr;
+ for (i = 0; i < ocm->no_ops; i++) {
+ data = readl(addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += ocm->read_addr_stride;
+ }
+ return ocm->no_ops * sizeof(u32);
+}
+
+static u32
+qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
+ u32 *buffer)
+{
+ int i, count = 0;
+ u32 fl_addr, size, val, lck_val, addr;
+ struct __mem *rom = &entry->region.mem;
+
+ fl_addr = rom->addr;
+ size = rom->size/4;
+lock_try:
+ lck_val = QLCRD(adapter, QLCNIC_FLASH_LOCK);
+ if (!lck_val && count < MAX_CTL_CHECK) {
+ usleep_range(10000, 11000);
+ count++;
+ goto lock_try;
+ }
+ QLCWR(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->ahw->pci_func);
+ for (i = 0; i < size; i++) {
+ addr = fl_addr & 0xFFFF0000;
+ qlcnic_ind_wr(adapter, FLASH_ROM_WINDOW, addr);
+ addr = LSW(fl_addr) + FLASH_ROM_DATA;
+ val = qlcnic_ind_rd(adapter, addr);
+ fl_addr += 4;
+ *buffer++ = cpu_to_le32(val);
+ }
+ QLCRD(adapter, QLCNIC_FLASH_UNLOCK);
+ return rom->size;
+}
+
+static u32
+qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ int i;
+ u32 cnt, val, data, addr;
+ struct __cache *l1 = &entry->region.cache;
+
+ val = l1->init_tag_val;
+
+ for (i = 0; i < l1->no_ops; i++) {
+ qlcnic_ind_wr(adapter, l1->addr, val);
+ qlcnic_ind_wr(adapter, l1->ctrl_addr, LSW(l1->ctrl_val));
+ addr = l1->read_addr;
+ cnt = l1->read_addr_num;
+ while (cnt) {
+ data = qlcnic_ind_rd(adapter, addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += l1->read_addr_stride;
+ cnt--;
+ }
+ val += l1->stride;
+ }
+ return l1->no_ops * l1->read_addr_num * sizeof(u32);
+}
+
+static u32
+qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ int i;
+ u32 cnt, val, data, addr;
+ u8 poll_mask, poll_to, time_out = 0;
+ struct __cache *l2 = &entry->region.cache;
+
+ val = l2->init_tag_val;
+ poll_mask = LSB(MSW(l2->ctrl_val));
+ poll_to = MSB(MSW(l2->ctrl_val));
+
+ for (i = 0; i < l2->no_ops; i++) {
+ qlcnic_ind_wr(adapter, l2->addr, val);
+ if (LSW(l2->ctrl_val))
+ qlcnic_ind_wr(adapter, l2->ctrl_addr,
+ LSW(l2->ctrl_val));
+ if (!poll_mask)
+ goto skip_poll;
+ do {
+ data = qlcnic_ind_rd(adapter, l2->ctrl_addr);
+ if (!(data & poll_mask))
+ break;
+ usleep_range(1000, 2000);
+ time_out++;
+ } while (time_out <= poll_to);
+
+ if (time_out > poll_to) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return 0;
+ }
+skip_poll:
+ addr = l2->read_addr;
+ cnt = l2->read_addr_num;
+ while (cnt) {
+ data = qlcnic_ind_rd(adapter, addr);
+ *buffer++ = cpu_to_le32(data);
+ addr += l2->read_addr_stride;
+ cnt--;
+ }
+ val += l2->stride;
+ }
+ return l2->no_ops * l2->read_addr_num * sizeof(u32);
+}
+
+static u32
+qlcnic_read_memory(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ u32 addr, data, test, ret = 0;
+ int i, reg_read;
+ struct __mem *mem = &entry->region.mem;
+
+ reg_read = mem->size;
+ addr = mem->addr;
+ /* check for data size of multiple of 16 and 16 byte alignment */
+ if ((addr & 0xf) || (reg_read%16)) {
+ dev_info(&adapter->pdev->dev,
+ "Unaligned memory addr:0x%x size:0x%x\n",
+ addr, reg_read);
+ return 0;
+ }
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ while (reg_read != 0) {
+ qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_LO, addr);
+ qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_HI, 0);
+ qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLC_TA_START_ENABLE);
+
+ for (i = 0; i < MAX_CTL_CHECK; i++) {
+ test = qlcnic_ind_rd(adapter, QLCNIC_MS_CTRL);
+ if (!(test & TA_CTL_BUSY))
+ break;
+ }
+ if (i == MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_WARNING
+ "failed to read through agent\n");
+ ret = 0;
+ goto out;
+ }
+ for (i = 0; i < 4; i++) {
+ data = qlcnic_ind_rd(adapter, QLCNIC_MS_READ_DATA[i]);
+ *buffer++ = cpu_to_le32(data);
+ }
+ addr += 16;
+ reg_read -= 16;
+ ret += 16;
+ }
+out:
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return mem->size;
+}
+
+static u32
+qlcnic_dump_nop(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ return 0;
+}
+
+static int
+qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
+ u32 size)
+{
+ int ret = 1;
+ if (size != entry->hdr.cap_size) {
+ dev_info(dev,
+ "Invalid entry, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
+ entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
+ ret = 0;
+ }
+ return ret;
+}
+
+static u32
+qlcnic_read_pollrdmwr(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ struct __pollrdmwr *poll = &entry->region.pollrdmwr;
+ u32 data, wait_count, poll_wait, temp;
+
+ poll_wait = poll->poll_wait;
+
+ qlcnic_ind_wr(adapter, poll->addr1, poll->val1);
+ wait_count = 0;
+
+ while (wait_count < poll_wait) {
+ data = qlcnic_ind_rd(adapter, poll->addr1);
+ if ((data & poll->poll_mask) != 0)
+ break;
+ wait_count++;
+ }
+
+ if (wait_count == poll_wait) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return 0;
+ }
+
+ data = qlcnic_ind_rd(adapter, poll->addr2) & poll->mod_mask;
+ qlcnic_ind_wr(adapter, poll->addr2, data);
+ qlcnic_ind_wr(adapter, poll->addr1, poll->val2);
+ wait_count = 0;
+
+ while (wait_count < poll_wait) {
+ temp = qlcnic_ind_rd(adapter, poll->addr1);
+ if ((temp & poll->poll_mask) != 0)
+ break;
+ wait_count++;
+ }
+
+ *buffer++ = cpu_to_le32(poll->addr2);
+ *buffer++ = cpu_to_le32(data);
+
+ return 2 * sizeof(u32);
+
+}
+
+static u32
+qlcnic_read_pollrd(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ struct __pollrd *pollrd = &entry->region.pollrd;
+ u32 data, wait_count, poll_wait, sel_val;
+ int i;
+
+ poll_wait = pollrd->poll_wait;
+ sel_val = pollrd->sel_val;
+
+ for (i = 0; i < pollrd->no_ops; i++) {
+ qlcnic_ind_wr(adapter, pollrd->sel_addr, sel_val);
+ wait_count = 0;
+ while (wait_count < poll_wait) {
+ data = qlcnic_ind_rd(adapter, pollrd->sel_addr);
+ if ((data & pollrd->poll_mask) != 0)
+ break;
+ wait_count++;
+ }
+
+ if (wait_count == poll_wait) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout exceeded in %s, aborting dump\n",
+ __func__);
+ return 0;
+ }
+
+ data = qlcnic_ind_rd(adapter, pollrd->read_addr);
+ *buffer++ = cpu_to_le32(sel_val);
+ *buffer++ = cpu_to_le32(data);
+ sel_val += pollrd->sel_val_stride;
+ }
+ return pollrd->no_ops * (2 * sizeof(u32));
+}
+
+static u32
+qlcnic_read_mux2(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ struct __mux2 *mux2 = &entry->region.mux2;
+ u32 data;
+ u32 t_sel_val, sel_val1, sel_val2;
+ int i;
+
+ sel_val1 = mux2->sel_val1;
+ sel_val2 = mux2->sel_val2;
+
+ for (i = 0; i < mux2->no_ops; i++) {
+ qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val1);
+ t_sel_val = sel_val1 & mux2->sel_val_mask;
+ qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val);
+ data = qlcnic_ind_rd(adapter, mux2->read_addr);
+ *buffer++ = cpu_to_le32(t_sel_val);
+ *buffer++ = cpu_to_le32(data);
+ qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val2);
+ t_sel_val = sel_val2 & mux2->sel_val_mask;
+ qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val);
+ data = qlcnic_ind_rd(adapter, mux2->read_addr);
+ *buffer++ = cpu_to_le32(t_sel_val);
+ *buffer++ = cpu_to_le32(data);
+ sel_val1 += mux2->sel_val_stride;
+ sel_val2 += mux2->sel_val_stride;
+ }
+
+ return mux2->no_ops * (4 * sizeof(u32));
+}
+
+static u32
+qlcnic_83xx_dump_rom(struct qlcnic_adapter *adapter,
+ struct qlcnic_dump_entry *entry, u32 *buffer)
+{
+ u32 fl_addr, size;
+ struct __mem *rom = &entry->region.mem;
+
+ fl_addr = rom->addr;
+ size = rom->size/4;
+
+ if (!qlcnic_83xx_lockless_flash_read_u32(adapter,
+ fl_addr, (u8 *)buffer, size))
+ return rom->size;
+
+ return 0;
+}
+
+static const struct qlcnic_dump_operations qlcnic_fw_dump_ops[] = {
+ { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
+ { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
+ { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
+ { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
+ { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
+ { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
+ { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
+ { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
+ { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
+ { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
+};
+
+static const struct qlcnic_dump_operations qlcnic_83xx_fw_dump_ops[] = {
+ { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
+ { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
+ { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
+ { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
+ { QLCNIC_DUMP_BRD_CONFIG, qlcnic_83xx_dump_rom },
+ { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
+ { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
+ { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
+ { QLCNIC_DUMP_POLL_RD, qlcnic_read_pollrd },
+ { QLCNIC_READ_MUX2, qlcnic_read_mux2 },
+ { QLCNIC_READ_POLLRDMWR, qlcnic_read_pollrdmwr },
+ { QLCNIC_DUMP_READ_ROM, qlcnic_83xx_dump_rom },
+ { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
+ { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
+ { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
+ { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
+};
+
+static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)
+{
+ uint64_t sum = 0;
+ int count = temp_size / sizeof(uint32_t);
+ while (count-- > 0)
+ sum += *temp_buffer++;
+ while (sum >> 32)
+ sum = (sum & 0xFFFFFFFF) + (sum >> 32);
+ return ~sum;
+}
+
+static int
+qlcnic_fw_flash_get_minidump_temp(struct qlcnic_adapter *adapter,
+ u8 *buffer, u32 size)
+{
+ int ret = 0;
+
+ if (QLCNIC_IS_82XX(adapter))
+ return -EIO;
+
+ if (qlcnic_83xx_lock_flash(adapter))
+ return -EIO;
+
+ ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ QLC_83XX_MINIDUMP_FLASH, buffer, size/sizeof(u32));
+
+ qlcnic_83xx_unlock_flash(adapter);
+
+ return ret;
+}
+
+static int
+qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter,
+ struct qlcnic_cmd_args *cmd)
+{
+ struct qlcnic_dump_template_hdr tmp_hdr;
+ u32 size = sizeof(struct qlcnic_dump_template_hdr) / sizeof(u32);
+ int ret = 0;
+
+ if (QLCNIC_IS_82XX(adapter))
+ return -EIO;
+
+ if (qlcnic_83xx_lock_flash(adapter))
+ return -EIO;
+
+ ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ QLC_83XX_MINIDUMP_FLASH, (u8 *)&tmp_hdr, size);
+
+ qlcnic_83xx_unlock_flash(adapter);
+
+ cmd->rsp.arg[2] = tmp_hdr.size;
+ cmd->rsp.arg[3] = tmp_hdr.version;
+
+ return ret;
+}
+
+static int
+qlcnic_fw_get_minidump_temp_size(struct qlcnic_adapter *adapter,
+ u32 *version, u32 *temp_size, u8 *use_flash_temp)
+{
+ int err = 0;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_hardware_context *ahw;
+
+ ahw = adapter->ahw;
+ if (adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_TEMP_SIZE))
+ return -ENOMEM;
+
+ err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err != QLCNIC_RCODE_SUCCESS) {
+ if (qlcnic_fw_flash_get_minidump_temp_size(adapter, &cmd)) {
+ qlcnic_free_mbx_args(&cmd);
+ return -EIO;
+ }
+ *use_flash_temp = 1;
+ }
+
+ *temp_size = cmd.rsp.arg[2];
+ *version = cmd.rsp.arg[3];
+ qlcnic_free_mbx_args(&cmd);
+
+ if (!(*temp_size))
+ return -EIO;
+
+ return 0;
+}
+
+static
+int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter,
+ u32 *buffer, u32 temp_size)
+{
+ int err = 0, i;
+ void *tmp_addr;
+ u32 *tmp_buf;
+ struct qlcnic_cmd_args cmd;
+ dma_addr_t tmp_addr_t = 0;
+
+ tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,
+ &tmp_addr_t, GFP_KERNEL);
+ if (!tmp_addr) {
+ dev_err(&adapter->pdev->dev,
+ "Can't get memory for FW dump template\n");
+ return -ENOMEM;
+ }
+
+ if (adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_TEMP_HDR)) {
+ err = -ENOMEM;
+ goto free_mem;
+ }
+
+ cmd.req.arg[1] = LSD(tmp_addr_t);
+ cmd.req.arg[2] = MSD(tmp_addr_t);
+ cmd.req.arg[3] = temp_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ tmp_buf = tmp_addr;
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ for (i = 0; i < temp_size/sizeof(u32); i++)
+ *buffer++ = __le32_to_cpu(*tmp_buf++);
+ }
+
+ qlcnic_free_mbx_args(&cmd);
+
+free_mem:
+ dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
+
+ return err;
+}
+
+int
+qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
+{
+ int err;
+ u32 temp_size = 0;
+ u32 version, csum, *tmp_buf;
+ struct qlcnic_hardware_context *ahw;
+ struct qlcnic_dump_template_hdr *tmpl_hdr;
+ u8 use_flash_temp = 0;
+
+ ahw = adapter->ahw;
+
+ err = qlcnic_fw_get_minidump_temp_size(adapter, &version,
+ &temp_size, &use_flash_temp);
+
+ if (err) {
+ dev_info(&adapter->pdev->dev,
+ "Can't get template size %d\n", err);
+ return -EIO;
+ }
+
+ ahw->fw_dump.tmpl_hdr = vmalloc(temp_size);
+
+ if (!ahw->fw_dump.tmpl_hdr)
+ return -ENOMEM;
+
+ memset(ahw->fw_dump.tmpl_hdr, 0, temp_size);
+ tmp_buf = (u32 *)ahw->fw_dump.tmpl_hdr;
+
+ if (use_flash_temp)
+ goto flash_temp;
+
+ err = __qlcnic_fw_cmd_get_minidump_temp(adapter, tmp_buf, temp_size);
+
+ if (err) {
+flash_temp:
+ err = qlcnic_fw_flash_get_minidump_temp(adapter,
+ (u8 *)tmp_buf, temp_size);
+
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get minidump template header %d\n",
+ err);
+ vfree(ahw->fw_dump.tmpl_hdr);
+ ahw->fw_dump.tmpl_hdr = NULL;
+ return -EIO;
+ }
+ }
+
+ csum = qlcnic_temp_checksum((uint32_t *) tmp_buf, temp_size);
+
+ if (csum) {
+ dev_err(&adapter->pdev->dev,
+ "Template header checksum validation failed\n");
+ vfree(ahw->fw_dump.tmpl_hdr);
+ ahw->fw_dump.tmpl_hdr = NULL;
+ return -EIO;
+ }
+
+ tmpl_hdr = ahw->fw_dump.tmpl_hdr;
+ tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+ ahw->fw_dump.enable = 1;
+
+ return 0;
+}
+
+int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
+{
+ u32 *buffer;
+ char mesg[64];
+ char *msg[] = {mesg, NULL};
+ int i, k, ops_cnt, ops_index, dump_size = 0;
+ u32 entry_offset, dump, no_entries, buf_offset = 0;
+ struct qlcnic_dump_entry *entry;
+ struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
+ static const struct qlcnic_dump_operations *fw_dump_ops;
+
+ if (!fw_dump->enable) {
+ dev_info(&adapter->pdev->dev,
+ "Dump not enabled\n");
+ return -EIO;
+ }
+
+ if (fw_dump->clr) {
+ dev_info(&adapter->pdev->dev,
+ "Previous dump not cleared, not capturing dump\n");
+ return -EIO;
+ }
+
+ QLCDB(adapter, DRV, "Take FW dump\n");
+ /* Calculate the size for dump data area only */
+ for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
+ if (i & tmpl_hdr->drv_cap_mask)
+ dump_size += tmpl_hdr->cap_sizes[k];
+ if (!dump_size)
+ return -EIO;
+
+ fw_dump->data = vmalloc(dump_size);
+ if (!fw_dump->data) {
+ dev_info(&adapter->pdev->dev,
+ "Unable to allocate (%d KB) for fw dump\n",
+ dump_size/1024);
+ return -ENOMEM;
+ }
+ memset(fw_dump->data, 0, dump_size);
+ buffer = fw_dump->data;
+ fw_dump->size = dump_size;
+ no_entries = tmpl_hdr->num_entries;
+ entry_offset = tmpl_hdr->offset;
+ tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
+ tmpl_hdr->sys_info[1] = adapter->fw_version;
+
+ if (QLCNIC_IS_82XX(adapter)) {
+ ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops);
+ fw_dump_ops = qlcnic_fw_dump_ops;
+ } else {
+ ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops);
+ fw_dump_ops = qlcnic_83xx_fw_dump_ops;
+ tmpl_hdr->saved_state[QLC_83XX_OCM_INDEX] =
+ tmpl_hdr->ocm_wnd_reg[adapter->ahw->pci_func];
+ tmpl_hdr->saved_state[QLC_83XX_PCI_INDEX] =
+ adapter->ahw->pci_func;
+ }
+
+ for (i = 0; i < no_entries; i++) {
+ entry = (void *)tmpl_hdr + entry_offset;
+ if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ entry_offset += entry->hdr.offset;
+ continue;
+ }
+
+ /* Find the handler for this entry */
+ ops_index = 0;
+ while (ops_index < ops_cnt) {
+ if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
+ break;
+ ops_index++;
+ }
+
+ if (ops_index == ops_cnt) {
+ dev_info(&adapter->pdev->dev,
+ "Invalid entry type %d, exiting dump\n",
+ entry->hdr.type);
+ goto error;
+ }
+
+ /* Collect dump for this entry */
+ dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
+ if (!qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, dump))
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ buf_offset += entry->hdr.cap_size;
+ entry_offset += entry->hdr.offset;
+ buffer = fw_dump->data + buf_offset;
+ }
+ if (dump_size != buf_offset) {
+ dev_info(&adapter->pdev->dev,
+ "Captured(%d) and expected size(%d) do not match\n",
+ buf_offset, dump_size);
+ goto error;
+ } else {
+ fw_dump->clr = 1;
+ snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
+ adapter->netdev->name);
+ dev_info(&adapter->pdev->dev,
+ "%s: Dump data, %d bytes captured\n",
+ adapter->netdev->name, fw_dump->size);
+ /* Send a udev event to notify availability of FW dump */
+ kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
+ return 0;
+ }
+error:
+ vfree(fw_dump->data);
+ return -EINVAL;
+}
+
+void
+qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter)
+{
+ u32 prev_version, current_version;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
+ struct pci_dev *pdev = adapter->pdev;
+
+ prev_version = adapter->fw_version;
+ current_version = qlcnic_83xx_get_fw_version(adapter);
+
+ if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) {
+ if (fw_dump->tmpl_hdr)
+ vfree(fw_dump->tmpl_hdr);
+ if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+ dev_info(&pdev->dev,
+ "Supports FW dump capability\n");
+ }
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 07/15] qlcnic: 83xx data path and HW interfaces routines
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Create 83xx adapter data path and hardware interface routines
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Manish chopra <manish.chopra@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 48 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 2692 ++++++++++++++++++++
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 627 +++++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 18 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 -
6 files changed, 3373 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index 34db053..2968c57 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
- qlcnic_sysfs.o
+ qlcnic_sysfs.o qlcnic_83xx_hw.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 29caa81..3886e17 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -34,6 +34,7 @@
#include "qlcnic_hdr.h"
#include "qlcnic_hw.h"
+#include "qlcnic_83xx_hw.h"
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 1
@@ -504,9 +505,13 @@ struct qlcnic_hardware_context {
struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
+ struct qlcnic_83xx_reset reset;
+ struct qlcnic_83xx_idc idc;
+ struct qlcnic_83xx_fw_info fw_info;
struct qlcnic_intrpt_config *intr_tbl;
u32 *reg_tbl;
u32 *ext_reg_tbl;
+ u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
spinlock_t mbx_lock;
};
@@ -1346,6 +1351,42 @@ struct __queue {
u8 rsvd3[2];
} __packed;
+struct __pollrd {
+ __le32 sel_addr;
+ __le32 read_addr;
+ __le32 sel_val;
+ __le16 sel_val_stride;
+ __le16 no_ops;
+ __le32 poll_wait;
+ __le32 poll_mask;
+ __le32 data_size;
+ u8 rsvd[4];
+} __packed;
+
+struct __mux2 {
+ __le32 sel_addr1;
+ __le32 sel_addr2;
+ __le32 sel_val1;
+ __le32 sel_val2;
+ __le32 no_ops;
+ __le32 sel_val_mask;
+ __le32 read_addr;
+ u8 sel_val_stride;
+ u8 data_size;
+ u8 rsvd[2];
+} __packed;
+
+struct __pollrdmwr {
+ __le32 addr1;
+ __le32 addr2;
+ __le32 val1;
+ __le32 val2;
+ __le32 poll_wait;
+ __le32 poll_mask;
+ __le32 mod_mask;
+ __le32 data_size;
+} __packed;
+
struct qlcnic_dump_entry {
struct qlcnic_common_entry_hdr hdr;
union {
@@ -1356,6 +1397,9 @@ struct qlcnic_dump_entry {
struct __mux mux;
struct __queue que;
struct __ctrl ctrl;
+ struct __pollrdmwr pollrdmwr;
+ struct __mux2 mux2;
+ struct __pollrd pollrd;
} region;
} __packed;
@@ -1421,7 +1465,6 @@ struct qlcnic_cmd_args {
struct _cdrp_cmd rsp;
};
-int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *);
@@ -1475,7 +1518,6 @@ int qlcnic_wol_supported(struct qlcnic_adapter *);
int qlcnic_config_led(struct qlcnic_adapter *, u32, u32);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *);
-int qlcnic_dump_fw(struct qlcnic_adapter *);
void qlcnic_get_ocm_win(struct qlcnic_hardware_context *);
void qlcnic_get_func_no(struct qlcnic_adapter *);
int qlcnic_api_lock(struct qlcnic_adapter *);
@@ -1561,7 +1603,7 @@ int qlcnic_rx_poll(struct napi_struct *, int);
void qlcnic_set_vlan_config(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
- struct qlcnic_esw_func_cfg *);
+ struct qlcnic_esw_func_cfg *);
int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
void qlcnic_check_options(struct qlcnic_adapter *adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
new file mode 100644
index 0000000..4edbdd2
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -0,0 +1,2692 @@
+#include "qlcnic.h"
+#include <linux/if_vlan.h>
+#include <linux/ipv6.h>
+#include <linux/ethtool.h>
+#include <linux/interrupt.h>
+
+/* Array of FW control command structs with command type and required
+ * number of input and output arguments respectively.
+*/
+static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
+ { QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1 },
+ { QLCNIC_CMD_CONFIG_INTRPT, 18, 34 },
+ { QLCNIC_CMD_CREATE_RX_CTX, 136, 27 },
+ { QLCNIC_CMD_DESTROY_RX_CTX, 2, 1 },
+ { QLCNIC_CMD_CREATE_TX_CTX, 54, 18 },
+ { QLCNIC_CMD_DESTROY_TX_CTX, 2, 1 },
+ { QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1 },
+ { QLCNIC_CMD_INTRPT_TEST, 22, 12 },
+ { QLCNIC_CMD_SET_MTU, 3, 1 },
+ { QLCNIC_CMD_READ_PHY, 4, 2 },
+ { QLCNIC_CMD_WRITE_PHY, 5, 1 },
+ { QLCNIC_CMD_READ_HW_REG, 4, 1 },
+ { QLCNIC_CMD_GET_FLOW_CTL, 4, 2 },
+ { QLCNIC_CMD_SET_FLOW_CTL, 4, 1 },
+ { QLCNIC_CMD_READ_MAX_MTU, 4, 2 },
+ { QLCNIC_CMD_READ_MAX_LRO, 4, 2 },
+ { QLCNIC_CMD_MAC_ADDRESS, 4, 3 },
+ { QLCNIC_CMD_GET_PCI_INFO, 1, 66 },
+ { QLCNIC_CMD_GET_NIC_INFO, 2, 19 },
+ { QLCNIC_CMD_SET_NIC_INFO, 32, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3 },
+ { QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3 },
+ { QLCNIC_CMD_SET_PORTMIRRORING, 4, 1 },
+ { QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3 },
+ { QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1 },
+ { QLCNIC_CMD_CONFIG_PORT, 4, 1 },
+ { QLCNIC_CMD_TEMP_SIZE, 1, 4 },
+ { QLCNIC_CMD_GET_TEMP_HDR, 5, 5 },
+ { QLCNIC_CMD_GET_LINK_EVENT, 2, 1 },
+ { QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 1 },
+ { QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1 },
+ { QLCNIC_CMD_CONFIGURE_RSS, 14, 1 },
+ { QLCNIC_CMD_CONFIGURE_LED, 2, 1 },
+ { QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1 },
+ { QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1 },
+ { QLCNIC_CMD_GET_STATISTICS, 2, 80 },
+ { QLCNIC_CMD_SET_PORT_CONFIG, 2, 1 },
+ { QLCNIC_CMD_GET_PORT_CONFIG, 2, 2 },
+ { QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
+ { QLCNIC_CMD_IDC_ACK, 5, 1},
+ { QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
+ { QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
+ { QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
+ { QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
+};
+const u32 qlcnic_83xx_ext_reg_tbl[] = {
+ 0x38CC, /* Global Reset */
+ 0x38F0, /* Wildcard */
+ 0x38FC, /* Informant */
+ 0x3038, /* Host MBX ctrl */
+ 0x303C, /* FW MBX ctrl */
+ 0x355C, /* BOOT LOADER ADDRESS REG */
+ 0x3560, /* BOOT LOADER SIZE REG */
+ 0x3564, /* FW IMAGE ADDR REG */
+ 0x1000, /* MBX intr enable */
+ 0x1200, /* Default Intr mask */
+ 0x1204, /* Default Interrupt ID */
+ 0x3780, /* QLC_83XX_IDC_MAJ_VERSION */
+ 0x3784, /* QLC_83XX_IDC_DEV_STATE */
+ 0x3788, /* QLC_83XX_IDC_DRV_PRESENCE */
+ 0x378C, /* QLC_83XX_IDC_DRV_ACK */
+ 0x3790, /* QLC_83XX_IDC_CTRL */
+ 0x3794, /* QLC_83XX_IDC_DRV_AUDIT */
+ 0x3798, /* QLC_83XX_IDC_MIN_VERSION */
+ 0x379C, /* QLC_83XX_RECOVER_DRV_LOCK */
+ 0x37A0, /* QLC_83XX_IDC_PF_0 */
+ 0x37A4, /* QLC_83XX_IDC_PF_1 */
+ 0x37A8, /* QLC_83XX_IDC_PF_2 */
+ 0x37AC, /* QLC_83XX_IDC_PF_3 */
+ 0x37B0, /* QLC_83XX_IDC_PF_4 */
+ 0x37B4, /* QLC_83XX_IDC_PF_5 */
+ 0x37B8, /* QLC_83XX_IDC_PF_6 */
+ 0x37BC, /* QLC_83XX_IDC_PF_7 */
+ 0x37C0, /* QLC_83XX_IDC_PF_8 */
+ 0x37C4, /* QLC_83XX_IDC_PF_9 */
+ 0x37C8, /* QLC_83XX_IDC_PF_10 */
+ 0x37CC, /* QLC_83XX_IDC_PF_11 */
+ 0x37D0, /* QLC_83XX_IDC_PF_12 */
+ 0x37D4, /* QLC_83XX_IDC_PF_13 */
+ 0x37D8, /* QLC_83XX_IDC_PF_14 */
+ 0x37DC, /* QLC_83XX_IDC_PF_15 */
+ 0x37E0, /* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */
+ 0x37E4, /* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */
+ 0x37F0, /* QLC_83XX_DRV_OP_MODE */
+ 0x37F4, /* QLC_83XX_VNIC_STATE */
+ 0x3868, /* QLC_83XX_DRV_LOCK */
+ 0x386C, /* QLC_83XX_DRV_UNLOCK */
+ 0x3504, /* QLC_83XX_DRV_LOCK_ID */
+ 0x34A4, /* QLC_83XX_ASIC_TEMP */
+};
+
+const u32 qlcnic_83xx_reg_tbl[] = {
+ 0x34A8, /* PEG_HALT_STAT1 */
+ 0x34AC, /* PEG_HALT_STAT2 */
+ 0x34B0, /* FW_HEARTBEAT */
+ 0x3500, /* FLASH LOCK_ID */
+ 0x3528, /* FW_CAPABILITIES */
+ 0x3538, /* drv active, DRV_REG0 */
+ 0x3540, /* dev state, DRV_REG1 */
+ 0x3544, /* drv state, DRV_REG2 */
+ 0x3548, /* drv scratch, DRV_REG3 */
+ 0x354C, /* dev part info, DRV_REG4 */
+ 0x3524, /* drv IDC ver, DRV_REG5 */
+ 0x3550, /* FW_VER_MAJOR */
+ 0x3554, /* FW_VER_MINOR */
+ 0x3558, /* FW_VER_SUB */
+ 0x359C, /* NPAR STATE */
+ 0x35FC, /* FW_IMG_VALID */
+ 0x3650, /* CMD_PEG_STATE */
+ 0x373C, /* RCV_PEG_STATE */
+ 0x37B4, /* ASIC TEMP */
+ 0x356C, /* FW API */
+ 0x3570, /* DRV OP MODE */
+ 0x3850, /* FLASH LOCK */
+ 0x3854, /* FLASH UNLOCK */
+};
+
+struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
+ .read_crb = qlcnic_83xx_read_crb,
+ .write_crb = qlcnic_83xx_write_crb,
+ .rdreg = qlcnic_83xx_rd_reg_indirect,
+ .wrtreg = qlcnic_83xx_wrt_reg_indirect,
+ .get_mac_address = qlcnic_83xx_get_mac_address,
+ .setup_intr = qlcnic_83xx_setup_intr,
+ .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
+ .mbx_cmd = qlcnic_83xx_mbx_op,
+ .get_func_no = qlcnic_83xx_get_func_no,
+ .api_lock = qlcnic_83xx_cam_lock,
+ .api_unlock = qlcnic_83xx_cam_unlock,
+ .add_sysfs = qlcnic_83xx_add_sysfs,
+ .remove_sysfs = qlcnic_83xx_remove_sysfs,
+ .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
+ .create_rx_ctx = qlcnic_83xx_create_rx_ctx,
+ .create_tx_ctx = qlcnic_83xx_create_tx_ctx,
+ .setup_link_event = qlcnic_83xx_setup_link_event,
+ .get_nic_info = qlcnic_83xx_get_nic_info,
+ .get_pci_info = qlcnic_83xx_get_pci_info,
+ .set_nic_info = qlcnic_83xx_set_nic_info,
+ .change_macvlan = qlcnic_83xx_sre_macaddr_change,
+ .napi_enable = qlcnic_83xx_napi_enable,
+ .napi_disable = qlcnic_83xx_napi_disable,
+ .config_intr_coal = qlcnic_83xx_config_intr_coal,
+ .config_rss = qlcnic_83xx_config_rss,
+ .config_hw_lro = qlcnic_83xx_config_hw_lro,
+ .config_loopback = qlcnic_83xx_set_lb_mode,
+ .clear_loopback = qlcnic_83xx_clear_lb_mode,
+ .config_promisc_mode = qlcnic_83xx_nic_set_promisc,
+ .change_l2_filter = qlcnic_83xx_change_l2_filter,
+ .get_board_info = qlcnic_83xx_get_port_info,
+};
+
+struct qlcnic_nic_template qlcnic_83xx_ops = {
+ .config_bridged_mode = qlcnic_config_bridged_mode,
+ .config_led = qlcnic_config_led,
+ .napi_add = qlcnic_83xx_napi_add,
+ .config_ipaddr = qlcnic_83xx_config_ipaddr,
+ .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
+};
+
+int
+qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
+{
+ return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
+ sizeof(adapter->ahw->ext_reg_tbl)) +
+ (ARRAY_SIZE(qlcnic_83xx_reg_tbl) +
+ sizeof(adapter->ahw->reg_tbl));
+}
+
+int
+qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
+{
+ int i, j = 0;
+
+ for (i = QLCNIC_DEV_INFO_SIZE + 1;
+ j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++)
+ regs_buff[i] = QLCRD(adapter, j);
+
+ for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++)
+ regs_buff[i++] = QLCRDX(adapter->ahw, j);
+ return i;
+}
+
+int
+qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
+{
+ u32 fw_major, fw_minor, fw_build;
+ struct pci_dev *pdev = adapter->pdev;
+
+ fw_major = QLCRD(adapter, QLCNIC_FW_VERSION_MAJOR);
+ fw_minor = QLCRD(adapter, QLCNIC_FW_VERSION_MINOR);
+ fw_build = QLCRD(adapter, QLCNIC_FW_VERSION_SUB);
+ adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
+
+ dev_info(&pdev->dev, "firmware version %d.%d.%d\n",
+ fw_major, fw_minor, fw_build);
+
+ return adapter->fw_version;
+}
+
+/* Caller needs to use locking before accessing this function */
+static int
+__qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
+{
+ void __iomem *base;
+ u32 val;
+
+ base = adapter->ahw->pci_base0 +
+ QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
+ writel(addr, base);
+ val = readl(base);
+ if (val != addr)
+ return -EIO;
+
+ return 0;
+}
+
+u32
+qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter,
+ ulong addr, int *err)
+{
+ int ret;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ ret = __qlcnic_set_win_base(adapter, (u32) addr);
+ if (!ret) {
+ return QLCRDX(ahw, QLCNIC_WILDCARD);
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "%s failed, addr = 0x%x\n", __func__, (int)addr);
+ if (err)
+ *err = -EIO;
+
+ return -1;
+ }
+}
+
+/* Caller needs to use locking before accessing this function */
+int
+qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
+ u32 data)
+{
+ int err;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ err = __qlcnic_set_win_base(adapter, (u32) addr);
+ if (!err) {
+ QLCWRX(ahw, QLCNIC_WILDCARD, data);
+ return 0;
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "%s failed, addr = 0x%x data = 0x%x\n",
+ __func__, (int)addr, data);
+ return err;
+ }
+}
+
+int
+qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
+{
+ int err, i, num_msix;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (!num_intr)
+ num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
+ num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
+ num_intr));
+ /* account for AEN interrupt MSI-X based interrupts */
+ num_msix += 1;
+ num_msix += adapter->max_drv_tx_rings;
+ err = qlcnic_enable_msix(adapter, num_msix);
+ if (err == -ENOMEM)
+ return err;
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ num_msix = adapter->ahw->num_msix;
+ else
+ num_msix = 1;
+ /* setup interrupt mapping table for fw */
+ ahw->intr_tbl = vmalloc(num_msix *
+ sizeof(struct qlcnic_intrpt_config));
+ if (!ahw->intr_tbl)
+ return -ENOMEM;
+ if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
+ /* MSI-X enablement failed, use legacy interrupt */
+ adapter->tgt_status_reg = ahw->pci_base0 + QLCNIC_83XX_INTX_PTR;
+ adapter->tgt_mask_reg = ahw->pci_base0 + QLCNIC_83XX_INTX_MASK;
+ adapter->isr_int_vec = ahw->pci_base0 + QLCNIC_83XX_INTX_TRGR;
+ adapter->msix_entries[0].vector = adapter->pdev->irq;
+ dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
+ }
+ memset(ahw->intr_tbl, 0, sizeof(struct qlcnic_intrpt_config));
+ for (i = 0; i < num_msix; i++) {
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
+ else
+ ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
+ ahw->intr_tbl[i].id = i;
+ ahw->intr_tbl[i].src = 0;
+ }
+ return 0;
+}
+
+inline void
+qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring)
+{
+ writel(0, sds_ring->crb_intr_mask);
+ if (!QLCNIC_IS_MSI_FAMILY(adapter))
+ writel(0, adapter->tgt_mask_reg);
+}
+
+inline void
+qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring)
+{
+ writel(0, tx_ring->crb_intr_mask);
+}
+
+inline void
+qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring)
+{
+ writel(1, tx_ring->crb_intr_mask);
+}
+
+irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
+{
+ u32 intr_val;
+
+ intr_val = readl(adapter->tgt_status_reg);
+
+ if (!QLCNIC_83XX_VALID_INTX_BIT30(intr_val)) {
+ dev_info(&adapter->pdev->dev,
+ "Invalid legacy interrupt:0x%x\n", intr_val);
+ return IRQ_NONE;
+ }
+ if (QLCNIC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
+ dev_info(&adapter->pdev->dev,
+ "Interrupt for wrong func: 0x%x\n", intr_val);
+ return IRQ_NONE;
+ }
+ /* clear the interrupt trigger control register */
+ writel(0, adapter->isr_int_vec);
+ /* Delay for 4 msec to fix bug in chip, remove it for B0 chip rev */
+ mdelay(4);
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
+{
+ struct qlcnic_host_sds_ring *sds_ring = data;
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ goto done;
+
+ if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
+ return IRQ_NONE;
+
+done:
+ adapter->ahw->diag_cnt++;
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+
+ return IRQ_HANDLED;
+}
+
+void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
+{
+ u32 val = 0;
+ u32 num_msix = adapter->ahw->num_msix - 1;
+
+ val = (num_msix << 8);
+
+ QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ free_irq(adapter->msix_entries[num_msix].vector, adapter);
+}
+
+int
+qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
+{
+ irq_handler_t handler;
+ u32 val;
+ char name[32];
+ int err = 0;
+ unsigned long flags = 0;
+
+ if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
+ !(adapter->flags & QLCNIC_MSIX_ENABLED)) {
+ flags |= IRQF_SHARED;
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ handler = qlcnic_83xx_handle_aen;
+ val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
+ sprintf(name, "%s[%s]", adapter->netdev->name, "aen");
+ err = request_irq(val, handler, flags, name, adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "failed to register MBX interrupt\n");
+ return err;
+ }
+ }
+
+ /* Enable mailbox interrupt */
+ qlcnic_83xx_enable_mbx_intrpt(adapter);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ err = qlcnic_83xx_config_intrpt(adapter, 1);
+
+ return err;
+}
+
+void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
+{
+ u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
+ adapter->ahw->pci_func = val & 0xf;
+}
+
+int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
+{
+ void __iomem *addr;
+ u32 val;
+ u32 timeo = 0;
+
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
+ do {
+ val = readl(addr);
+ if (val) {
+ /* write the function number to register */
+ QLCWR(adapter, QLCNIC_FLASH_LOCK_OWNER, ahw->pci_func);
+ return 0;
+ }
+ usleep_range(1000, 2000);
+ } while (++timeo <= QLCNIC_PCIE_SEM_TIMEOUT);
+
+ return -EIO;
+}
+
+void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
+{
+ void __iomem *addr;
+ u32 val;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
+ val = readl(addr);
+}
+
+void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ u32 data;
+ int err;
+
+ if (adapter->ahw->hw_ops->api_lock(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: failed to acquire lock. addr offset 0x%x\n",
+ __func__, (u32)offset);
+ return;
+ }
+
+ data = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset, &err);
+ adapter->ahw->hw_ops->api_unlock(adapter);
+
+ if (err == -EIO) {
+ dev_err(&adapter->pdev->dev,
+ "%s: failed. addr offset 0x%x\n",
+ __func__, (u32)offset);
+ return;
+ }
+ memcpy(buf, &data, size);
+
+}
+
+void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ u32 data;
+
+ memcpy(&data, buf, size);
+ qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
+}
+
+static void
+qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ u32 id;
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
+
+ /* Check if recovery need to be performed by the calling function */
+ if ((val & QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK) == 0) {
+ val = val & ~0x3F;
+ val = val | ((adapter->portnum << 2) |
+ QLC_83XX_NEED_DRV_LOCK_RECOVERY);
+ QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
+ dev_info(&adapter->pdev->dev,
+ "%s: lock recovery initiated\n", __func__);
+ msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
+ val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
+ id = ((val >> 2) & 0xF);
+ if (id == adapter->portnum) {
+ val = val & ~QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK;
+ val = val | QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS;
+ QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
+ /* Force release the lock */
+ QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
+ /* Clear recovery bits */
+ val = val & ~0x3F;
+ QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
+ dev_info(&adapter->pdev->dev,
+ "%s: lock recovery completed\n", __func__);
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "%s: func %d to resume lock recovery process\n",
+ __func__, id);
+ }
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "%s: lock recovery initiated by other functions\n",
+ __func__);
+ }
+}
+
+int
+qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
+{
+ u32 lock_alive_counter, val, id, i = 0, status = 0, temp = 0;
+ int max_attempt = 0;
+
+ while (status == 0) {
+ status = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK);
+ if (status)
+ break;
+
+ msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
+ i++;
+
+ if (i == 1)
+ temp = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+
+ if (i == QLC_83XX_DRV_LOCK_WAIT_COUNTER) {
+ val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+ if (val == temp) {
+ id = val & 0xFF;
+ dev_info(&adapter->pdev->dev,
+ "%s: lock to be recovered from %d\n",
+ __func__, id);
+ qlcnic_83xx_recover_driver_lock(adapter);
+ i = 0;
+ max_attempt++;
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "%s: failed to acquire lock\n", __func__);
+ return -EIO;
+ }
+ }
+
+ /* Force exit from while loop after few attempts */
+ if (max_attempt == QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT) {
+ dev_info(&adapter->pdev->dev,
+ "%s: failed to acquire lock\n", __func__);
+ return -EIO;
+ }
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+ lock_alive_counter = val >> 8;
+ lock_alive_counter++;
+ val = lock_alive_counter << 8 | adapter->portnum;
+ QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
+
+ return 0;
+}
+
+void
+qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
+{
+ u32 val, lock_alive_counter, id;
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+ id = val & 0xFF;
+ lock_alive_counter = val >> 8;
+
+ if (id != adapter->portnum)
+ dev_err(&adapter->pdev->dev,
+ "%s: Warning! func %d is unlocking lock owned by %d\n",
+ __func__, adapter->portnum, id);
+
+ val = (lock_alive_counter << 8) | 0xFF;
+ QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
+ QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ u8 ring, u64 sts_data[])
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index >= rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ length = qlcnic_83xx_pktln(sts_data[0]);
+ cksum = qlcnic_83xx_csum_status(sts_data[1]);
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return buffer;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+
+ napi_gro_receive(&sds_ring->napi, skb);
+
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return buffer;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ u8 ring, u64 sts_data[])
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h;
+ struct tcphdr *th;
+ bool push;
+ int l2_hdr_offset, l4_hdr_offset;
+ int index;
+ u16 lro_length, length, data_offset;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring > adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index > rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ lro_length = qlcnic_83xx_lro_pktln(sts_data[0]);
+ l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]);
+ l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]);
+ push = qlcnic_83xx_is_psh_bit(sts_data[1]);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return buffer;
+ if (qlcnic_83xx_is_tstamp(sts_data[1]))
+ data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+ else
+ data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+ skb_put(skb, lro_length + data_offset);
+
+ skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (htons(skb->protocol) == ETH_P_IPV6) {
+ ipv6h = (struct ipv6hdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
+
+ length = (th->doff << 2) + lro_length;
+ ipv6h->payload_len = htons(length);
+ } else {
+ iph = (struct iphdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+
+ length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+ iph->tot_len = htons(length);
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ }
+
+
+ th->psh = push;
+
+ length = skb->len;
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+ netif_receive_skb(skb);
+
+ adapter->stats.lro_pkts++;
+ adapter->stats.lrobytes += length;
+ return buffer;
+}
+
+static int
+qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct list_head *cur;
+ struct status_desc *desc;
+ struct qlcnic_rx_buffer *rxbuf = NULL;
+ u64 sts_data[2];
+
+ int count = 0, opcode;
+ u8 ring;
+ u32 consumer = sds_ring->consumer;
+
+ while (count < max) {
+ desc = &sds_ring->desc_head[consumer];
+ sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
+ opcode = qlcnic_83xx_opcode(sts_data[1]);
+ if (!opcode)
+ break;
+ sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
+ ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
+
+ switch (opcode) {
+ case QLCNIC_83XX_REG_DESC:
+ rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring,
+ ring, sts_data);
+ break;
+ case QLCNIC_83XX_LRO_DESC:
+ rxbuf = qlcnic_83xx_process_lro(adapter, sds_ring,
+ ring, sts_data);
+ break;
+ default:
+ dev_info(&adapter->pdev->dev,
+ "Unkonwn opcode: 0x%x\n", opcode);
+ goto skip;
+ }
+
+ if (likely(rxbuf))
+ list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+ else
+ adapter->stats.null_rxbuf++;
+
+skip:
+ desc = &sds_ring->desc_head[consumer];
+ /* Reset the descriptor */
+ desc->status_desc_data[1] = 0;
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ count++;
+ }
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ struct qlcnic_host_rds_ring *rds_ring =
+ &adapter->recv_ctx->rds_rings[ring];
+
+ if (!list_empty(&sds_ring->free_list[ring])) {
+ list_for_each(cur, &sds_ring->free_list[ring]) {
+ rxbuf = list_entry(cur,
+ struct qlcnic_rx_buffer, list);
+ qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+ }
+ spin_lock(&rds_ring->lock);
+ list_splice_tail_init(&sds_ring->free_list[ring],
+ &rds_ring->free_list);
+ spin_unlock(&rds_ring->lock);
+ }
+
+ qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
+ }
+
+ if (count) {
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+ }
+ return count;
+}
+
+static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+ /* there is only 1 tx ring in this path */
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+ int tx_complete;
+ int work_done;
+
+ if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+ qlcnic_83xx_process_aen(adapter);
+
+ tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
+
+ work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
+
+ if ((work_done < budget) && tx_complete) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ return work_done;
+}
+
+static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_tx_ring *tx_ring =
+ container_of(napi, struct qlcnic_host_tx_ring, napi);
+
+ struct qlcnic_adapter *adapter = tx_ring->adapter;
+ int work_done;
+
+ work_done = qlcnic_process_cmd_ring(adapter, tx_ring,
+ QLCNIC_TX_POLL_BUDGET);
+
+ if (work_done) {
+ napi_complete(&tx_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
+ qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ }
+
+ return work_done;
+}
+
+static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ int work_done;
+
+ work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
+
+ if (work_done < budget) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ return work_done;
+}
+
+void
+qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ napi_enable(&sds_ring->napi);
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ napi_enable(&tx_ring->napi);
+ qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ }
+ }
+}
+
+void
+qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_host_tx_ring *tx_ring;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ writel(1, sds_ring->crb_intr_mask);
+ napi_synchronize(&sds_ring->napi);
+ napi_disable(&sds_ring->napi);
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
+ napi_synchronize(&tx_ring->napi);
+ napi_disable(&tx_ring->napi);
+ }
+ }
+}
+
+int
+qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+ return -ENOMEM;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ netif_napi_add(netdev, &sds_ring->napi,
+ qlcnic_83xx_rx_poll, QLCNIC_NETDEV_WEIGHT * 2);
+ else
+ netif_napi_add(netdev, &sds_ring->napi,
+ qlcnic_83xx_poll,
+ QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
+ }
+
+ if (qlcnic_alloc_tx_rings(adapter, netdev)) {
+ qlcnic_free_sds_rings(recv_ctx);
+ return -ENOMEM;
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ netif_napi_add(netdev, &tx_ring->napi,
+ qlcnic_83xx_msix_tx_poll,
+ QLCNIC_NETDEV_WEIGHT);
+ }
+ }
+
+ return 0;
+}
+
+void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data[])
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ length = qlcnic_83xx_pktln(sts_data[0]);
+ cksum = qlcnic_83xx_csum_status(sts_data[0]);
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->ahw->diag_cnt++;
+ else
+ dump_skb(skb, adapter);
+
+ dev_kfree_skb_any(skb);
+ return;
+}
+
+void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data[2];
+ int ring, opcode;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
+ sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
+ opcode = qlcnic_83xx_opcode(sts_data[1]);
+ if (!opcode)
+ return;
+
+ ring = QLCNIC_FETCH_RING_ID(qlcnic_83xx_hndl(sts_data[0]));
+ qlcnic_83xx_process_rcv_diag(adapter, sds_ring, ring, sts_data);
+
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
+
+int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
+{
+ int status;
+
+ status = qlcnic_83xx_get_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "Get Port Info failed\n");
+ } else {
+ if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
+ adapter->ahw->port_type = QLCNIC_XGBE;
+ else
+ adapter->ahw->port_type = QLCNIC_GBE;
+ if (QLC_83XX_AUTONEG(adapter->ahw->port_config))
+ adapter->ahw->link_autoneg = AUTONEG_ENABLE;
+ }
+ return status;
+}
+
+int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
+{
+ int err;
+ u32 config = 0, state;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func));
+ if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) {
+ dev_info(&adapter->pdev->dev, "link state down\n");
+ return config;
+ }
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_LINK_STATUS);
+ err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_info(&adapter->pdev->dev,
+ "Get Link Status Command failed: 0x%x\n", err);
+ goto out;
+ } else {
+ config = le32_to_cpu(cmd.rsp.arg[1]);
+ switch (QLC_83XX_CURRENT_LINK_SPEED(config)) {
+ case QLC_83XX_10M_LINK:
+ ahw->link_speed = SPEED_10;
+ break;
+ case QLC_83XX_100M_LINK:
+ ahw->link_speed = SPEED_100;
+ break;
+ case QLC_83XX_1G_LINK:
+ ahw->link_speed = SPEED_1000;
+ break;
+ case QLC_83XX_10G_LINK:
+ ahw->link_speed = SPEED_10000;
+ break;
+ default:
+ ahw->link_speed = 0;
+ break;
+ }
+ config = le32_to_cpu(cmd.rsp.arg[3]);
+ if (config & 1)
+ err = 1;
+ }
+out:
+ qlcnic_free_mbx_args(&cmd);
+ return config;
+}
+
+int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
+{
+ u32 config = 0;
+ int status = 0;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ /* Get port configuration info */
+ status = qlcnic_83xx_get_port_info(adapter);
+ /* Get Link Status related info */
+ config = qlcnic_83xx_test_link(adapter);
+ ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
+ /* hard code until there is a way to get it from flash/fw */
+ ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
+ return status;
+}
+
+int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter,
+ struct ethtool_cmd *ecmd)
+{
+ int status = 0;
+ u32 config = adapter->ahw->port_config;
+
+ if (ecmd->autoneg)
+ adapter->ahw->port_config |= BIT_15;
+
+ switch (ethtool_cmd_speed(ecmd)) {
+ case SPEED_10:
+ adapter->ahw->port_config |= BIT_8;
+ break;
+ case SPEED_100:
+ adapter->ahw->port_config |= BIT_9;
+ break;
+ case SPEED_1000:
+ adapter->ahw->port_config |= BIT_10;
+ break;
+ case SPEED_10000:
+ adapter->ahw->port_config |= BIT_11;
+ break;
+ default:
+ return -EIO;
+ }
+
+ status = qlcnic_83xx_set_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "Faild to Set Link Speed and autoneg.\n");
+ adapter->ahw->port_config = config;
+ }
+ return status;
+}
+
+static inline u64*
+qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd, u64 *data, int index)
+{
+ u32 low, hi;
+ u64 val;
+
+ low = le32_to_cpu(cmd->rsp.arg[index]);
+ hi = le32_to_cpu(cmd->rsp.arg[index + 1]);
+ val = (((u64) low) | (((u64) hi) << 32));
+ *data++ = val;
+ return data;
+}
+
+static u64*
+qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
+ struct qlcnic_cmd_args *cmd, u64 *data, int type, int *ret)
+{
+ int err, k, total_regs;
+
+ *ret = 0;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, cmd);
+ if (err != QLCNIC_RCODE_SUCCESS) {
+ dev_info(&adapter->pdev->dev,
+ "Error in get statistics mailbox command\n");
+ *ret = -EIO;
+ return data;
+ }
+ total_regs = cmd->rsp.num;
+ switch (type) {
+ case QLCNIC_83XX_STAT_MAC:
+ /* fill in MAC tx counters */
+ for (k = 2; k < 28; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ /* skip 24 bytes of reserved area */
+ /* fill in MAC rx counters */
+ for (k += 6; k < 60; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ /* skip 24 bytes of reserved area */
+ /* fill in MAC rx frame stats */
+ for (k += 6; k < 80; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ break;
+ case QLCNIC_83XX_STAT_RX:
+ for (k = 2; k < 8; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ /* skip 8 bytes of reserved data */
+ for (k += 2; k < 24; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ /* skip 8 bytes containing RE1FBQ error data*/
+ for (k += 2; k < total_regs; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ break;
+ case QLCNIC_83XX_STAT_TX:
+ for (k = 2; k < 10; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ /* skip 8 bytes of reserved data */
+ for (k += 2; k < total_regs; k += 2)
+ data = qlcnic_83xx_copy_stats(cmd, data, k);
+ break;
+ default:
+ dev_info(&adapter->pdev->dev, "Unknown get statistics mode\n");
+ *ret = -EIO;
+ }
+ return data;
+}
+
+/*
+ * Get statistics of MAC and that of Context/Function/Vport
+ */
+void
+qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct qlcnic_cmd_args cmd;
+ int ret = 0;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_STATISTICS);
+ /* Get Tx stats */
+ if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
+ cmd.req.arg[1] = cpu_to_le32(BIT_1 |
+ (adapter->tx_ring->ctx_id << 16));
+ cmd.rsp.num = QLCNIC_83XX_TX_STAT_REGS;
+ data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
+ QLCNIC_83XX_STAT_TX, &ret);
+ if (ret) {
+ dev_info(&adapter->pdev->dev,
+ "Error getting MAC stats\n");
+ goto out;
+ }
+ /* Get MAC stats */
+ cmd.req.arg[1] = cpu_to_le32(BIT_2 | (adapter->portnum << 16));
+ cmd.rsp.num = QLCNIC_83XX_MAC_STAT_REGS;
+ memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
+ data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
+ QLCNIC_83XX_STAT_MAC, &ret);
+ if (ret) {
+ dev_info(&adapter->pdev->dev,
+ "Error getting Rx stats\n");
+ goto out;
+ }
+ /* Get Rx stats */
+ cmd.req.arg[1] =
+ cpu_to_le32(adapter->recv_ctx->context_id << 16);
+ cmd.rsp.num = QLCNIC_83XX_RX_STAT_REGS;
+ memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
+ data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
+ QLCNIC_83XX_STAT_RX, &ret);
+ if (ret)
+ dev_info(&adapter->pdev->dev,
+ "Error in getting Tx stats\n");
+ }
+out:
+ qlcnic_free_mbx_args(&cmd);
+}
+
+int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
+{
+ u32 major, minor, sub;
+
+ major = QLCRD(adapter, QLCNIC_FW_VERSION_MAJOR);
+ minor = QLCRD(adapter, QLCNIC_FW_VERSION_MINOR);
+ sub = QLCRD(adapter, QLCNIC_FW_VERSION_SUB);
+
+ if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) {
+ dev_info(&adapter->pdev->dev, "%s: Reg test failed.\n",
+ __func__);
+ return 1;
+ }
+ return 0;
+}
+
+void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
+ struct ethtool_pauseparam *pause)
+{
+ int status = 0;
+
+ status = qlcnic_83xx_get_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "%s: Get Pause Config failed.\n", __func__);
+ return;
+ }
+ if (adapter->ahw->port_config & QLC_83XX_CFG_PAUSE_STD) {
+ pause->autoneg = 1;
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
+ }
+}
+
+int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
+ struct ethtool_pauseparam *pause)
+{
+ int status = 0;
+ u32 config = adapter->ahw->port_config;
+
+ if ((pause->rx_pause) || (pause->tx_pause) || (pause->autoneg))
+ adapter->ahw->port_config |= QLC_83XX_CFG_PAUSE_STD;
+ else if (!(pause->rx_pause && pause->tx_pause && pause->autoneg))
+ adapter->ahw->port_config &= ~QLC_83XX_CFG_PAUSE_STD;
+ else
+ return -EINVAL;
+
+ status = qlcnic_83xx_set_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "%s: Set Pause Config failed.\n", __func__);
+ adapter->ahw->port_config = config;
+ }
+ return status;
+}
+
+void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
+ else
+ val = BIT_2;
+ QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
+}
+
+void qlcnic_set_npar_data(struct qlcnic_adapter *adapter,
+ const struct qlcnic_info *nic_info, struct qlcnic_info *npar_info)
+{
+ npar_info->pci_func = (le16_to_cpu(nic_info->pci_func)) & 0xF;
+ npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
+ npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
+ npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
+ npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
+ npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
+ npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
+ npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
+ npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
+ npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
+
+ dev_info(&adapter->pdev->dev,
+ "phy port: %d switch_mode: %d,\n"
+ "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n"
+ "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n",
+ npar_info->phys_port, npar_info->switch_mode,
+ npar_info->max_tx_ques, npar_info->max_rx_ques,
+ npar_info->min_tx_bw, npar_info->max_tx_bw,
+ npar_info->max_mtu, npar_info->capabilities);
+}
+
+int
+qlcnic_83xx_ms_mem_write_128b(struct qlcnic_adapter *adapter,
+ u64 addr, u32 *data, u32 count)
+{
+ int i, j, err, ret = 0;
+ u32 temp;
+
+ /* Only 128-bit aligned access */
+ if (addr & 0xF)
+ return -EIO;
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ /* Write address */
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_HI, 0);
+
+ for (i = 0 ; i < count ; i++, addr += 16) {
+ if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX)) ||
+ (ADDR_IN_RANGE(addr, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX)))){
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return -EIO;
+ }
+
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLCNIC_MS_ADDR_LO, addr);
+
+ /* Write data */
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLCNIC_MS_WRTDATA_LO, *data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLCNIC_MS_WRTDATA_HI, *data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLCNIC_MS_WRTDATA_ULO, *data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLCNIC_MS_WRTDATA_UHI, *data++);
+
+ /* Check write status */
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
+ QLC_TA_WRITE_ENABLE);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
+ QLC_TA_WRITE_START);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLCNIC_MS_CTRL, &err);
+ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ /* Status check failed */
+ if (j >= MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_WARNING "memory write err\n");
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return -EIO;
+ }
+ }
+
+ mutex_unlock(&adapter->ahw->mem_lock);
+
+ return ret;
+}
+
+void
+qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
+ const struct pci_device_id *ent)
+{
+ u32 op_mode, priv_level;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ /* Determine FW API version */
+ /* hilda workaround */
+ ahw->fw_hal_version = 2;
+ /* Find PCI function number */
+ ahw->hw_ops->get_func_no(adapter);
+
+ /* Determine function privilege level */
+ op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
+ if (op_mode == QLC_83XX_DEFAULT_OPMODE)
+ priv_level = QLCNIC_MGMT_FUNC;
+ else
+ priv_level = QLC_83XX_GET_FUNC_PRIVILEGE_LEVEL(op_mode,
+ ahw->pci_func);
+
+ if (priv_level == QLCNIC_NON_PRIV_FUNC) {
+ ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
+ dev_info(&adapter->pdev->dev,
+ "HAL Version: %d Non Privileged function\n",
+ ahw->fw_hal_version);
+ adapter->nic_ops = &qlcnic_vf_ops;
+ } else {
+ adapter->nic_ops = &qlcnic_83xx_ops;
+ }
+}
+
+static void
+qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, u32 data[]);
+static void
+qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, u32 data[]);
+
+static void
+qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
+ struct qlcnic_cmd_args *cmd)
+{
+ int i;
+
+ dev_info(&adapter->pdev->dev,
+ "Host MBX regs(%d)\n", cmd->req.num);
+ for (i = 0; i < cmd->req.num; i++) {
+ if (i && !(i % 8))
+ pr_info("\n");
+ pr_info("%08x ", le32_to_cpu(cmd->req.arg[i]));
+ }
+ pr_info("\n");
+ dev_info(&adapter->pdev->dev,
+ "FW MBX regs(%d)\n", cmd->rsp.num);
+ for (i = 0; i < cmd->rsp.num; i++) {
+ if (i && !(i % 8))
+ pr_info("\n");
+ pr_info("%08x ", le32_to_cpu(cmd->rsp.arg[i]));
+ }
+ pr_info("\n");
+}
+
+static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
+{
+ u32 data;
+ unsigned long wait_time = 0;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ /* wait for mailbox completion */
+ do {
+ data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
+ if (++wait_time > QLCNIC_MBX_TIMEOUT) {
+ data = QLCNIC_RCODE_TIMEOUT;
+ break;
+ }
+ mdelay(1);
+ } while (!data);
+ return data;
+}
+
+int
+qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
+{
+ int i;
+ u16 opcode;
+ u8 mbx_err_code;
+ u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, fw[8];
+ unsigned long flags;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ opcode = LSW(le32_to_cpu(cmd->req.arg[0]));
+ if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
+ dev_info(&adapter->pdev->dev,
+ "Mailbox cmd attempted, 0x%x\n", opcode);
+ dev_info(&adapter->pdev->dev, "Mailbox detached\n");
+ return 0;
+ }
+
+ spin_lock_irqsave(&ahw->mbx_lock, flags);
+
+ mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+ if (mbx_val) {
+ dev_info(&adapter->pdev->dev,
+ "Mailbox cmd attempted, 0x%x\n", opcode);
+ dev_info(&adapter->pdev->dev,
+ "Mailbox not available, 0x%x, collect FW dump\n",
+ mbx_val);
+ /* Take FW dump */
+ spin_unlock_irqrestore(&ahw->mbx_lock, flags);
+
+ return cmd->rsp.arg[0];
+ }
+
+ /* Fill in mailbox registers */
+ mbx_cmd = cpu_to_le32(cmd->req.arg[0]);
+ writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
+ for (i = 1; i < cmd->req.num; i++)
+ writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
+
+ /* Signal FW about the impending command */
+ QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
+
+poll:
+ rsp = qlcnic_83xx_mbx_poll(adapter);
+ /* Get the FW response data */
+ fw_data = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, 0)));
+ mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
+ rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
+ opcode = QLCNIC_MBX_RSP(fw_data);
+
+ if (rsp != QLCNIC_RCODE_TIMEOUT) {
+ if (opcode == QLCNIC_MBX_LINK_EVENT) {
+ for (i = 0; i < rsp_num; i++)
+ fw[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw,
+ i)));
+ qlcnic_83xx_handle_link_aen(adapter, fw);
+ /* clear fw mbx control register */
+ QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+ mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+ if (mbx_val)
+ goto poll;
+ } else if (opcode == QLCNIC_MBX_COMP_EVENT) {
+ for (i = 0; i < rsp_num; i++)
+ fw[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw,
+ i)));
+ qlcnic_83xx_handle_idc_comp_aen(adapter, fw);
+ /* clear fw mbx control register */
+ QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+ mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+ if (mbx_val)
+ goto poll;
+ } else if ((mbx_err_code == QLCNIC_MBX_RSP_OK)
+ || (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
+ for (i = 0; i < cmd->rsp.num; i++)
+ cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(ahw, i));
+ rsp = QLCNIC_RCODE_SUCCESS;
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "MBX command 0x%x failed with err:0x%x\n",
+ opcode, mbx_err_code);
+ rsp = mbx_err_code;
+ qlcnic_dump_mbx(adapter, cmd);
+ }
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "MBX command 0x%x timed out\n", opcode);
+ qlcnic_dump_mbx(adapter, cmd);
+ }
+ /* clear fw mbx control register */
+ QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+ spin_unlock_irqrestore(&ahw->mbx_lock, flags);
+ return rsp;
+}
+
+/* Allocate mailbox incoming and outgoing registers. It should be used with a
+ * follow up call to qlcnic_free_mbx_args
+ */
+int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
+ struct qlcnic_adapter *adapter, u32 type)
+{
+ int i, size;
+ const struct qlcnic_mailbox_metadata *mbx_tbl;
+
+ mbx_tbl = qlcnic_83xx_mbx_tbl;
+ size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
+ for (i = 0; i < size; i++) {
+ if (type == mbx_tbl[i].cmd) {
+ mbx->req.num = mbx_tbl[i].in_args;
+ mbx->rsp.num = mbx_tbl[i].out_args;
+ mbx->req.arg = kcalloc(mbx->req.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->req.arg)
+ return -ENOMEM;
+ mbx->rsp.arg = kcalloc(mbx->rsp.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->rsp.arg) {
+ kfree(mbx->req.arg);
+ mbx->req.arg = NULL;
+ return -ENOMEM;
+ }
+ memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
+ memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
+ mbx->req.arg[0] = (type | (mbx->req.num << 16) |
+ (adapter->ahw->fw_hal_version << 29));
+ break;
+ }
+ }
+ return 0;
+}
+
+void qlcnic_83xx_handle_idc_request_aen(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_cmd_args cmd;
+ int i, err = 0;
+
+ /* Issue idc ack mbx command */
+ if (test_and_clear_bit(QLC_83XX_MBX_AEN_ACK,
+ &adapter->ahw->idc.status)) {
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_IDC_ACK);
+ for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
+ cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "%s: Mailbox IDC ACK failed.\n", __func__);
+ qlcnic_free_mbx_args(&cmd);
+ }
+}
+
+static void
+qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, u32 data[])
+{
+ dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
+ QLCNIC_MBX_RSP(data[0]));
+ return;
+}
+
+void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ unsigned long flags;
+ u32 mask, resp, event[QLC_83XX_MBX_AEN_CNT];
+ int i;
+
+ spin_lock_irqsave(&ahw->mbx_lock, flags);
+
+ resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
+ if (!(resp & QLCNIC_SET_OWNER))
+ goto out;
+ for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
+ event[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, i)));
+ switch (QLCNIC_MBX_RSP(event[0])) {
+
+ /* This case is only active when we arrive here
+ * as a result of issuing a mailbox command to
+ * the firmware.
+ */
+ case QLCNIC_MBX_LINK_EVENT:
+ /* Link Event */
+ qlcnic_83xx_handle_link_aen(adapter, event);
+ break;
+ case QLCNIC_MBX_COMP_EVENT:
+ /* IDC Completion Notification */
+ qlcnic_83xx_handle_idc_comp_aen(adapter, event);
+ break;
+ case QLCNIC_MBX_REQUEST_EVENT:
+ /* IDC Request Notification */
+ for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
+ adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
+ /* IDC ack wiil be done by worker thread, just set the flag */
+ set_bit(QLC_83XX_MBX_AEN_ACK, &adapter->ahw->idc.status);
+ break;
+ case QLCNIC_MBX_TIME_EXTEND_EVENT:
+ /* IDC Time Extend Notification */
+ break;
+ case QLCNIC_MBX_SFP_INSERT_EVENT:
+ /* IDC SFP+ Transceiver Insertion Notification */
+ dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
+ QLCNIC_MBX_RSP(event[0]));
+ break;
+ case QLCNIC_MBX_SFP_REMOVE_EVENT:
+ /* IDC SFP+ Transceiver Removal Notification */
+ dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
+ QLCNIC_MBX_RSP(event[0]));
+ break;
+ default:
+ dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
+ QLCNIC_MBX_RSP(event[0]));
+ break;
+ }
+ QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+out:
+ mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
+ writel(0, adapter->ahw->pci_base0 + mask);
+
+ spin_unlock_irqrestore(&ahw->mbx_lock, flags);
+}
+
+int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
+{
+ int i, err, index, sds_mbx_size, rds_mbx_size;
+ u8 num_sds, num_rds;
+ u32 *buf, intrpt_id, intr_mask;
+ struct qlcnic_host_sds_ring *sds;
+ struct qlcnic_host_rds_ring *rds;
+ struct qlcnic_sds_mbx sds_mbx;
+ struct qlcnic_rds_mbx rds_mbx;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_rcv_mbx_out *mbx_out;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ num_sds = adapter->max_sds_rings;
+ num_rds = adapter->max_rds_rings;
+
+ sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
+ rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
+
+ /* set mailbox hdr and capabilities */
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_RX_CTX);
+ cmd.req.arg[1] = cpu_to_le32(QLCNIC_CAP0_LEGACY_CONTEXT);
+ cmd.req.arg[5] = cpu_to_le32(1 | (num_rds << 5) | (num_sds << 8) |
+ (QLCNIC_HOST_83XX_RDS_MODE_UNIQUE << 16));
+ /* set up status rings, mbx 8-57/87 */
+ index = QLCNIC_HOST_SDS_MBX_IDX;
+ for (i = 0; i < num_sds; i++) {
+ memset(&sds_mbx, 0, sds_mbx_size);
+ sds = &recv_ctx->sds_rings[i];
+ sds->consumer = 0;
+ sds_mbx.phy_addr = cpu_to_le64(sds->phys_addr);
+ sds_mbx.sds_ring_size = cpu_to_le16(sds->num_desc);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ intrpt_id = ahw->intr_tbl[i].id;
+ else
+ intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
+ if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
+ sds_mbx.intrpt_id = cpu_to_le32(intrpt_id);
+ else
+ sds_mbx.intrpt_id = 0xffff;
+ sds_mbx.intrpt_val = 0;
+ buf = &cmd.req.arg[index];
+ memcpy(buf, &sds_mbx, sds_mbx_size);
+ index += sds_mbx_size/sizeof(u32);
+ }
+ /* set up receive rings, mbx 88-111/135 */
+ index = QLCNIC_HOST_RDS_MBX_IDX;
+ rds = &recv_ctx->rds_rings[0];
+ rds->producer = 0;
+ memset(&rds_mbx, 0, rds_mbx_size);
+ rds_mbx.phy_addr_reg = cpu_to_le64(rds->phys_addr);
+ rds_mbx.reg_ring_sz = cpu_to_le16(rds->dma_size);
+ rds_mbx.reg_ring_len = cpu_to_le16(rds->num_desc);
+ /* Jumbo ring */
+ rds = &recv_ctx->rds_rings[1];
+ rds->producer = 0;
+ rds_mbx.phy_addr_jmb = cpu_to_le64(rds->phys_addr);
+ rds_mbx.jmb_ring_sz = cpu_to_le16(rds->dma_size);
+ rds_mbx.jmb_ring_len = cpu_to_le16(rds->num_desc);
+ buf = &cmd.req.arg[index];
+ memcpy(buf, &rds_mbx, rds_mbx_size);
+
+ /* send the mailbox command */
+ err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create Rx ctx in firmware%d\n", err);
+ goto out;
+ }
+ mbx_out = (struct qlcnic_rcv_mbx_out *) &cmd.rsp.arg[1];
+ recv_ctx->context_id = le16_to_cpu(mbx_out->ctx_id);
+ recv_ctx->state = le32_to_cpu(mbx_out->state);
+ recv_ctx->virt_port = le16_to_cpu(mbx_out->vport_id);
+ dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
+ recv_ctx->context_id, recv_ctx->state);
+ /* Receive descriptor ring */
+ /* Standard ring */
+ rds = &recv_ctx->rds_rings[0];
+ rds->crb_rcv_producer = ahw->pci_base0 +
+ le32_to_cpu(mbx_out->host_prod[0].reg_buf);
+ /* Jumbo ring */
+ rds = &recv_ctx->rds_rings[1];
+ rds->crb_rcv_producer = ahw->pci_base0 +
+ le32_to_cpu(mbx_out->host_prod[0].jmb_buf);
+ /* status descriptor ring */
+ for (i = 0; i < num_sds; i++) {
+ sds = &recv_ctx->sds_rings[i];
+ sds->crb_sts_consumer = ahw->pci_base0 +
+ le32_to_cpu(mbx_out->host_csmr[i]);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ intr_mask = ahw->intr_tbl[i].src;
+ else
+ intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+ sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
+ }
+out:
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx, int ring)
+{
+ int err;
+ u16 msix_id;
+ u32 *buf, intr_mask;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_tx_mbx mbx;
+ struct qlcnic_tx_mbx_out *mbx_out;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ /* Reset host resources */
+ tx->producer = 0;
+ tx->sw_consumer = 0;
+ *(tx->hw_consumer) = 0;
+
+ memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
+
+ /* setup mailbox inbox registerss */
+ mbx.phys_addr = cpu_to_le64(tx->phys_addr);
+ mbx.cnsmr_index = cpu_to_le64(tx->hw_cons_phys_addr);
+ mbx.size = cpu_to_le16(tx->num_desc);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
+ else
+ msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
+ if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
+ mbx.intr_id = cpu_to_le16(msix_id);
+ else
+ mbx.intr_id = 0xffff;
+ mbx.src = 0;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_TX_CTX);
+ cmd.req.arg[1] = cpu_to_le32(QLCNIC_CAP0_LEGACY_CONTEXT);
+ cmd.req.arg[5] = cpu_to_le32(QLCNIC_MAX_TX_QUEUES);
+ buf = &cmd.req.arg[6];
+ memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
+ /* send the mailbox command*/
+ err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create Tx ctx in firmware 0x%x\n", err);
+ goto out;
+ }
+ mbx_out = (struct qlcnic_tx_mbx_out *) &cmd.rsp.arg[2];
+ tx->crb_cmd_producer = ahw->pci_base0 + le32_to_cpu(mbx_out->host_prod);
+ tx->ctx_id = le16_to_cpu(mbx_out->ctx_id);
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
+ tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
+ }
+ dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
+ tx->ctx_id, mbx_out->state);
+out:
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int
+qlcnic_83xx_interrupt_test(struct qlcnic_adapter *adapter,
+ struct qlcnic_cmd_args *cmd)
+{
+ u8 val;
+ int ret;
+ u32 data;
+ u16 intrpt_id, id;
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ intrpt_id = adapter->ahw->intr_tbl[0].id;
+ else
+ intrpt_id = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_ID);
+
+ cmd->req.arg[1] = cpu_to_le32(1);
+ cmd->req.arg[2] = cpu_to_le32(intrpt_id);
+ cmd->req.arg[3] = cpu_to_le32(BIT_0);
+
+ ret = adapter->ahw->hw_ops->mbx_cmd(adapter, cmd);
+ data = le32_to_cpu(cmd->rsp.arg[2]);
+ id = LSW(data);
+ val = LSB(MSW(data));
+ if (id != intrpt_id)
+ dev_info(&adapter->pdev->dev,
+ "Interrupt generated: 0x%x, requested:0x%x\n",
+ id, intrpt_id);
+ if (val) {
+ dev_info(&adapter->pdev->dev,
+ "Interrupt test error: 0x%x\n", val);
+ }
+ return ret;
+}
+
+void qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 val, u32 beacon)
+{
+ struct qlcnic_cmd_args cmd;
+ u32 mbreg1 = 0, mbreg2 = 0, mbreg3 = 0, mbreg4 = 0, mbx_in;
+ int status;
+
+ /* Get LED configuration */
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_LED_CONFIG);
+ status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (status) {
+ dev_info(&adapter->pdev->dev, "Get led config failed.\n");
+ } else {
+ mbreg1 = cmd.rsp.arg[1];
+ mbreg2 = cmd.rsp.arg[2];
+ mbreg3 = cmd.rsp.arg[3];
+ mbreg4 = cmd.rsp.arg[4];
+ }
+ /* Set LED Configuration */
+ mbx_in = (LSW(QLCNIC_83XX_LED_CONFIG) << 16) |
+ LSW(QLCNIC_83XX_LED_CONFIG);
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_LED_CONFIG);
+ cmd.req.arg[1] = cpu_to_le32(mbx_in);
+ cmd.req.arg[2] = cpu_to_le32(mbx_in);
+ cmd.req.arg[3] = cpu_to_le32(mbx_in);
+ if (beacon)
+ cmd.req.arg[4] = QLCNIC_83XX_ENABLE_BEACON;
+ status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (status)
+ dev_info(&adapter->pdev->dev, "Set led config failed.\n");
+ qlcnic_free_mbx_args(&cmd);
+
+ msleep_interruptible(val * 1000);
+
+ /* Restoring default LED configuration */
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_LED_CONFIG);
+ cmd.req.arg[1] = mbreg1;
+ cmd.req.arg[2] = mbreg2;
+ cmd.req.arg[3] = mbreg3;
+ if (beacon)
+ cmd.req.arg[4] = mbreg4;
+ status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (status)
+ dev_info(&adapter->pdev->dev, "Restoring led config failed.\n");
+ qlcnic_free_mbx_args(&cmd);
+}
+
+void
+qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, int enable)
+{
+ struct qlcnic_cmd_args cmd;
+ int status;
+
+ if (enable) {
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_INIT_NIC_FUNC);
+ cmd.req.arg[1] = cpu_to_le32(1 | BIT_0);
+ } else {
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_STOP_NIC_FUNC);
+ cmd.req.arg[1] = cpu_to_le32(0 | BIT_0);
+ }
+ status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to %s in NIC IDC function event.\n",
+ (enable ? "register" : "unregistered"));
+ }
+ qlcnic_free_mbx_args(&cmd);
+}
+
+int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_cmd_args cmd;
+ int err;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_PORT_CONFIG);
+ cmd.req.arg[1] = cpu_to_le32(adapter->ahw->port_config);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_cmd_args cmd;
+ int err;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_PORT_CONFIG);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev, "Get Port config failed\n");
+ else
+ adapter->ahw->port_config = le32_to_cpu(cmd.rsp.arg[1]);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_LINK_EVENT);
+ cmd.req.arg[1] = cpu_to_le32((enable ? 1 : 0) | BIT_8 |
+ ((adapter->recv_ctx->context_id) << 16));
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "Setup linkevent mailbox failed\n");
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
+ return -EIO;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
+ cmd.req.arg[1] = cpu_to_le32((mode ? 1 : 0) |
+ (adapter->recv_ctx->context_id) << 16);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "Promiscous mode config failed\n");
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ int status = 0;
+ u32 config;
+
+ status = qlcnic_83xx_get_port_config(adapter);
+ if (status)
+ return status;
+
+ config = adapter->ahw->port_config;
+
+ if (mode == QLCNIC_ILB_MODE)
+ adapter->ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
+ if (mode == QLCNIC_ELB_MODE)
+ adapter->ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
+
+ status = qlcnic_83xx_set_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "Failed to Set Loopback Mode = 0x%x.\n",
+ adapter->ahw->port_config);
+ adapter->ahw->port_config = config;
+ }
+ adapter->ahw->hw_ops->change_macvlan(adapter, adapter->mac_addr,
+ 0, QLCNIC_MAC_ADD);
+ return status;
+}
+
+int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ int status = 0;
+ u32 config = adapter->ahw->port_config;
+
+ if (mode == QLCNIC_ILB_MODE)
+ adapter->ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
+ if (mode == QLCNIC_ELB_MODE)
+ adapter->ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
+
+ status = qlcnic_83xx_set_port_config(adapter);
+ if (status) {
+ dev_info(&adapter->pdev->dev,
+ "Failed to Clear Loopback Mode = 0x%x.\n",
+ adapter->ahw->port_config);
+ adapter->ahw->port_config = config;
+ }
+ adapter->ahw->hw_ops->change_macvlan(adapter, adapter->mac_addr,
+ 0, QLCNIC_MAC_DEL);
+ return status;
+}
+
+void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter,
+ __be32 ip, int mode)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_IP_ADDR);
+ if (mode == QLCNIC_IP_UP)
+ cmd.req.arg[1] = cpu_to_le32(1 |
+ adapter->recv_ctx->context_id << 16);
+ else
+ cmd.req.arg[1] = cpu_to_le32(2 |
+ adapter->recv_ctx->context_id << 16);
+ cmd.req.arg[2] = cpu_to_le32(ip);
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err != QLCNIC_RCODE_SUCCESS)
+ dev_err(&adapter->netdev->dev,
+ "could not notify %s IP 0x%x request\n",
+ (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
+ qlcnic_free_mbx_args(&cmd);
+}
+
+int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
+ return -EIO;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_HW_LRO);
+ cmd.req.arg[1] = cpu_to_le32((mode ? (BIT_0 | BIT_1 | BIT_3) : 0) |
+ ((adapter->recv_ctx->context_id) << 16));
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "LRO config failed\n");
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
+{
+ int err;
+ u32 word;
+ struct qlcnic_cmd_args cmd;
+
+
+ const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
+ 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
+ 0x255b0ec26d5a56daULL };
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_RSS);
+
+ /*
+ * RSS request:
+ * bits 3-0: Rsvd
+ * 5-4: hash_type_ipv4
+ * 7-6: hash_type_ipv6
+ * 8: enable
+ * 9: use indirection table
+ * 16-31: indirection table mask
+ */
+ word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
+ ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
+ ((u32)(enable & 0x1) << 8) |
+ ((0x7ULL) << 16);
+ cmd.req.arg[1] = (adapter->recv_ctx->context_id);
+ cmd.req.arg[2] = cpu_to_le32(word);
+ memcpy(&cmd.req.arg[4], key, sizeof(key));
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "RSS config failed\n");
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+
+}
+
+int
+qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
+ __le16 vlan_id, u8 op)
+{
+ int err;
+ u32 *buf;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_macvlan_mbx mv;
+
+ if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
+ return -EIO;
+
+ err = adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIG_MAC_VLAN);
+ if (err)
+ return err;
+ cmd.req.arg[1] = cpu_to_le32(op | (1 << 8) |
+ (adapter->recv_ctx->context_id << 16));
+
+ mv.vlan = cpu_to_le16(vlan_id);
+ memcpy(&mv.mac, addr, ETH_ALEN);
+ buf = &cmd.req.arg[2];
+ memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "MAC-VLAN add to CAM failed\n");
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
+ __le16 vlan_id)
+{
+ u8 mac[ETH_ALEN];
+ memcpy(&mac, addr, ETH_ALEN);
+ qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
+}
+
+void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
+ u8 type, struct qlcnic_cmd_args *cmd)
+{
+ switch (type) {
+ case QLCNIC_SET_STATION_MAC:
+ case QLCNIC_SET_FAC_DEF_MAC:
+ memcpy(&cmd->req.arg[2], mac, sizeof(u32));
+ memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
+ break;
+ }
+ cmd->req.arg[1] = cpu_to_le32(type);
+}
+
+/* Get MAC address of a NIC partition */
+int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
+{
+ int err, i;
+ struct qlcnic_cmd_args cmd;
+ u32 mac_low, mac_high;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_MAC_ADDRESS);
+ qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ mac_low = cmd.rsp.arg[1];
+ mac_high = cmd.rsp.arg[2];
+
+ for (i = 0; i < 2; i++)
+ mac[i] = (u8) (mac_high >> ((1 - i) * 8));
+ for (i = 2; i < 6; i++)
+ mac[i] = (u8) (mac_low >> ((5 - i) * 8));
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get mac address%d\n", err);
+ err = -EIO;
+ }
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
+
+ if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
+ return;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIG_INTR_COAL);
+ cmd.req.arg[1] = cpu_to_le32(1 | (adapter->recv_ctx->context_id << 16));
+ cmd.req.arg[3] = cpu_to_le32(coal->flag);
+ cmd.req.arg[2] = cpu_to_le32(coal->rx_packets |
+ (coal->rx_time_us << 16));
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err != QLCNIC_RCODE_SUCCESS)
+ dev_info(&adapter->pdev->dev,
+ "Can not send interrupt coalescence parameters\n");
+ qlcnic_free_mbx_args(&cmd);
+}
+
+static void
+qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, u32 data[])
+{
+ u8 link_status, duplex;
+ /* link speed */
+ link_status = LSB(data[3]) & 1;
+ adapter->ahw->link_speed = MSW(data[2]);
+ adapter->ahw->link_autoneg = MSB(MSW(data[3]));
+ adapter->ahw->module_type = MSB(LSW(data[3]));
+ duplex = LSB(MSW(data[3]));
+ if (duplex)
+ adapter->ahw->link_duplex = DUPLEX_FULL;
+ else
+ adapter->ahw->link_duplex = DUPLEX_HALF;
+ adapter->ahw->has_link_events = 1;
+ qlcnic_advert_link_change(adapter, link_status);
+}
+
+irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
+{
+ struct qlcnic_adapter *adapter = data;
+ qlcnic_83xx_process_aen(adapter);
+ return IRQ_HANDLED;
+}
+
+int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
+{
+ int err = -EIO;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Error, invoked by non management func\n",
+ __func__);
+ return err;
+ }
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_TOGGLE_ESWITCH);
+
+ cmd.req.arg[1] = (port & 0xf) | BIT_4;
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err != QLCNIC_RCODE_SUCCESS) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to enable eswitch%d\n", err);
+ err = -EIO;
+ }
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+
+}
+
+/* Configure a NIC partition */
+int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
+ struct qlcnic_info *nic)
+{
+ int i, err = -EIO;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Error, invoked by non management func\n",
+ __func__);
+ return err;
+ }
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_NIC_INFO);
+
+ cmd.req.arg[1] = (nic->pci_func << 16);
+ cmd.req.arg[2] = 0x1 << 16;
+ cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
+ cmd.req.arg[4] = nic->capabilities;
+ cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
+ cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
+ cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
+ for (i = 8; i < 32; i++)
+ cmd.req.arg[i] = 0;
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err != QLCNIC_RCODE_SUCCESS) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to set nic info%d\n", err);
+ err = -EIO;
+ }
+
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
+ struct qlcnic_info *npar_info, u8 func_id)
+{
+ int err;
+ u8 op = 0;
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd,
+ adapter, QLCNIC_CMD_GET_NIC_INFO);
+ if (func_id != adapter->ahw->pci_func) {
+ cmd.req.arg[1] = cpu_to_le32(op | BIT_31 |
+ (func_id << 16));
+ } else {
+ cmd.req.arg[1] = cpu_to_le32(adapter->ahw->pci_func << 16);
+ }
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_info(&adapter->pdev->dev,
+ "Failed to get nic info %d\n", err);
+ goto out;
+ }
+
+ npar_info->op_type = cmd.rsp.arg[1];
+ npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
+ npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
+ npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
+ npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
+ npar_info->capabilities = cmd.rsp.arg[4];
+ npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
+ npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
+ npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
+ npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
+ npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
+ npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
+ if (cmd.rsp.arg[8] & 0x1)
+ npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
+ if (cmd.rsp.arg[8] & 0x10000)
+ npar_info->max_linkspeed_reg_offset =
+ (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
+
+ dev_info(&adapter->pdev->dev,
+ "\n\top_type: %d, phy port: %d switch_mode: %d,\n"
+ "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x, max_tx_bw: %d,\n"
+ "\tmax_bw_offset: 0x%x max_link_speed_offset: 0x%x,\n"
+ "\tmax_mtu:0x%x, capabilities: 0x%x\n",
+ npar_info->op_type,
+ npar_info->phys_port, npar_info->switch_mode,
+ npar_info->max_tx_ques, npar_info->max_rx_ques,
+ npar_info->min_tx_bw, npar_info->max_tx_bw,
+ npar_info->max_bw_reg_offset,
+ npar_info->max_linkspeed_reg_offset,
+ npar_info->max_mtu, npar_info->capabilities);
+out:
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+/* Get PCI Info of a partition */
+int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
+ struct qlcnic_pci_info *pci_info)
+{
+ int i, err = 0, j = 0;
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_PCI_INFO);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ adapter->ahw->act_pci_func = 0;
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
+ dev_info(&adapter->pdev->dev,
+ "%s: total functions = %d\n",
+ __func__, pci_info->func_count);
+ for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
+ pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
+ pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
+ i++;
+ pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
+ if (pci_info->type == QLCNIC_TYPE_NIC)
+ adapter->ahw->act_pci_func++;
+ pci_info->default_port =
+ (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
+ i++;
+ pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
+ pci_info->tx_max_bw =
+ (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
+ i = i + 2;
+ memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
+ i++;
+ memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
+ i = i + 3;
+
+ dev_info(&adapter->pdev->dev, "%s:\n"
+ "\tid = %d active = %d type = %d\n"
+ "\tport = %d min bw = %d max bw = %d\n"
+ "\tmac_addr = %pM\n", __func__,
+ pci_info->id, pci_info->active, pci_info->type,
+ pci_info->default_port, pci_info->tx_min_bw,
+ pci_info->tx_max_bw, pci_info->mac);
+ }
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get PCI Info%d\n", err);
+ err = -EIO;
+ }
+
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+/* Configure interrupts command registers interrupt vectors with the FW
+ * @op_type: 1 for creation and 0 for deletion
+ * @type: Interrupt type, INTx or MSI-X
+ * */
+int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
+
+{
+ int i, index, err;
+ u8 max_ints;
+ u32 val;
+ struct qlcnic_cmd_args cmd;
+
+ max_ints = adapter->ahw->num_msix;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIG_INTRPT);
+ cmd.req.arg[1] = cpu_to_le32(max_ints);
+ for (i = 0, index = 2; i < max_ints; i++) {
+ val = (op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL) |
+ (adapter->ahw->intr_tbl[i].type << 4);
+ if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
+ val |= (adapter->ahw->intr_tbl[i].id << 16);
+ cmd.req.arg[index++] = cpu_to_le32(val);
+ }
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to configure interrupts 0x%x\n", err);
+ goto out;
+ }
+
+ max_ints = le32_to_cpu(cmd.rsp.arg[1]);
+ for (i = 0, index = 2; i < max_ints; i++, index += 2) {
+
+ val = le32_to_cpu(cmd.rsp.arg[index]);
+ if (LSB(val)) {
+ dev_info(&adapter->pdev->dev,
+ "Can't configure interrupt %d\n",
+ adapter->ahw->intr_tbl[i].id);
+ continue;
+ }
+ if (op_type) {
+ adapter->ahw->intr_tbl[i].id = MSW(val);
+ adapter->ahw->intr_tbl[i].enabled = 1;
+ adapter->ahw->intr_tbl[i].src =
+ le32_to_cpu(cmd.rsp.arg[index + 1]);
+ } else {
+ adapter->ahw->intr_tbl[i].id = i;
+ adapter->ahw->intr_tbl[i].enabled = 0;
+ adapter->ahw->intr_tbl[i].src = 0;
+ }
+ }
+out:
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int
+qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter)
+{
+ int id, timeout = 0;
+ u32 status = 0;
+
+ while (status == 0) {
+ status = QLCRD(adapter, QLCNIC_FLASH_LOCK);
+ if (status)
+ break;
+
+ if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) {
+ id = QLCRD(adapter, QLCNIC_FLASH_LOCK_OWNER);
+ dev_err(&adapter->pdev->dev,
+ "%s: failed: lock held by %d\n", __func__, id);
+ return -EIO;
+ }
+ usleep_range(1000, 2000);
+ }
+
+ QLCWR(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum);
+ return 0;
+}
+
+void
+qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
+{
+ QLCRD(adapter, QLCNIC_FLASH_UNLOCK);
+ QLCWR(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF);
+}
+
+int
+qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *adapter, u32 flash_addr,
+ u8 *p_data, int u32_word_count)
+{
+ int i, err;
+ u32 u32_word;
+ u32 addr = flash_addr;
+
+ if (qlcnic_83xx_lock_flash(adapter) != 0)
+ return -EIO;
+
+ if (addr & 0x3) {
+ dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
+ qlcnic_83xx_unlock_flash(adapter);
+ return -EIO;
+ }
+
+ for (i = 0; i < u32_word_count; i++) {
+ if (qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_WINDOW, (addr))) {
+ qlcnic_83xx_unlock_flash(adapter);
+ return -EIO;
+ }
+
+ u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
+ *(__le32 *)p_data = le32_to_cpu(u32_word);
+ p_data = p_data + 4;
+ addr = addr + 4;
+ }
+
+ qlcnic_83xx_unlock_flash(adapter);
+
+ return 0;
+}
+
+int
+qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *adapter,
+ u32 flash_addr, u8 *p_data, int u32_word_count)
+{
+ int err;
+ u32 i, u32_word, flash_offset;
+ u32 addr = flash_addr;
+
+ flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
+
+ if (addr & 0x3) {
+ dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
+ return -EIO;
+ }
+
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_WINDOW, (addr));
+
+ /* Check if data is spread across multiple sectors */
+ if ((flash_offset + (u32_word_count * sizeof(u32))) >
+ (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
+
+ /* Multi sector read */
+ for (i = 0; i < u32_word_count; i++) {
+ u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
+
+ *(__le32 *)p_data = le32_to_cpu(u32_word);
+ p_data = p_data + 4;
+ addr = addr + 4;
+ flash_offset = flash_offset + 4;
+
+ if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
+ /* This write is needed once for each sector */
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_WINDOW, (addr));
+ flash_offset = 0;
+ }
+ }
+ } else {
+ /* Single sector read */
+ for (i = 0; i < u32_word_count; i++) {
+ u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
+ *(__le32 *)p_data = cpu_to_le32(u32_word);
+ p_data = p_data + 4;
+ addr = addr + 4;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
new file mode 100644
index 0000000..6cd4877
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -0,0 +1,627 @@
+#ifndef __QLCNIC_83XX_HW_H
+#define __QLCNIC_83XX_HW_H
+
+#include <linux/types.h>
+#include <linux/etherdevice.h>
+#include "qlcnic_hw.h"
+
+#define IS_QLCNIC_83XX_USED(a, b, c) \
+ (((1 << a->portnum) & b) || ((c >> 6) & 0x1))
+
+/* Directly mapped registers */
+#define QLC_83XX_CRB_WIN_BASE 0x3800
+#define QLC_83XX_CRB_WIN_FUNC(f) (QLC_83XX_CRB_WIN_BASE+((f)*4))
+#define QLC_83XX_SEM_LOCK_BASE 0x3840
+#define QLC_83XX_SEM_UNLOCK_BASE 0x3844
+#define QLC_83XX_SEM_LOCK_FUNC(f) (QLC_83XX_SEM_LOCK_BASE+((f)*8))
+#define QLC_83XX_SEM_UNLOCK_FUNC(f) (QLC_83XX_SEM_UNLOCK_BASE+((f)*8))
+#define QLC_83XX_LINK_STATE(f) (0x3698+((f) > 7 ? 4 : 0))
+#define QLC_83XX_LINK_SPEED(f) (0x36E0+(((f) >> 2) * 4))
+#define QLC_83XX_LINK_SPEED_FACTOR 10
+#define QLC_83xx_FUNC_VAL(v, f) ((v) & (1 << (f * 4)))
+#define QLCNIC_83XX_INTX_PTR 0x38C0
+#define QLCNIC_83XX_INTX_TRGR 0x38C4
+#define QLCNIC_83XX_INTX_MASK 0x38C8
+
+/* Indirectly mapped registers */
+#define QLC_83XX_FLASH_SPI_STATUS 0x2808E010
+#define QLC_83XX_FLASH_SPI_CONTROL 0x2808E014
+#define QLC_83XX_FLASH_STATUS 0x42100004
+#define QLC_83XX_FLASH_CONTROL 0x42110004
+#define QLC_83XX_FLASH_ADDR 0x42110008
+#define QLC_83XX_FLASH_WRDATA 0x4211000C
+#define QLC_83XX_FLASH_RDDATA 0x42110018
+#define QLC_83XX_FLASH_DIRECT_WINDOW 0x42110030
+#define QLC_83XX_FLASH_DIRECT_DATA(DATA) (0x42150000 | (0x0000FFFF&DATA))
+
+#define QLC_83XX_FLASH_SECTOR_ERASE_CMD 0xdeadbeef
+#define QLC_83XX_FLASH_WRITE_CMD 0xdacdacda
+#define QLC_83XX_FLASH_BULK_WRITE_CMD 0xcadcadca
+#define QLC_83XX_FLASH_READ_RETRY_COUNT 5000
+#define QLC_83XX_FLASH_STATUS_READY 0x6
+#define QLC_83XX_FLASH_BULK_WRITE_MIN 2
+#define QLC_83XX_FLASH_BULK_WRITE_MAX 64
+#define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY 1
+#define QLC_83XX_ERASE_MODE 1
+#define QLC_83XX_WRITE_MODE 2
+#define QLC_83XX_BULK_WRITE_MODE 3
+
+/* Flash Operations Misc Signatures*/
+#define QLC_83XX_FLASH_FDT_WRITE_DEF_SIG 0xFD0100
+#define QLC_83XX_FLASH_FDT_ERASE_DEF_SIG 0xFD0300
+#define QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL 0xFD009F
+
+#define QLC_83XX_FLASH_OEM_ERASE_SIG 0xFD03D8
+#define QLC_83XX_FLASH_OEM_WRITE_SIG 0xFD0101
+#define QLC_83XX_FLASH_OEM_READ_SIG 0xFD0005
+
+#define QLC_83XX_FLASH_ADDR_TEMP_VAL 0x00800000
+#define QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL 0x00800001
+
+#define QLC_83XX_FLASH_WRDATA_DEF_VAL 0x0
+#define QLC_83XX_FLASH_READ_CONTROL_VAL 0x3F
+#define QLC_83XX_FLASH_SPI_CONTROL_VAL 0x4
+
+#define QLC_83XX_FLASH_FIRST_ERASE_MS_VAL 0x2
+#define QLC_83XX_FLASH_SECOND_ERASE_MS_VAL 0x5
+#define QLC_83XX_FLASH_LAST_ERASE_MS_VAL 0x3D
+
+#define QLC_83XX_FLASH_FIRST_WRITE_MS_PATTERN 0x43
+#define QLC_83XX_FLASH_SECOND_WRITE_MS_PATTERN 0x7F
+#define QLC_83XX_FLASH_LAST_WRITE_MS_PATTERN 0x7D
+
+#define QLC_83xx_FLASH_MAX_WAIT_USEC 100
+#define QLC_83XX_FLASH_LOCK_TIMEOUT 10000
+#define QLC_83XX_DRV_LOCK_WAIT_COUNTER 100
+#define QLC_83XX_DRV_LOCK_WAIT_DELAY 20
+#define QLC_83XX_NEED_DRV_LOCK_RECOVERY 1
+#define QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS 2
+#define QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT 3
+#define QLC_83XX_DRV_LOCK_RECOVERY_DELAY 200
+#define QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK 0x3
+
+#define QLC_83XX_FLASH_SECTOR_SIZE (64 * 1024)
+
+
+/* PEG status definitions */
+#define QLC_83xx_CMDPEG_COMPLETE 0xff01
+
+/* Firmware image definitions */
+#define QLC_83XX_BOOTLOADER_FLASH_ADDR 0x10000
+#define QLC_83XX_FW_FILE_NAME "83xx_fw.bin"
+
+#define QLC_83XX_BOOT_FROM_FLASH 0
+#define QLC_83XX_BOOT_FROM_FILE 0x12345678
+
+/* Reset template definitions */
+#define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16
+#define QLC_83XX_RESTART_TEMPLATE_SIZE 0x2000
+#define QLC_83XX_RESET_TEMPLATE_ADDR 0x4F0000
+#define QLC_83XX_RESET_SEQ_VERSION 0x0101
+
+#define OPCODE_NOP 0x0000
+#define OPCODE_WRITE_LIST 0x0001
+#define OPCODE_READ_WRITE_LIST 0x0002
+#define OPCODE_POLL_LIST 0x0004
+#define OPCODE_POLL_WRITE_LIST 0x0008
+#define OPCODE_READ_MODIFY_WRITE 0x0010
+#define OPCODE_SEQ_PAUSE 0x0020
+#define OPCODE_SEQ_END 0x0040
+#define OPCODE_TMPL_END 0x0080
+#define OPCODE_POLL_READ_LIST 0x0100
+
+#define qlcnic_83xx_pktln(sts) \
+ ((sts >> 32) & 0x3FFF)
+#define qlcnic_83xx_hndl(sts) \
+ ((sts >> 48) & 0x7FFF)
+#define qlcnic_83xx_csum_status(sts) \
+ ((sts >> 39) & 7)
+#define qlcnic_83xx_opcode(sts) \
+ ((sts >> 42) & 0xF)
+#define qlcnic_83xx_vlan_tag(sts) \
+ (((sts) >> 48) & 0xFFFF)
+#define qlcnic_83xx_lro_pktln(sts) \
+ (((sts) >> 32) & 0x3FFF)
+#define qlcnic_83xx_l2_hdr_off(sts) \
+ (((sts) >> 16) & 0xFF)
+#define qlcnic_83xx_l4_hdr_off(sts) \
+ (((sts) >> 24) & 0xFF)
+#define qlcnic_83xx_pkt_cnt(sts) \
+ (((sts) >> 16) & 0x7)
+
+#define qlcnic_83xx_is_tstamp(sts) \
+ (((sts) >> 40) & 1)
+#define qlcnic_83xx_is_psh_bit(sts) \
+ (((sts) >> 41) & 1)
+#define qlcnic_83xx_is_ip_align(sts) \
+ (((sts) >> 46) & 1)
+#define qlcnic_83xx_has_vlan_tag(sts) \
+ (((sts) >> 47) & 1)
+
+#define QLCNIC_83XX_VALID_INTX_BIT30(val) \
+ ((val) & BIT_30)
+
+#define QLCNIC_83XX_VALID_INTX_BIT31(val) \
+ ((val) & BIT_31)
+#define QLCNIC_83XX_INTX_FUNC(val) \
+ ((val) & 0xFF)
+
+#define QLC_83XX_LEGACY_INTX_MAX_RETRY 100
+#define QLC_83XX_LEGACY_INTX_DELAY 4
+
+#define QLCNIC_83XX_REG_DESC 1
+#define QLCNIC_83XX_LRO_DESC 2
+#define QLCNIC_83XX_CTRL_DESC 3
+
+#define QLCNIC_FW_83XX_CAPABILITY_TSO BIT_6
+
+#define QLCNIC_HOST_83XX_RDS_MODE_UNIQUE 0
+#define QLCNIC_HOST_SDS_MBX_IDX 8
+/* status descriptor mailbox data
+ * @phy_addr: physical address of buffer
+ * @sds_ring_size: buffer size
+ * @intrpt_id: interrupt id
+ * @intrpt_val: source of interrupt
+ */
+struct qlcnic_sds_mbx {
+ __le64 phy_addr;
+ u8 rsvd1[16];
+ __le16 sds_ring_size;
+ __le16 rsvd2[3];
+ __le16 intrpt_id;
+ u8 intrpt_val;
+ u8 rsvd3[5];
+} __packed;
+
+#define QLCNIC_HOST_RDS_MBX_IDX 88
+/* receive descriptor buffer data
+ * phy_addr_reg: physical address of regular buffer
+ * phy_addr_jmb: physical address of jumbo buffer
+ * reg_ring_sz: size of regular buffer
+ * reg_ring_len: no. of entries in regular buffer
+ * jmb_ring_len: no. of entries in jumbo buffer
+ * jmb_ring_sz: size of jumbo buffer
+ */
+struct qlcnic_rds_mbx {
+ __le64 phy_addr_reg;
+ __le64 phy_addr_jmb;
+ __le16 reg_ring_sz;
+ __le16 reg_ring_len;
+ __le16 jmb_ring_sz;
+ __le16 jmb_ring_len;
+} __packed;
+
+/* host producers for regular and jumbo rings */
+struct __host_producer_mbx {
+ __le32 reg_buf;
+ __le32 jmb_buf;
+} __packed;
+
+#define QLCNIC_MAX_RING_SETS 8
+/* Receive context mailbox data outbox registers
+ * @state: state of the context
+ * @vport_id: virtual port id
+ * @context_id: receive context id
+ * @num_pci_func: number of pci functions of the port
+ * @phy_port: physical port id
+ */
+struct qlcnic_rcv_mbx_out {
+ u8 rcv_num;
+ u8 sts_num;
+ __le16 ctx_id;
+ u8 state;
+ u8 num_pci_func;
+ u8 phy_port;
+ u8 vport_id;
+ __le32 host_csmr[QLCNIC_MAX_RING_SETS];
+ struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
+} __packed;
+
+/* Transmit context mailbox inbox registers
+ * @phys_addr: DMA address of the transmit buffer
+ * @cnsmr_index: host consumer index
+ * @size: legth of transmit buffer ring
+ * @intr_id: interrput id
+ * @src: src of interrupt
+ */
+struct qlcnic_tx_mbx {
+ __le64 phys_addr;
+ __le64 cnsmr_index;
+ __le16 size;
+ __le16 intr_id;
+ u8 src;
+ u8 rsvd[3];
+} __packed;
+
+/* Transmit context mailbox outbox registers
+ * @host_prod: host producer index
+ * @ctx_id: transmit context id
+ * @state: state of the transmit context
+ */
+struct qlcnic_tx_mbx_out {
+ __le32 host_prod;
+ __le16 ctx_id;
+ u8 state;
+ u8 rsvd;
+} __packed;
+
+struct qlcnic_intrpt_config {
+ u8 type;
+ u8 enabled;
+ u16 id;
+ u32 src;
+};
+
+struct qlcnic_macvlan_mbx {
+ u8 mac[ETH_ALEN];
+ __le16 vlan;
+};
+
+struct qlcnic_83xx_fw_info {
+ u16 major_fw_version;
+ u8 minor_fw_version;
+ u8 sub_fw_version;
+ u8 fw_build_num;
+ u8 load_from_file;
+ const struct firmware *fw;
+};
+
+/* Template Header */
+struct qlcnic_83xx_reset_template_hdr {
+ __le16 version;
+ __le16 signature;
+ __le16 size;
+ __le16 entries;
+ __le16 hdr_size;
+ __le16 checksum;
+ __le16 init_seq_offset;
+ __le16 start_seq_offset;
+} __packed;
+
+/* Common Entry Header. */
+struct qlcnic_83xx_reset_entry_hdr {
+ __le16 cmd;
+ __le16 size;
+ __le16 count;
+ __le16 delay;
+} __packed;
+
+/* Generic poll entry type. */
+struct qlcnic_83xx_poll {
+ __le32 test_mask;
+ __le32 test_value;
+} __packed;
+
+/* Read modify write entry type. */
+struct qlcnic_83xx_rmw {
+ __le32 test_mask;
+ __le32 xor_value;
+ __le32 or_value;
+ u8 shl;
+ u8 shr;
+ u8 index_a;
+ u8 rsvd;
+} __packed;
+
+/* Generic Entry Item with 2 DWords. */
+struct qlcnic_83xx_entry {
+ __le32 arg1;
+ __le32 arg2;
+} __packed;
+
+/* Generic Entry Item with 4 DWords.*/
+struct qlcnic_83xx_quad_entry {
+ __le32 dr_addr;
+ __le32 dr_value;
+ __le32 ar_addr;
+ __le32 ar_value;
+} __packed;
+
+struct qlcnic_83xx_reset {
+ int seq_index;
+ int seq_error ;
+ int array_index;
+ u32 array[QLC_83XX_MAX_RESET_SEQ_ENTRIES];
+ u8 *buff;
+ u8 *stop_offset;
+ u8 *start_offset;
+ u8 *init_offset;
+ struct qlcnic_83xx_reset_template_hdr *hdr;
+ u8 seq_end;
+ u8 template_end;
+};
+
+#define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1
+#define QLC_83XX_IDC_GRACEFULL_RESET 0x2
+#define QLC_83XX_IDC_TIMESTAMP 0
+#define QLC_83XX_IDC_DURATION 1
+#define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30
+#define QLC_83XX_IDC_RESET_ACK_TIMEOUT_SECS 10
+#define QLC_83XX_IDC_RESET_TIMEOUT_SECS 10
+#define QLC_83XX_IDC_QUIESCE_ACK_TIMEOUT_SECS 20
+#define QLC_83XX_IDC_FW_POLL_DELAY (1 * HZ)
+#define QLC_83XX_IDC_FW_FAIL_THRESH 2
+#define QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO 8
+#define QLC_83XX_IDC_MAX_CNA_FUNCTIONS 16
+#define QLC_83XX_IDC_MAJOR_VERSION 1
+#define QLC_83XX_IDC_MINOR_VERSION 0
+#define QLC_83XX_IDC_FLASH_PARAM_ADDR 0x3e8020
+
+/* Mailbox process AEN count */
+#define QLC_83XX_MBX_AEN_CNT 5
+
+struct qlcnic_adapter;
+struct qlcnic_83xx_idc {
+ u64 sec_counter;
+ u64 delay;
+ unsigned long status;
+ int err_code;
+ int collect_dump;
+ u8 curr_state;
+ u8 prev_state;
+ u8 vnic_state;
+ u8 vnic_wait_limit;
+ u8 quiesce_req;
+ int (*ready_state_entry_action) (struct qlcnic_adapter *);
+ char **name;
+};
+
+#define QLC_83XX_MODULE_LOADED 1
+#define QLC_83XX_MBX_READY 2
+#define QLC_83XX_MBX_AEN_ACK 3
+
+#define QLC_83XX_SFP_PRESENT(data) ((data) & 3)
+#define QLC_83XX_SFP_ERR(data) (((data) >> 2) & 3)
+#define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F)
+#define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16))
+#define QLC_83XX_SFP_TX_FAULT(data) ((data) & BIT_10)
+#define QLC_83XX_SFP_10G_CAPABLE(data) ((data) & BIT_11)
+#define QLC_83XX_LINK_STATS(data) ((data) & BIT_0)
+#define QLC_83XX_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7)
+#define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3)
+#define QLC_83XX_LINK_LB(data) (((data) >> 8) & 7)
+#define QLC_83XX_LINK_FEC(data) ((data) & BIT_12)
+#define QLC_83XX_LINK_EEE(data) ((data) & BIT_13)
+#define QLC_83XX_DCBX(data) (((data) >> 28) & 7)
+#define QLC_83XX_AUTONEG(data) ((data) & BIT_15)
+#define QLC_83XX_CFG_PAUSE_STD (1 << 5) /* Standard Pause Configuration */
+#define QLC_83XX_CFG_LOOPBACK_HSS (2 << 1) /* HSS Internal Loopback Mode */
+#define QLC_83XX_CFG_LOOPBACK_PHY (3 << 1) /* PHY Internal Loopback Mode */
+#define QLC_83XX_CFG_LOOPBACK_EXT (4 << 1) /* External Loopback Mode */
+
+/* LED configuration settings */
+#define QLCNIC_83XX_ENABLE_BEACON 0xe
+#define QLCNIC_83XX_LED_RATE 0xff
+#define QLCNIC_83XX_LED_ACT (1 << 10)
+#define QLCNIC_83XX_LED_MOD (0 << 13)
+#define QLCNIC_83XX_LED_CONFIG (QLCNIC_83XX_LED_RATE | QLCNIC_83XX_LED_ACT |\
+ QLCNIC_83XX_LED_MOD)
+
+#define QLC_83XX_10M_LINK 1
+#define QLC_83XX_100M_LINK 2
+#define QLC_83XX_1G_LINK 3
+#define QLC_83XX_10G_LINK 4
+
+#define QLCNIC_83XX_STAT_TX 3
+#define QLCNIC_83XX_STAT_RX 2
+
+#define QLCNIC_83XX_STAT_MAC 1
+
+#define QLCNIC_83XX_TX_STAT_REGS 14
+#define QLCNIC_83XX_RX_STAT_REGS 40
+#define QLCNIC_83XX_MAC_STAT_REGS 80
+
+#define QLC_83XX_GET_FUNC_PRIVILEGE_LEVEL(VAL, FN) (0x3 & ((VAL) >> (FN * 2)))
+#define QLC_83XX_SET_FUNC_OPMODE(VAL, FN) ((VAL) << (FN * 2))
+#define QLC_83XX_DEFAULT_OPMODE 0x55555555
+#define QLC_83XX_PRIVLEGED_FUNC 0x1
+#define QLC_83XX_VIRTUAL_FUNC 0x2
+
+#define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000)
+#define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20)
+#define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40)
+#define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40)
+#define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400)
+#define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000)
+
+#define QLC_83XX_VIRTUAL_NIC_MODE 0xFF
+#define QLC_83XX_DEFAULT_MODE 0x0
+
+
+/* Additional registers in 83xx */
+enum qlcnic_83xx_ext_regs {
+ QLCNIC_GLOBAL_RESET = 0,
+ QLCNIC_WILDCARD,
+ QLCNIC_INFORMANT,
+ QLCNIC_HOST_MBX_CTRL,
+ QLCNIC_FW_MBX_CTRL,
+ QLCNIC_BOOTLOADER_ADDR,
+ QLCNIC_BOOTLOADER_SIZE,
+ QLCNIC_FW_IMAGE_ADDR,
+ QLCNIC_MBX_INTR_ENBL,
+ QLCNIC_DEF_INT_MASK,
+ QLCNIC_DEF_INT_ID,
+ QLC_83XX_IDC_MAJ_VERSION,
+ QLC_83XX_IDC_DEV_STATE,
+ QLC_83XX_IDC_DRV_PRESENCE,
+ QLC_83XX_IDC_DRV_ACK,
+ QLC_83XX_IDC_CTRL,
+ QLC_83XX_IDC_DRV_AUDIT,
+ QLC_83XX_IDC_MIN_VERSION,
+ QLC_83XX_RECOVER_DRV_LOCK,
+ QLC_83XX_IDC_PF_0,
+ QLC_83XX_IDC_PF_1,
+ QLC_83XX_IDC_PF_2,
+ QLC_83XX_IDC_PF_3,
+ QLC_83XX_IDC_PF_4,
+ QLC_83XX_IDC_PF_5,
+ QLC_83XX_IDC_PF_6,
+ QLC_83XX_IDC_PF_7,
+ QLC_83XX_IDC_PF_8,
+ QLC_83XX_IDC_PF_9,
+ QLC_83XX_IDC_PF_10,
+ QLC_83XX_IDC_PF_11,
+ QLC_83XX_IDC_PF_12,
+ QLC_83XX_IDC_PF_13,
+ QLC_83XX_IDC_PF_14,
+ QLC_83XX_IDC_PF_15,
+ QLC_83XX_IDC_DEV_PARTITION_INFO_1,
+ QLC_83XX_IDC_DEV_PARTITION_INFO_2,
+ QLC_83XX_DRV_OP_MODE,
+ QLC_83XX_VNIC_STATE,
+ QLC_83XX_DRV_LOCK,
+ QLC_83XX_DRV_UNLOCK,
+ QLC_83XX_DRV_LOCK_ID,
+ QLC_83XX_ASIC_TEMP,
+};
+
+struct qlcnic_pci_info;
+struct qlcnic_info;
+struct qlcnic_cmd_args;
+struct ethtool_stats;
+struct pci_device_id;
+struct qlcnic_host_sds_ring;
+struct qlcnic_host_tx_ring;
+struct qlcnic_host_tx_ring;
+struct qlcnic_hardware_context;
+
+/* 83xx funcitons */
+int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
+void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
+int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
+int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8);
+void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
+int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
+void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *);
+int qlcnic_83xx_lock_driver(struct qlcnic_adapter *);
+void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *);
+int qlcnic_send_ctrl_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *, u32);
+void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *);
+void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *);
+void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
+u32 qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong, int *);
+int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
+void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *,
+ struct qlcnic_host_sds_ring *, int, u64 []);
+int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
+int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8);
+int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8);
+int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
+int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int);
+int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *);
+void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, __le16);
+int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *);
+
+
+int qlcnic_83xx_init(struct qlcnic_adapter *);
+void qlcnic_83xx_idc_exit(struct qlcnic_adapter *);
+void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *, u32);
+int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
+int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
+int qlcnic_83xx_idc_vnic_pf_ready_state_entry_action(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_ready_state_entry_action(struct qlcnic_adapter *);
+int qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *, int);
+int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *, int);
+int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *);
+int qlcnic_83xx_set_default_offload_settings(struct qlcnic_adapter *);
+int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *,
+ struct qlcnic_info *, u8);
+int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
+void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int);
+void qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
+
+/* 83xx MS memory access API's */
+int qlcnic_83xx_ms_mem_write_128b(struct qlcnic_adapter *, u64, u32 *, u32);
+void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
+u32 qlcnic_ind_rd(struct qlcnic_adapter *, u32);
+
+/* 83xx flash operations */
+int qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *, u32, u8 *, int);
+int qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *,
+ u32, u8 *, int);
+int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *, u32);
+int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *, u32, u32 *, int);
+int qlcnic_83xx_flash_write_u32(struct qlcnic_adapter *, u32, u32 *);
+int qlcnic_83xx_lock_flash(struct qlcnic_adapter *);
+void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *);
+void qlcnic_83xx_get_stats(struct qlcnic_adapter *,
+ struct ethtool_stats *, u64 *);
+
+/* IDC user API */
+
+/* 83xx reset template operations */
+int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);
+void qlcnic_83xx_free_reset_template(struct qlcnic_adapter *);
+int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
+int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *, int);
+int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
+int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int);
+void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *);
+int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *);
+int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *, bool);
+int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8);
+int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *, u8 *);
+void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8,
+ struct qlcnic_cmd_args *);
+int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *,
+ struct qlcnic_adapter *, u32);
+void qlcnic_free_mbx_args(struct qlcnic_cmd_args *);
+void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
+ struct qlcnic_info *);
+void qlcnic_83xx_napi_enable(struct qlcnic_adapter *);
+void qlcnic_83xx_napi_disable(struct qlcnic_adapter *);
+void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
+irqreturn_t qlcnic_83xx_handle_aen(int, void *);
+int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
+int qlcnic_83xx_get_settings(struct qlcnic_adapter *);
+int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
+void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
+ struct ethtool_pauseparam *);
+int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,
+ struct ethtool_pauseparam *);
+void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *);
+int qlcnic_83xx_test_link(struct qlcnic_adapter *);
+int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
+int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
+int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
+int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
+irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
+irqreturn_t qlcnic_83xx_tmp_intr(int, void *);
+void qlcnic_83xx_enable_intr(struct qlcnic_adapter *,
+ struct qlcnic_host_sds_ring *);
+void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *);
+void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *,
+ struct qlcnic_host_tx_ring *);
+void qlcnic_83xx_check_vf(struct qlcnic_adapter *,
+ const struct pci_device_id *);
+void qlcnic_83xx_process_aen(struct qlcnic_adapter *);
+int qlcnic_83xx_get_port_config(struct qlcnic_adapter *);
+int qlcnic_83xx_set_port_config(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter);
+void qlcnic_83xx_idc_poll_dev_state(struct work_struct *);
+int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
+int qlcnic_enable_eswitch(struct qlcnic_adapter *, u8, u8);
+int qlcnic_83xx_restart_hw(struct qlcnic_adapter *);
+int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *);
+int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *);
+int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *);
+int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *);
+int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *,
+ struct qlcnic_cmd_args *);
+
+int qlcnic_83xx_save_flash_status(struct qlcnic_adapter *);
+int qlcnic_83xx_restore_flash_status(struct qlcnic_adapter *, int);
+int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *);
+void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *);
+
+int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *);
+int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *);
+void qlcnic_83xx_register_map(struct qlcnic_hardware_context *);
+
+void qlcnic_83xx_idc_aen_work(struct work_struct *);
+void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int);
+void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
+#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index fb7a0b7..2d08234 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -952,9 +952,8 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off)
writel(window, addr);
if (readl(addr) != window) {
- if (printk_ratelimit())
- dev_warn(&adapter->pdev->dev,
- "failed to set CRB window to %d off 0x%lx\n",
+ printk_ratelimited(KERN_WARNING
+ "failed to set CRB window to %d off 0x%lx\n",
window, off);
return -EIO;
}
@@ -1189,12 +1188,12 @@ qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
}
if (j >= MAX_CTL_CHECK) {
- if (printk_ratelimit())
- dev_err(&adapter->pdev->dev,
- "failed to write through agent\n");
+ printk_ratelimited(KERN_WARNING
+ "failed to write through agent\n");
ret = -EIO;
- } else
+ } else {
ret = 0;
+ }
done:
mutex_unlock(&adapter->ahw->mem_lock);
@@ -1244,9 +1243,8 @@ qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
}
if (j >= MAX_CTL_CHECK) {
- if (printk_ratelimit())
- dev_err(&adapter->pdev->dev,
- "failed to read through agent\n");
+ printk_ratelimited(KERN_WARNING
+ "failed to read through agent\n");
ret = -EIO;
} else {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 829dfa5..fa7f3e5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2541,7 +2541,6 @@ skip_ack_check:
ahw->hw_ops->api_unlock(adapter);
-
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 09/15] qlcnic: 83xx adpater flash interface routines
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Flash interface routines for 83xx adapter
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 31 ++
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 344 ++++++++++++++++++--
2 files changed, 345 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 9e46670..f95477e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -315,6 +315,36 @@ struct qlcnic_flt_entry {
u32 end_addr;
};
+struct qlcnic_flash_desc_table {
+ u32 flash_valid;
+ u16 flash_ver;
+ u16 flash_len;
+ u16 flash_cksum;
+ u16 flash_unused;
+ u8 flash_model[16];
+ u16 flash_manuf;
+ u16 flash_id;
+ u8 flash_flag;
+ u8 erase_cmd;
+ u8 alt_erase_cmd;
+ u8 write_enable_cmd;
+ u8 write_enable_bits;
+ u8 write_statusreg_cmd;
+ u8 unprotected_sec_cmd;
+ u8 read_manuf_cmd;
+ u32 block_size;
+ u32 alt_block_size;
+ u32 flash_size;
+ u32 write_enable_data;
+ u8 readid_addr_len;
+ u8 write_disable_bits;
+ u8 read_dev_id_len;
+ u8 chip_erase_cmd;
+ u16 read_timeo;
+ u8 protected_sec_cmd;
+ u8 resvd[65];
+};
+
/* Magic number to let user know flash is programmed */
#define QLCNIC_BDINFO_MAGIC 0x12345678
@@ -505,6 +535,7 @@ struct qlcnic_hardware_context {
struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
+ struct qlcnic_flash_desc_table flash_fdt;
struct qlcnic_83xx_reset reset;
struct qlcnic_83xx_idc idc;
struct qlcnic_83xx_fw_info fw_info;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 4edbdd2..c430723 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -4,9 +4,6 @@
#include <linux/ethtool.h>
#include <linux/interrupt.h>
-/* Array of FW control command structs with command type and required
- * number of input and output arguments respectively.
-*/
static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{ QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1 },
{ QLCNIC_CMD_CONFIG_INTRPT, 18, 34 },
@@ -209,7 +206,6 @@ qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
return adapter->fw_version;
}
-/* Caller needs to use locking before accessing this function */
static int
__qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
{
@@ -1229,9 +1225,6 @@ qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
return data;
}
-/*
- * Get statistics of MAC and that of Context/Function/Vport
- */
void
qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter,
struct ethtool_stats *stats, u64 *data)
@@ -1539,7 +1532,6 @@ qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
dev_info(&adapter->pdev->dev,
"Mailbox not available, 0x%x, collect FW dump\n",
mbx_val);
- /* Take FW dump */
spin_unlock_irqrestore(&ahw->mbx_lock, flags);
return cmd->rsp.arg[0];
@@ -1606,9 +1598,6 @@ poll:
return rsp;
}
-/* Allocate mailbox incoming and outgoing registers. It should be used with a
- * follow up call to qlcnic_free_mbx_args
- */
int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
struct qlcnic_adapter *adapter, u32 type)
{
@@ -1685,36 +1674,24 @@ void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
event[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, i)));
switch (QLCNIC_MBX_RSP(event[0])) {
-
- /* This case is only active when we arrive here
- * as a result of issuing a mailbox command to
- * the firmware.
- */
case QLCNIC_MBX_LINK_EVENT:
- /* Link Event */
qlcnic_83xx_handle_link_aen(adapter, event);
break;
case QLCNIC_MBX_COMP_EVENT:
- /* IDC Completion Notification */
qlcnic_83xx_handle_idc_comp_aen(adapter, event);
break;
case QLCNIC_MBX_REQUEST_EVENT:
- /* IDC Request Notification */
for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
- /* IDC ack wiil be done by worker thread, just set the flag */
set_bit(QLC_83XX_MBX_AEN_ACK, &adapter->ahw->idc.status);
break;
case QLCNIC_MBX_TIME_EXTEND_EVENT:
- /* IDC Time Extend Notification */
break;
case QLCNIC_MBX_SFP_INSERT_EVENT:
- /* IDC SFP+ Transceiver Insertion Notification */
dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
QLCNIC_MBX_RSP(event[0]));
break;
case QLCNIC_MBX_SFP_REMOVE_EVENT:
- /* IDC SFP+ Transceiver Removal Notification */
dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
QLCNIC_MBX_RSP(event[0]));
break;
@@ -2257,7 +2234,6 @@ void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
cmd->req.arg[1] = cpu_to_le32(type);
}
-/* Get MAC address of a NIC partition */
int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
{
int err, i;
@@ -2363,7 +2339,6 @@ int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
}
-/* Configure a NIC partition */
int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *nic)
{
@@ -2460,7 +2435,6 @@ out:
return err;
}
-/* Get PCI Info of a partition */
int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *pci_info)
{
@@ -2515,10 +2489,6 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
return err;
}
-/* Configure interrupts command registers interrupt vectors with the FW
- * @op_type: 1 for creation and 0 for deletion
- * @type: Interrupt type, INTx or MSI-X
- * */
int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
{
@@ -2690,3 +2660,317 @@ qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *adapter,
return 0;
}
+
+static int
+qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
+{
+ u32 status;
+ int err, retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
+
+ do {
+ status = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_STATUS, &err);
+ if ((status & QLC_83XX_FLASH_STATUS_READY) ==
+ QLC_83XX_FLASH_STATUS_READY)
+ break;
+
+ msleep(QLC_83XX_FLASH_STATUS_REG_POLL_DELAY);
+ } while (--retries);
+
+ if (!retries)
+ return -EIO;
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
+{
+ int ret;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
+ adapter->ahw->flash_fdt.write_statusreg_cmd));
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
+ adapter->ahw->flash_fdt.write_enable_bits);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
+
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter)
+{
+ int ret;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
+ adapter->ahw->flash_fdt.write_statusreg_cmd));
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
+ adapter->ahw->flash_fdt.write_enable_bits);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
+
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+int
+qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
+{
+ int ret, mfg_id;
+
+ if (qlcnic_83xx_lock_flash(adapter))
+ return -EIO;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_READ_CONTROL_VAL);
+
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ qlcnic_83xx_unlock_flash(adapter);
+ return -EIO;
+ }
+
+ mfg_id = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_RDDATA, &ret);
+
+ adapter->flash_mfg_id = (mfg_id & 0xFF);
+ qlcnic_83xx_unlock_flash(adapter);
+
+ return 0;
+}
+
+int
+qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
+{
+ int count, fdt_size, ret = 0;
+
+ fdt_size = sizeof(struct qlcnic_flash_desc_table);
+ count = fdt_size/sizeof(u32);
+
+ if (qlcnic_83xx_lock_flash(adapter))
+ return -EIO;
+
+ memset(&adapter->ahw->flash_fdt, 0, fdt_size);
+ ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ QLCNIC_FDT_LOCATION,
+ (u8 *)&adapter->ahw->flash_fdt,
+ count);
+
+ qlcnic_83xx_unlock_flash(adapter);
+ return ret;
+}
+
+int
+qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
+ u32 sector_start_addr)
+{
+ u32 reversed_addr;
+ int ret = -EIO;
+
+ if (qlcnic_83xx_lock_flash(adapter) != 0)
+ return -EIO;
+
+ if (adapter->ahw->flash_fdt.flash_manuf == adapter->flash_mfg_id) {
+ ret = qlcnic_83xx_enable_flash_write_op(adapter);
+ if (ret) {
+ qlcnic_83xx_unlock_flash(adapter);
+ dev_err(&adapter->pdev->dev,
+ "%s failed at %d\n",
+ __func__, __LINE__);
+ return ret;
+ }
+ }
+
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ qlcnic_83xx_unlock_flash(adapter);
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ reversed_addr = (((sector_start_addr & 0xFF) << 16) |
+ ((sector_start_addr & 0xFF0000) >> 16));
+
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_WRDATA, reversed_addr);
+
+ if (adapter->ahw->flash_fdt.flash_manuf == adapter->flash_mfg_id)
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ (QLC_83XX_FLASH_FDT_ERASE_DEF_SIG |
+ adapter->ahw->flash_fdt.erase_cmd));
+ else
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_OEM_ERASE_SIG);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
+
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ qlcnic_83xx_unlock_flash(adapter);
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ if (adapter->ahw->flash_fdt.flash_manuf == adapter->flash_mfg_id) {
+ ret = qlcnic_83xx_disable_flash_write_op(adapter);
+ if (ret) {
+ qlcnic_83xx_unlock_flash(adapter);
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return ret;
+ }
+ }
+
+ qlcnic_83xx_unlock_flash(adapter);
+
+ return 0;
+}
+
+int
+qlcnic_83xx_flash_write_u32(struct qlcnic_adapter *adapter, u32 addr,
+ u32 *p_data)
+{
+ int ret = -EIO;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ 0x00800000 | (addr >> 2));
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
+ u32 *p_data, int u32_word_count)
+{
+ u32 temp;
+ int ret = -EIO, err;
+
+ if ((u32_word_count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
+ (u32_word_count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
+ dev_err(&adapter->pdev->dev,
+ " %s: Invalid word count\n", __func__);
+ return -EIO;
+ }
+
+ temp = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_SPI_CONTROL, &err);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_SPI_CONTROL,
+ (temp | QLC_83XX_FLASH_SPI_CONTROL_VAL));
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_ADDR_TEMP_VAL);
+
+ /* First DWORD write */
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_FIRST_WRITE_MS_PATTERN);
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ u32_word_count--;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
+
+ /* Second to N-1 DWORD writes */
+ while (u32_word_count != 1) {
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_WRDATA, *p_data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_SECOND_WRITE_MS_PATTERN);
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+ u32_word_count--;
+ }
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_ADDR_TEMP_VAL | (addr >> 2));
+ /* Last DWORD write */
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_LAST_WRITE_MS_PATTERN);
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ ret = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_SPI_STATUS, &err);
+ if ((ret & QLC_83XX_FLASH_SPI_CONTROL_VAL) ==
+ QLC_83XX_FLASH_SPI_CONTROL_VAL) {
+ dev_err(&adapter->pdev->dev,
+ " %s: failed at %d\n", __func__, __LINE__);
+ /* Operation failed, clear error bit */
+ temp = qlcnic_83xx_rd_reg_indirect(adapter,
+ QLC_83XX_FLASH_SPI_CONTROL, &err);
+ qlcnic_83xx_wrt_reg_indirect(adapter,
+ QLC_83XX_FLASH_SPI_CONTROL,
+ (temp | QLC_83XX_FLASH_SPI_CONTROL_VAL));
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
+{
+ int ret, err;
+
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
+ QLC_83XX_FLASH_OEM_READ_SIG);
+ qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
+ QLC_83XX_FLASH_READ_CONTROL_VAL);
+ ret = qlcnic_83xx_poll_flash_status_reg(adapter);
+ if (ret)
+ return -EIO;
+
+ ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA, &err);
+ return ret&0xFF;
+}
+
+int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
+{
+ int status;
+
+ status = qlcnic_83xx_read_flash_status_reg(adapter);
+ if (status == -EIO) {
+ dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n",
+ __func__);
+ return 1;
+ }
+ return 0;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 10/15] qlcnic: 83xx CNA inter driver communication mechanism
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Inter driver communication mechanism for 83xx CNA function drivers
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 3 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 8 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 102 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 1991 ++++++++++++++++++++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 8 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 5 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 144 ++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 12 +
9 files changed, 2211 insertions(+), 64 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index f87d98f..799325d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
- qlcnic_sysfs.o qlcnic_83xx_hw.o qlcnic_minidump.o
+ qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
+ qlcnic_83xx_init.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index f95477e..eaaa049 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1067,7 +1067,9 @@ struct qlcnic_adapter {
struct msix_entry *msix_entries;
+ struct workqueue_struct *qlcnic_wq;
struct delayed_work fw_work;
+ struct delayed_work idc_aen_work;
struct qlcnic_filter_hash fhash;
@@ -1160,9 +1162,9 @@ struct qlcnic_eswitch {
#define QLCNIC_SWITCH_PORT_MIRRORING BIT_4
};
-
/* Return codes for Error handling */
-#define QL_STATUS_INVALID_PARAM -1
+#define QL_STATUS_INVALID_PARAM -1
+#define QL_STATUS_UNSUPPORTED_CMD -2
#define MAX_BW 100 /* % of link speed */
#define MAX_VLAN_ID 4095
@@ -1628,7 +1630,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
void qlcnic_dev_request_reset(struct qlcnic_adapter *, u32);
int qlcnic_validate_max_rss(u8, u8);
-int qlcnic_set_max_rss(struct qlcnic_adapter *, u8);
+int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t);
int qlcnic_setup_intr(struct qlcnic_adapter *, u8);
int qlcnic_msix_tx_poll(struct napi_struct *, int);
int qlcnic_poll(struct napi_struct *, int);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index c430723..fc50e1d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -161,11 +161,21 @@ struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
struct qlcnic_nic_template qlcnic_83xx_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
+ .request_reset = qlcnic_83xx_idc_request_reset,
+ .cancel_idc_work = qlcnic_83xx_idc_exit,
.napi_add = qlcnic_83xx_napi_add,
.config_ipaddr = qlcnic_83xx_config_ipaddr,
.clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
};
+void
+qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
+{
+ ahw->hw_ops = &qlcnic_83xx_hw_ops;
+ ahw->reg_tbl = (u32 *) qlcnic_83xx_reg_tbl;
+ ahw->ext_reg_tbl = (u32 *) qlcnic_83xx_ext_reg_tbl;
+}
+
int
qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
{
@@ -200,8 +210,8 @@ qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
fw_build = QLCRD(adapter, QLCNIC_FW_VERSION_SUB);
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
- dev_info(&pdev->dev, "firmware version %d.%d.%d\n",
- fw_major, fw_minor, fw_build);
+ dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
+ QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
return adapter->fw_version;
}
@@ -333,14 +343,14 @@ qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
{
u32 intr_val;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ int retries = 0;
intr_val = readl(adapter->tgt_status_reg);
- if (!QLCNIC_83XX_VALID_INTX_BIT30(intr_val)) {
- dev_info(&adapter->pdev->dev,
- "Invalid legacy interrupt:0x%x\n", intr_val);
+ if (!QLCNIC_83XX_VALID_INTX_BIT31(intr_val))
return IRQ_NONE;
- }
+
if (QLCNIC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
dev_info(&adapter->pdev->dev,
"Interrupt for wrong func: 0x%x\n", intr_val);
@@ -348,8 +358,23 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
}
/* clear the interrupt trigger control register */
writel(0, adapter->isr_int_vec);
- /* Delay for 4 msec to fix bug in chip, remove it for B0 chip rev */
- mdelay(4);
+
+ /* Legacy Workaround for A0 & B0 */
+ do {
+ intr_val = readl(adapter->tgt_status_reg);
+ if (QLCNIC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
+ break;
+ retries++;
+ } while (QLCNIC_83XX_VALID_INTX_BIT30(intr_val) &&
+ (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
+
+ if (retries == QLC_83XX_LEGACY_INTX_MAX_RETRY) {
+ dev_info(&adapter->pdev->dev,
+ "Reached maximum retries to clear legacy interrupt\n");
+ return IRQ_NONE;
+ }
+
+ mdelay(QLC_83XX_LEGACY_INTX_DELAY);
return IRQ_HANDLED;
}
@@ -1532,6 +1557,10 @@ qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
dev_info(&adapter->pdev->dev,
"Mailbox not available, 0x%x, collect FW dump\n",
mbx_val);
+ /* Take FW dump */
+ qlcnic_83xx_idc_request_reset(adapter,
+ QLCNIC_FORCE_FW_DUMP_KEY);
+ cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
spin_unlock_irqrestore(&ahw->mbx_lock, flags);
return cmd->rsp.arg[0];
@@ -1557,8 +1586,9 @@ poll:
if (rsp != QLCNIC_RCODE_TIMEOUT) {
if (opcode == QLCNIC_MBX_LINK_EVENT) {
for (i = 0; i < rsp_num; i++)
- fw[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw,
- i)));
+ fw[i] =
+ le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, i)));
+
qlcnic_83xx_handle_link_aen(adapter, fw);
/* clear fw mbx control register */
QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
@@ -1567,14 +1597,29 @@ poll:
goto poll;
} else if (opcode == QLCNIC_MBX_COMP_EVENT) {
for (i = 0; i < rsp_num; i++)
- fw[i] = le32_to_cpu(readl(QLCNIC_MBX_FW(ahw,
- i)));
+ fw[i] =
+ le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, i)));
qlcnic_83xx_handle_idc_comp_aen(adapter, fw);
/* clear fw mbx control register */
QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
if (mbx_val)
goto poll;
+ } else if (opcode == QLCNIC_MBX_REQUEST_EVENT) {
+ /* IDC Request Notification */
+ for (i = 0; i < rsp_num; i++)
+ fw[i] =
+ le32_to_cpu(readl(QLCNIC_MBX_FW(ahw, i)));
+ for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
+ adapter->ahw->mbox_aen[i] =
+ QLCNIC_MBX_RSP(fw[i]);
+ queue_delayed_work(adapter->qlcnic_wq,
+ &adapter->idc_aen_work, 0);
+ /* clear fw mbx control register */
+ QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
+ mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
+ if (mbx_val)
+ goto poll;
} else if ((mbx_err_code == QLCNIC_MBX_RSP_OK)
|| (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
for (i = 0; i < cmd->rsp.num; i++)
@@ -1591,6 +1636,9 @@ poll:
dev_info(&adapter->pdev->dev,
"MBX command 0x%x timed out\n", opcode);
qlcnic_dump_mbx(adapter, cmd);
+ /* Take FW dump */
+ qlcnic_83xx_idc_request_reset(adapter,
+ QLCNIC_FORCE_FW_DUMP_KEY);
}
/* clear fw mbx control register */
QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
@@ -1631,24 +1679,23 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
return 0;
}
-void qlcnic_83xx_handle_idc_request_aen(struct qlcnic_adapter *adapter)
+void qlcnic_83xx_idc_aen_work(struct work_struct *work)
{
+ struct qlcnic_adapter *adapter;
struct qlcnic_cmd_args cmd;
int i, err = 0;
+ adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
+
/* Issue idc ack mbx command */
- if (test_and_clear_bit(QLC_83XX_MBX_AEN_ACK,
- &adapter->ahw->idc.status)) {
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_IDC_ACK);
- for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
- cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err)
- dev_info(&adapter->pdev->dev,
- "%s: Mailbox IDC ACK failed.\n", __func__);
- qlcnic_free_mbx_args(&cmd);
- }
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
+ for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
+ cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_info(&adapter->pdev->dev,
+ "%s: Mailbox IDC ACK failed.\n", __func__);
+ qlcnic_free_mbx_args(&cmd);
}
static void
@@ -1683,7 +1730,9 @@ void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
case QLCNIC_MBX_REQUEST_EVENT:
for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
- set_bit(QLC_83XX_MBX_AEN_ACK, &adapter->ahw->idc.status);
+
+ queue_delayed_work(adapter->qlcnic_wq,
+ &adapter->idc_aen_work, 0);
break;
case QLCNIC_MBX_TIME_EXTEND_EVENT:
break;
@@ -1739,6 +1788,7 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
memset(&sds_mbx, 0, sds_mbx_size);
sds = &recv_ctx->sds_rings[i];
sds->consumer = 0;
+ memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
sds_mbx.phy_addr = cpu_to_le64(sds->phys_addr);
sds_mbx.sds_ring_size = cpu_to_le16(sds->num_desc);
if (adapter->flags & QLCNIC_MSIX_ENABLED)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
new file mode 100644
index 0000000..1bb9ae9
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -0,0 +1,1991 @@
+#include "qlcnic.h"
+#include "qlcnic_hw.h"
+
+static int
+qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter);
+static int
+qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
+
+static const char * const qlcnic_83xx_idc_states[] = {
+ "Unknown",
+ "Cold",
+ "Init",
+ "Ready",
+ "Need Reset",
+ "Need Quiesce",
+ "Failed",
+ "Quiesce"
+};
+
+/* IDC Device States */
+enum qlc_83xx_states {
+ QLC_83XX_IDC_DEV_UNKNOWN,
+ QLC_83XX_IDC_DEV_COLD,
+ QLC_83XX_IDC_DEV_INIT,
+ QLC_83XX_IDC_DEV_READY,
+ QLC_83XX_IDC_DEV_NEED_RESET,
+ QLC_83XX_IDC_DEV_NEED_QUISCENT,
+ QLC_83XX_IDC_DEV_FAILED,
+ QLC_83XX_IDC_DEV_QUISCENT
+};
+
+static int
+qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+
+ if ((val & 0xFFFF))
+ return 1;
+ else
+ return 0;
+}
+
+static void
+qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter *adapter)
+{
+ u32 cur, prev;
+ cur = adapter->ahw->idc.curr_state;
+ prev = adapter->ahw->idc.prev_state;
+
+ dev_info(&adapter->pdev->dev,
+ "current state = %s, prev state = %s\n",
+ adapter->ahw->idc.name[cur],
+ adapter->ahw->idc.name[prev]);
+}
+
+static int
+qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter, u8 mode,
+ int lock)
+{
+ u32 val;
+ int seconds;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ val = adapter->portnum & 0xf;
+ val |= mode << 7;
+ if (mode)
+ seconds = jiffies/HZ - adapter->ahw->idc.sec_counter;
+ else
+ seconds = jiffies/HZ;
+
+ val |= seconds << 8;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT, val);
+ adapter->ahw->idc.sec_counter = jiffies/HZ;
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static void
+qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION);
+ val = val & ~(0x3 << (adapter->portnum * 2));
+ val = val | (QLC_83XX_IDC_MINOR_VERSION << (adapter->portnum * 2));
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION, val);
+}
+
+static int
+qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter *adapter, int lock)
+{
+ u32 val;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);
+ val = val & ~0xFF;
+ val = val | QLC_83XX_IDC_MAJOR_VERSION;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION, val);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter *adapter,
+ int status, int lock)
+{
+ u32 val;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+
+ if (status)
+ val = val | (1 << adapter->portnum);
+ else
+ val = val & ~(1 << adapter->portnum);
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
+
+ qlcnic_83xx_idc_update_minor_version(adapter);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ u8 version;
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);
+ version = val & 0xFF;
+
+ if (version != QLC_83XX_IDC_MAJOR_VERSION) {
+ dev_info(&adapter->pdev->dev,
+ "%s: mismatch. version 0x%x, expected version 0x%x\n",
+ __func__, version, QLC_83XX_IDC_MAJOR_VERSION);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter *adapter, int lock)
+{
+ u32 val;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, 0);
+ /* Clear gracefull reset bit */
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ val &= ~QLC_83XX_IDC_GRACEFULL_RESET;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter *adapter,
+ int flag, int lock)
+{
+ u32 val;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);
+ if (flag)
+ val = val | (1 << adapter->portnum);
+ else
+ val = val & ~(1 << adapter->portnum);
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, val);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter *adapter, int time_limit)
+{
+ u64 seconds;
+
+ seconds = jiffies/HZ - adapter->ahw->idc.sec_counter;
+ if (seconds <= time_limit)
+ return 0;
+ else
+ return -EBUSY;
+}
+
+/**
+ * qlcnic_83xx_idc_check_reset_ack_reg
+ *
+ * @adapter: adapter structure
+ *
+ * Return 0 if all functions have acknowledged the reset request.
+ * Check ACK wait limit and clear the functions which failed to ACK
+ *
+ **/
+static int
+qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter *adapter)
+{
+ u32 ack, presence, val;
+
+ ack = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);
+ presence = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+ dev_info(&adapter->pdev->dev,
+ "%s: ack = 0x%x, presence = 0x%x\n", __func__, ack, presence);
+ if (~ack & presence) {
+ if (qlcnic_83xx_idc_check_timeout(adapter,
+ QLC_83XX_IDC_RESET_TIMEOUT_SECS)) {
+ /* Clear functions which failed to ACK */
+ dev_info(&adapter->pdev->dev,
+ "%s: ACK wait exceeds time limit\n", __func__);
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+ val = val & ~(ack^presence);
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
+ dev_info(&adapter->pdev->dev,
+ "%s: updated drv presence reg = 0x%x\n",
+ __func__, val);
+ qlcnic_83xx_unlock_driver(adapter);
+ return 0;
+
+ } else {
+ return 1;
+ }
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "%s: Reset ACK received from all functions\n",
+ __func__);
+ return 0;
+ }
+}
+
+/**
+ * qlcnic_83xx_idc_tx_soft_reset
+ *
+ * @adapter: adapter structure
+ *
+ * Handle context deletion and recreation request from transmit routine
+ *
+ * Returns -EBUSY or Success (0)
+ *
+ **/
+static int
+qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EBUSY;
+
+ netif_device_detach(netdev);
+ qlcnic_down(adapter, netdev);
+ qlcnic_up(adapter, netdev);
+ netif_device_attach(netdev);
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ dev_err(&adapter->pdev->dev, "%s:\n", __func__);
+
+ adapter->netdev->trans_start = jiffies;
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_detach_driver
+ *
+ * @adapter: adapter structure
+ * Detach net interface, stop TX and cleanup resources before the HW reset.
+ * Returns: None
+ *
+ **/
+static void
+qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
+{
+ int i;
+
+ struct net_device *netdev = adapter->netdev;
+
+ netif_device_detach(netdev);
+ /* Disable mailbox interrupt */
+ QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0);
+ qlcnic_down(adapter, netdev);
+ for (i = 0; i < adapter->ahw->num_msix; i++) {
+ adapter->ahw->intr_tbl[i].id = i;
+ adapter->ahw->intr_tbl[i].enabled = 0;
+ adapter->ahw->intr_tbl[i].src = 0;
+ }
+}
+
+/**
+ * qlcnic_83xx_idc_attach_driver
+ *
+ * @adapter: adapter structure
+ *
+ * Re-attach and re-enable net interface
+ * Returns: None
+ *
+ **/
+static void
+qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+
+ if (netif_running(netdev)) {
+ if (qlcnic_up(adapter, netdev))
+ goto done;
+
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+ }
+done:
+ netif_device_attach(netdev);
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+}
+
+static int
+qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,
+ int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ qlcnic_83xx_idc_clear_registers(adapter, 0);
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
+ QLC_83XX_IDC_DEV_FAILED);
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ qlcnic_83xx_idc_log_state_history(adapter);
+ dev_info(&adapter->pdev->dev, "Device will enter failed state\n");
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter *adapter, int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_INIT);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_enter_need_quiscent(struct qlcnic_adapter *adapter, int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
+ QLC_83XX_IDC_DEV_NEED_QUISCENT);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter *adapter, int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
+ QLC_83XX_IDC_DEV_NEED_RESET);
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter *adapter, int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,
+ QLC_83XX_IDC_DEV_READY);
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_find_reset_owner_id
+ *
+ * @adapter: adapter structure
+ *
+ * NIC gets precedence over ISCSI and ISCSI has precedence over FCOE.
+ * Within the same class, function with lowest PCI ID assumes ownership
+ *
+ * Returns: reset owner id or failure indication (-EIO)
+ *
+ **/
+static int
+qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter *adapter)
+{
+ u32 reg, reg1, reg2, i, j, owner, class;
+
+ reg1 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_1);
+ reg2 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_2);
+ owner = QLCNIC_TYPE_NIC;
+ i = 0;
+ j = 0;
+ reg = reg1;
+
+ do {
+ class = (((reg & (0xF << j*4)) >> j*4) & 0x3);
+ if (class == owner)
+ break;
+ if (i == (QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO - 1)) {
+ reg = reg2;
+ j = 0;
+ } else {
+ j++;
+ }
+
+ if (i == (QLC_83XX_IDC_MAX_CNA_FUNCTIONS - 1)) {
+ if (owner == QLCNIC_TYPE_NIC)
+ owner = QLCNIC_TYPE_ISCSI;
+ else if (owner == QLCNIC_TYPE_ISCSI)
+ owner = QLCNIC_TYPE_FCOE;
+ else if (owner == QLCNIC_TYPE_FCOE)
+ return -EIO;
+
+ reg = reg1;
+ j = 0;
+ i = 0;
+ }
+
+ } while (i++ < QLC_83XX_IDC_MAX_CNA_FUNCTIONS);
+
+ return i;
+}
+
+static int
+qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter *adapter, int lock)
+{
+ int ret = 0;
+
+ ret = qlcnic_83xx_restart_hw(adapter);
+
+ if (ret) {
+ qlcnic_83xx_idc_enter_failed_state(adapter, lock);
+ } else {
+ qlcnic_83xx_idc_clear_registers(adapter, lock);
+ ret = qlcnic_83xx_idc_enter_ready_state(adapter, lock);
+ }
+
+ return ret;
+}
+
+static int
+qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)
+{
+ u32 status;
+
+ status = QLCRD(adapter, QLCNIC_PEG_HALT_STATUS1);
+
+ if (status & QLCNIC_RCODE_FATAL_ERROR) {
+ dev_err(&adapter->pdev->dev,
+ "peg halt status1=0x%x\n", status);
+ if (QLCNIC_FWERROR_CODE(status) ==
+ QLCNIC_FWERROR_FAN_FAILURE) {
+ dev_err(&adapter->pdev->dev,
+ "On board active cooling fan failed. "
+ "Device has been halted.\n");
+ dev_err(&adapter->pdev->dev,
+ "Replace the adapter.\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
+{
+ qlcnic_83xx_enable_mbx_intrpt(adapter);
+ if ((adapter->flags & QLCNIC_MSIX_ENABLED)) {
+ if (qlcnic_83xx_config_intrpt(adapter, 1)) {
+ netdev_err(adapter->netdev,
+ "Failed to enable mbx intr\n");
+ return -EIO;
+ }
+ }
+
+ if (qlcnic_83xx_configure_opmode(adapter)) {
+ qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+ return -EIO;
+ }
+
+ if (adapter->nic_ops->init_driver(adapter)) {
+ qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+ return -EIO;
+ }
+
+ qlcnic_83xx_idc_attach_driver(adapter);
+
+ return 0;
+}
+
+static void
+qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
+{
+ qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+ qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
+ set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
+ adapter->ahw->idc.quiesce_req = 0;
+ adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
+ adapter->ahw->idc.err_code = 0;
+ adapter->ahw->idc.collect_dump = 0;
+}
+
+/**
+ * qlcnic_83xx_idc_ready_state_entry_action
+ *
+ * @adapter: adapter structure
+ *
+ * Perform ready state initialization, this routine will get invoked only
+ * once from READY state.
+ *
+ * Returns: -EIO or 0
+ *
+ **/
+int
+qlcnic_83xx_idc_ready_state_entry_action(struct qlcnic_adapter *adapter)
+{
+ if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) {
+ qlcnic_83xx_idc_update_idc_params(adapter);
+ /* Re-attach the device if required */
+ if ((adapter->ahw->idc.prev_state ==
+ QLC_83XX_IDC_DEV_NEED_RESET) ||
+ (adapter->ahw->idc.prev_state ==
+ QLC_83XX_IDC_DEV_INIT)) {
+ if (qlcnic_83xx_idc_reattach_driver(adapter))
+ return -EIO;
+
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_vnic_pf_ready_state_entry_action
+ *
+ * @adapter: adapter structure
+ *
+ * Ensure vNIC mode privileged function becomes ready only when vNIC mode is
+ * set ready by vNIC management function.
+ * If vNIC mode is ready, perform ready state initialization.
+ *
+ * Returns: -EIO or 0
+ *
+ **/
+int
+qlcnic_83xx_idc_vnic_pf_ready_state_entry_action(struct qlcnic_adapter *adapter)
+{
+ u32 state;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ /* Privileged function waits till mgmt function enables VNIC mode */
+ state = QLCRDX(adapter->ahw, QLC_83XX_VNIC_STATE);
+ if (state != QLCNIC_DEV_NPAR_OPER) {
+ if (!ahw->idc.vnic_wait_limit--) {
+ qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+ return -EIO;
+ }
+
+ dev_info(&adapter->pdev->dev, "vNIC mode disabled\n");
+ return -EIO;
+
+ } else {
+ /* Perform one time initialization from ready state */
+ if (adapter->ahw->idc.vnic_state != QLCNIC_DEV_NPAR_OPER) {
+ qlcnic_83xx_idc_update_idc_params(adapter);
+
+ /* If the previous state is UNKNOWN, device will be
+ already attached properly */
+ if (adapter->ahw->idc.prev_state !=
+ QLC_83XX_IDC_DEV_UNKNOWN) {
+ if (qlcnic_83xx_idc_reattach_driver(adapter))
+ return -EIO;
+ }
+
+ adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_OPER;
+ dev_info(&adapter->pdev->dev, "vNIC mode enabled\n");
+ }
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_unknown_state_handler(struct qlcnic_adapter *adapter)
+{
+ adapter->ahw->idc.err_code = -EIO;
+ dev_err(&adapter->pdev->dev,
+ "%s: Device in unknown state\n", __func__);
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_cold_state_handler
+ *
+ * @adapter: adapter structure
+ *
+ * If HW is up and running device will enter READY state.
+ * If host file system based firmware image needs to be loaded, device is
+ * forced to start with the file firmware image.
+ *
+ * Returns: Success (0) or -EIO
+ *
+ **/
+static int
+qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter *adapter)
+{
+ qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 0);
+ qlcnic_83xx_idc_update_audit_reg(adapter, 1, 0);
+ if (adapter->ahw->fw_info.load_from_file) {
+ qlcnic_83xx_idc_restart_hw(adapter, 0);
+ } else {
+ if (qlcnic_83xx_check_hw_status(adapter)) {
+ qlcnic_83xx_idc_enter_failed_state(adapter, 0);
+ return -EIO;
+ } else {
+ qlcnic_83xx_idc_enter_ready_state(adapter, 0);
+ }
+ }
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_init_state_handler
+ *
+ * @adapter: adapter structure
+ *
+ * Reset owner will restart the device from this state.
+ * Device will enter failed state if it remains
+ * in this state for more than DEV_INIT time limit.
+ *
+ * Returns:
+ *
+ **/
+static int
+qlcnic_83xx_idc_init_state_handler(struct qlcnic_adapter *adapter)
+{
+ int ret = 0;
+ u32 owner;
+
+ if (adapter->ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) {
+ owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+ if (adapter->ahw->pci_func == owner)
+ ret = qlcnic_83xx_idc_restart_hw(adapter, 1);
+ } else {
+ ret = qlcnic_83xx_idc_check_timeout(adapter,
+ QLC_83XX_IDC_INIT_TIMEOUT_SECS);
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * qlcnic_83xx_idc_ready_state_handler
+ *
+ * @adapter: adapter structure
+ *
+ * Perform IDC protocol specicifed actions after monitoring device temperature,
+ * FW status, reset and quiesce requests.
+ *
+ * Returns: 0 or -EIO
+ *
+ **/
+static int
+qlcnic_83xx_idc_ready_state_handler(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ int ret = 0;
+
+ /* Perform NIC configuration based ready state entry actions */
+ if (ahw->idc.ready_state_entry_action(adapter))
+ return -EIO;
+
+ /* Check temperature */
+ if (qlcnic_check_temp(adapter)) {
+ if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
+ qlcnic_83xx_idc_check_fan_failure(adapter);
+ dev_err(&adapter->pdev->dev,
+ "Error: device temperature %d above limits\n",
+ adapter->ahw->temp);
+ clear_bit(QLC_83XX_MBX_READY,
+ &adapter->ahw->idc.status);
+ set_bit(__QLCNIC_RESETTING, &adapter->state);
+ qlcnic_83xx_idc_detach_driver(adapter);
+ qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+ return -EIO;
+ }
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+
+ /* Check FW hearbeat */
+ ret = qlcnic_83xx_check_heartbeat(adapter);
+ if (ret) {
+ adapter->flags |= QLCNIC_FW_HANG;
+ if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
+ clear_bit(QLC_83XX_MBX_READY,
+ &adapter->ahw->idc.status);
+ set_bit(__QLCNIC_RESETTING, &adapter->state);
+ qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
+ }
+ return -EIO;
+ }
+
+ if ((val & QLC_83XX_IDC_GRACEFULL_RESET) ||
+ adapter->ahw->idc.collect_dump) {
+ /* Move to need reset state and prepare for reset */
+ qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
+ return ret;
+
+ }
+
+ /* Check for soft reset request */
+ if (adapter->ahw->reset_context &&
+ !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
+ qlcnic_83xx_idc_tx_soft_reset(adapter);
+ return ret;
+ }
+
+ /* Move to need quiesce state if requested */
+ if (adapter->ahw->idc.quiesce_req) {
+ qlcnic_83xx_idc_enter_need_quiscent(adapter, 1);
+ qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * qlcnic_83xx_idc_need_reset_state_handler
+ *
+ * @adapter: adapter structure
+ *
+ * Device will remain in this state until:
+ * Reset request ACK's are recieved from all the functions
+ * Wait time exceeds max time limit
+ *
+ * Source States:
+ * Destination States:
+ *
+ * Returns: 0 or -EIO
+ *
+ **/
+static int
+qlcnic_83xx_idc_need_reset_state_handler(struct qlcnic_adapter *adapter)
+{
+ int ret = 0;
+
+ if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
+ qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
+ qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
+ set_bit(__QLCNIC_RESETTING, &adapter->state);
+ clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+ qlcnic_83xx_idc_detach_driver(adapter);
+ }
+
+ /* Check ACK from other functions */
+ ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
+ if (ret) {
+ dev_info(&adapter->pdev->dev,
+ "%s: Waiting for reset ACK\n", __func__);
+ return 0;
+ }
+
+ /* Transit to INIT state and restart the HW */
+ qlcnic_83xx_idc_enter_init_state(adapter, 1);
+
+ return ret;
+}
+
+static int
+qlcnic_83xx_idc_need_quiesce_state_handler(struct qlcnic_adapter *adapter)
+{
+ dev_err(&adapter->pdev->dev, "%s: TBD\n", __func__);
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_failed_state_handler(struct qlcnic_adapter *adapter)
+{
+ dev_err(&adapter->pdev->dev,
+ "%s: please reboot!!\n", __func__);
+ adapter->ahw->idc.err_code = -EIO;
+
+ return 0;
+}
+
+static int
+qlcnic_83xx_idc_quiesce_state_handler(struct qlcnic_adapter *adapter)
+{
+ dev_info(&adapter->pdev->dev,
+ "%s: TBD\n", __func__);
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_check_dev_state_validity
+ *
+ * @adapter: adapter structure
+ * @state: IDC destination state
+ *
+ * Ensure state transitions are according to the IDC protocol.
+ *
+ * Returns: Success (0) or FAILURE (1)
+ *
+ **/
+static int
+qlcnic_83xx_idc_check_dev_state_validity(struct qlcnic_adapter *adapter,
+ u32 state)
+{
+ u32 cur, prev, next;
+
+ cur = adapter->ahw->idc.curr_state;
+ prev = adapter->ahw->idc.prev_state;
+ next = state;
+
+ if ((next < QLC_83XX_IDC_DEV_COLD) ||
+ (next > QLC_83XX_IDC_DEV_QUISCENT)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: curr %d, prev %d, next state %d is invalid\n",
+ __func__, cur, prev, state);
+ return 1;
+ }
+
+ if ((cur == QLC_83XX_IDC_DEV_UNKNOWN) &&
+ (prev == QLC_83XX_IDC_DEV_UNKNOWN)) {
+ if ((next != QLC_83XX_IDC_DEV_COLD) &&
+ (next != QLC_83XX_IDC_DEV_READY)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: invalid transition, cur %d prev %d next %d\n",
+ __func__, cur, prev, next);
+ return 1;
+ }
+ }
+
+ if (next == QLC_83XX_IDC_DEV_INIT) {
+ if ((prev != QLC_83XX_IDC_DEV_INIT) &&
+ (prev != QLC_83XX_IDC_DEV_COLD) &&
+ (prev != QLC_83XX_IDC_DEV_NEED_RESET)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: invalid transition, cur %d prev %d next %d\n",
+ __func__, cur, prev, next);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_poll_dev_state
+ *
+ * @work: kernel work queue structure used to schedule the function
+ *
+ * Poll device state periodically and perform state specific
+ * actions defined by Inter Driver Communication (IDC) protocol.
+ *
+ * Returns: None
+ *
+ **/
+void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
+{
+ struct qlcnic_adapter *adapter;
+ u32 state;
+
+ adapter = container_of(work, struct qlcnic_adapter, fw_work.work);
+ state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);
+
+ if (qlcnic_83xx_idc_check_dev_state_validity(adapter, state)) {
+ qlcnic_83xx_idc_log_state_history(adapter);
+ adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;
+ } else {
+ adapter->ahw->idc.curr_state = state;
+ }
+
+ switch (adapter->ahw->idc.curr_state) {
+ case QLC_83XX_IDC_DEV_READY:
+ qlcnic_83xx_idc_ready_state_handler(adapter);
+ break;
+
+ case QLC_83XX_IDC_DEV_NEED_RESET:
+ qlcnic_83xx_idc_need_reset_state_handler(adapter);
+ break;
+
+ case QLC_83XX_IDC_DEV_NEED_QUISCENT:
+ qlcnic_83xx_idc_need_quiesce_state_handler(adapter);
+ break;
+
+ case QLC_83XX_IDC_DEV_FAILED:
+ qlcnic_83xx_idc_failed_state_handler(adapter);
+ return;
+
+ case QLC_83XX_IDC_DEV_INIT:
+ qlcnic_83xx_idc_init_state_handler(adapter);
+ break;
+
+ case QLC_83XX_IDC_DEV_QUISCENT:
+ qlcnic_83xx_idc_quiesce_state_handler(adapter);
+ break;
+
+ default:
+ qlcnic_83xx_idc_unknown_state_handler(adapter);
+ return;
+ }
+
+ adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
+
+ /* Re-schedule the function */
+ if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
+ qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
+ adapter->ahw->idc.delay);
+}
+
+static void
+qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
+{
+ u32 idc_params, val;
+
+ if (qlcnic_83xx_lockless_flash_read_u32(adapter,
+ QLC_83XX_IDC_FLASH_PARAM_ADDR,
+ (u8 *)&idc_params, 1)) {
+ dev_info(&adapter->pdev->dev,
+ "%s: failed to get IDC params from flash.\n", __func__);
+ adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;
+ adapter->reset_ack_timeo = QLC_83XX_IDC_RESET_TIMEOUT_SECS;
+ } else {
+ adapter->dev_init_timeo = idc_params & 0xFFFF;
+ adapter->reset_ack_timeo = ((idc_params >> 16) & 0xFFFF);
+ }
+
+ adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;
+ adapter->ahw->idc.prev_state = QLC_83XX_IDC_DEV_UNKNOWN;
+ adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
+ adapter->ahw->idc.err_code = 0;
+ adapter->ahw->idc.collect_dump = 0;
+ adapter->ahw->idc.name = (char **)qlcnic_83xx_idc_states;
+
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+ set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
+
+ /* Check if reset recovery is disabled */
+ if (!auto_fw_reset) {
+ /* Propagate do not reset request to other functions */
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ val = val | QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
+ }
+}
+
+/**
+ * qlcnic_83xx_idc_first_to_load_function_handler
+ *
+ * @adapter: adapter structure
+ *
+ * Peform first to load function specific initialization
+ *
+ * Returns: Success(0) or Failure(-EIO)
+ *
+ **/
+static int
+qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter)
+{
+ u32 state, val;
+
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EIO;
+
+ /* Clear driver lock register */
+ QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, 0);
+
+ if (qlcnic_83xx_idc_update_major_version(adapter, 0)) {
+ qlcnic_83xx_unlock_driver(adapter);
+ return -EIO;
+ }
+
+ state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);
+ if (qlcnic_83xx_idc_check_dev_state_validity(adapter, state)) {
+ qlcnic_83xx_unlock_driver(adapter);
+ return -EIO;
+ }
+
+ adapter->ahw->idc.curr_state = state;
+
+ /* First to load function should cold boot the device */
+ if (state == QLC_83XX_IDC_DEV_COLD)
+ qlcnic_83xx_idc_cold_state_handler(adapter);
+
+ /* Check if reset recovery is enabled */
+ if (auto_fw_reset) {
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ val = val & ~QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
+ }
+
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_idc_init
+ *
+ * @adapter: adapter structure
+ *
+ * Initialize IDC task parameters
+ *
+ * Returns: Success(0) or Failure(-EIO)
+ *
+ **/
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
+{
+ int ret = -EIO;
+
+ qlcnic_83xx_setup_idc_parameters(adapter);
+
+ if (!qlcnic_83xx_idc_check_driver_presence_reg(adapter)) {
+ if (qlcnic_83xx_idc_first_to_load_function_handler(adapter))
+ return -EIO;
+ } else {
+ if (qlcnic_83xx_idc_check_major_version(adapter))
+ return -EIO;
+ }
+
+ if (qlcnic_83xx_get_reset_instruction_template(adapter))
+ return ret;
+
+ qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
+
+ return 0;
+}
+
+void
+qlcnic_83xx_idc_exit(struct qlcnic_adapter *adapter)
+{
+ int id;
+ u32 val;
+
+ while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ usleep_range(10000, 11000);
+
+ id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+ id = id & 0xFF;
+
+ if (id == adapter->portnum) {
+ dev_err(&adapter->pdev->dev,
+ "%s: wait for lock recovery.. %d\n", __func__, id);
+ msleep(20);
+ id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
+ id = id & 0xFF;
+ }
+
+ /* Clear driver presence bit */
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+ val = val & ~(1 << adapter->portnum);
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);
+
+ clear_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+}
+
+void
+qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
+{
+ u32 val;
+
+ if (qlcnic_83xx_lock_driver(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s:failed, please retry\n", __func__);
+ return;
+ }
+
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) || !auto_fw_reset) {
+ dev_err(&adapter->pdev->dev,
+ "%s:failed, device in non reset mode\n", __func__);
+ qlcnic_83xx_unlock_driver(adapter);
+ return;
+ }
+
+ if (key == QLCNIC_FORCE_FW_RESET) {
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ val = val | QLC_83XX_IDC_GRACEFULL_RESET;
+ QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
+ } else if (key == QLCNIC_FORCE_FW_DUMP_KEY) {
+ adapter->ahw->idc.collect_dump = 1;
+ }
+
+ qlcnic_83xx_unlock_driver(adapter);
+ return;
+}
+
+static int
+qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
+{
+ u8 *p_cache;
+ u32 src, count, size;
+ u64 dest;
+ int ret = -EIO;
+
+ src = QLC_83XX_BOOTLOADER_FLASH_ADDR;
+ dest = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_ADDR);
+ size = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_SIZE);
+
+ /* alignmnet check */
+ if (size & 0xF)
+ size = (size + 16) & ~0xF;
+
+ count = size/16;
+
+ p_cache = kzalloc(size, GFP_KERNEL);
+ if (p_cache == NULL) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to allocate memory for boot loader cache\n");
+ return -ENOMEM;
+ }
+
+ ret = qlcnic_83xx_lockless_flash_read_u32(adapter, src,
+ p_cache, size/sizeof(u32));
+ if (ret) {
+ kfree(p_cache);
+ return ret;
+ }
+
+ /* 16 byte write to MS memory */
+ ret = qlcnic_83xx_ms_mem_write_128b(adapter, dest,
+ (u32 *)p_cache, size/16);
+ if (ret) {
+ kfree(p_cache);
+ return ret;
+ }
+
+ kfree(p_cache);
+
+ return ret;
+}
+
+static int
+qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
+{
+ u32 dest, *p_cache;
+ u64 addr ;
+ u8 data[16] ;
+ size_t size ;
+ int i, ret = -EIO;
+
+ dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
+
+ size = (adapter->ahw->fw_info.fw->size & ~0xF);
+ p_cache = (u32 *)adapter->ahw->fw_info.fw->data;
+ addr = (u64)dest;
+
+ ret = qlcnic_83xx_ms_mem_write_128b(adapter, addr,
+ (u32 *)p_cache, size/16);
+ if (ret) {
+ dev_err(&adapter->pdev->dev, "MS memory write failed\n");
+ release_firmware(adapter->ahw->fw_info.fw);
+ adapter->ahw->fw_info.fw = NULL;
+ return -EIO;
+ }
+
+ /* Check 128 bit alignment */
+ if (adapter->ahw->fw_info.fw->size & 0xF) {
+ addr = dest + size;
+ for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++)
+ data[i] = adapter->ahw->fw_info.fw->data[size + i];
+
+ for (; i < 16 ; i++)
+ data[i] = 0;
+
+ ret = qlcnic_83xx_ms_mem_write_128b(adapter, addr,
+ (u32 *)data, 1);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ "MS memory write failed\n");
+ release_firmware(adapter->ahw->fw_info.fw);
+ adapter->ahw->fw_info.fw = NULL;
+ return -EIO;
+ }
+ }
+
+ release_firmware(adapter->ahw->fw_info.fw);
+ adapter->ahw->fw_info.fw = NULL;
+
+ return 0 ;
+}
+
+int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev)
+{
+ u32 heartbeat, ret = -EIO;
+ int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
+
+ p_dev->heartbeat = QLCRD(p_dev, QLCNIC_PEG_ALIVE_COUNTER);
+
+ do {
+ msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
+ heartbeat = QLCRD(p_dev, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != p_dev->heartbeat) {
+ ret = QLCNIC_RCODE_SUCCESS;
+ break;
+ }
+ } while (--retries);
+
+ if (ret)
+ dev_err(&p_dev->pdev->dev, "firmware hang detected\n");
+
+ return ret;
+}
+
+static int
+qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter *p_dev)
+{
+ int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
+ u32 val;
+
+ do {
+ val = QLCRD(p_dev, QLCNIC_CMDPEG_STATE);
+ if (val == QLC_83xx_CMDPEG_COMPLETE)
+ return 0;
+
+ msleep(QLCNIC_CMDPEG_CHECK_DELAY);
+ } while (--retries);
+
+ dev_err(&p_dev->pdev->dev, "%s: failed, state = 0x%x\n", __func__, val);
+ return -EIO;
+}
+
+int
+qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev)
+{
+ int err;
+
+ err = qlcnic_83xx_check_cmd_peg_status(p_dev);
+ if (err)
+ return err;
+
+ err = qlcnic_83xx_check_heartbeat(p_dev);
+ if (err)
+ return err;
+
+ return err;
+}
+
+static int
+qlcnic_83xx_poll_reg(struct qlcnic_adapter *p_dev, u32 addr, int duration,
+ u32 test_mask, u32 test_result)
+{
+ u32 value;
+ int err, timeout_error;
+ u8 retries;
+
+ value = qlcnic_83xx_rd_reg_indirect(p_dev, addr, &err);
+
+ /* poll every 1/10 of the total duration */
+ retries = duration/10;
+
+ do {
+ if ((value & test_mask) != test_result) {
+ timeout_error = 1;
+ msleep(duration/10);
+ value = qlcnic_83xx_rd_reg_indirect(p_dev, addr, &err);
+ } else {
+ timeout_error = 0;
+ break;
+ }
+ } while (retries--);
+
+ if (timeout_error) {
+ p_dev->ahw->reset.seq_error++ ;
+ dev_err(&p_dev->pdev->dev,
+ "%s: 0x%08x 0x%08x 0x%08x\n",
+ __func__, value, test_mask, test_result);
+ }
+
+ return timeout_error;
+}
+
+static int
+qlcnic_83xx_validate_reset_template_checksum(struct qlcnic_adapter *p_dev)
+{
+ u32 sum = 0;
+ u16 *buff = (u16 *)p_dev->ahw->reset.buff;
+ int count = p_dev->ahw->reset.hdr->size / sizeof(u16);
+
+ while (count-- > 0)
+ sum += *buff++;
+
+ while (sum >> 16)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+
+ if (~sum) {
+ return 0;
+ } else {
+ dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
+ return -1;
+ }
+}
+
+int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
+{
+ u8 *p_buff;
+ u32 addr, u32_count;
+
+ p_dev->ahw->reset.seq_error = 0;
+ p_dev->ahw->reset.buff =
+ kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
+
+ if (p_dev->ahw->reset.buff == NULL) {
+ dev_err(&p_dev->pdev->dev,
+ "%s: resource allocation failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ p_buff = p_dev->ahw->reset.buff;
+ addr = QLC_83XX_RESET_TEMPLATE_ADDR;
+
+ u32_count = sizeof(struct qlcnic_83xx_reset_template_hdr) / sizeof(u32);
+
+ /* Copy template header from flash */
+ if (qlcnic_83xx_flash_read_u32(p_dev, addr, p_buff, u32_count)) {
+ dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
+ return -EIO;
+ }
+
+ p_dev->ahw->reset.hdr =
+ (struct qlcnic_83xx_reset_template_hdr *) p_dev->ahw->reset.buff;
+
+ addr = QLC_83XX_RESET_TEMPLATE_ADDR + p_dev->ahw->reset.hdr->hdr_size;
+ p_buff = p_dev->ahw->reset.buff + p_dev->ahw->reset.hdr->hdr_size;
+ u32_count = (p_dev->ahw->reset.hdr->size -
+ p_dev->ahw->reset.hdr->hdr_size)/sizeof(u32);
+
+ /* Copy rest of the template */
+ if (qlcnic_83xx_flash_read_u32(p_dev, addr, p_buff, u32_count)) {
+ dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
+ return -EIO;
+ }
+
+ /* Integrity check */
+ if (qlcnic_83xx_validate_reset_template_checksum(p_dev))
+ return -EIO;
+
+ /* Get STOP, START, INIT sequence offsets */
+ p_dev->ahw->reset.init_offset = p_dev->ahw->reset.buff +
+ p_dev->ahw->reset.hdr->init_seq_offset;
+
+ p_dev->ahw->reset.start_offset = p_dev->ahw->reset.buff +
+ p_dev->ahw->reset.hdr->start_seq_offset;
+
+ p_dev->ahw->reset.stop_offset = p_dev->ahw->reset.buff +
+ p_dev->ahw->reset.hdr->hdr_size;
+ return 0;
+}
+
+static void
+qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter *p_dev, u32 raddr,
+ u32 waddr)
+{
+ int err, value;
+
+ value = qlcnic_83xx_rd_reg_indirect(p_dev, raddr, &err);
+ qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);
+}
+
+/* Read Modify Write CRB register. */
+static void
+qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter *p_dev,
+ u32 raddr, u32 waddr, struct qlcnic_83xx_rmw *p_rmw_hdr)
+{
+ int value, err;
+ if (p_rmw_hdr->index_a)
+ value = p_dev->ahw->reset.array[p_rmw_hdr->index_a];
+ else
+ value = qlcnic_83xx_rd_reg_indirect(p_dev, raddr, &err);
+
+ value &= p_rmw_hdr->test_mask;
+ value <<= p_rmw_hdr->shl;
+ value >>= p_rmw_hdr->shr;
+ value |= p_rmw_hdr->or_value;
+ value ^= p_rmw_hdr->xor_value;
+ qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);
+ return;
+}
+
+static void
+qlcnic_83xx_write_list(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ int i;
+ struct qlcnic_83xx_entry *p_entry;
+
+ p_entry = (struct qlcnic_83xx_entry *)((char *)p_hdr +
+ sizeof(struct qlcnic_83xx_reset_entry_hdr));
+
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_wrt_reg_indirect(p_dev, p_entry->arg1,
+ p_entry->arg2);
+ if (p_hdr->delay)
+ udelay((u32)(p_hdr->delay));
+ }
+}
+
+static void
+qlcnic_83xx_read_write_list(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ int i;
+ struct qlcnic_83xx_entry *p_entry;
+
+ p_entry = (struct qlcnic_83xx_entry *)((char *)p_hdr +
+ sizeof(struct qlcnic_83xx_reset_entry_hdr));
+
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_read_write_crb_reg(p_dev, p_entry->arg1,
+ p_entry->arg2);
+ if (p_hdr->delay)
+ udelay((u32)(p_hdr->delay));
+ }
+}
+
+static void
+qlcnic_83xx_poll_list(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ long delay;
+ struct qlcnic_83xx_entry *p_entry;
+ struct qlcnic_83xx_poll *p_poll;
+ int i, err;
+
+ p_poll = (struct qlcnic_83xx_poll *)
+ ((char *)p_hdr + sizeof(struct qlcnic_83xx_reset_entry_hdr));
+
+ p_entry = (struct qlcnic_83xx_entry *)((char *)p_poll +
+ sizeof(struct qlcnic_83xx_poll));
+
+ delay = (long)p_hdr->delay;
+
+ if (!delay) {
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_poll_reg(p_dev, p_entry->arg1,
+ delay, p_poll->test_mask, p_poll->test_value);
+ }
+ } else {
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ if (delay) {
+ if (qlcnic_83xx_poll_reg(p_dev,
+ p_entry->arg1, delay,
+ p_poll->test_mask,
+ p_poll->test_value)){
+ qlcnic_83xx_rd_reg_indirect(p_dev,
+ p_entry->arg1, &err);
+ qlcnic_83xx_rd_reg_indirect(p_dev,
+ p_entry->arg2, &err);
+
+ dev_err(&p_dev->pdev->dev,
+ "Timeout Error: poll list ");
+ dev_err(&p_dev->pdev->dev,
+ "item_num = %d entry_num = %d\n",
+ i, p_dev->ahw->reset.seq_index);
+ }
+ }
+ }
+ }
+}
+
+static void
+qlcnic_83xx_poll_write_list(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ long delay;
+ struct qlcnic_83xx_quad_entry *p_entry;
+ struct qlcnic_83xx_poll *p_poll;
+ int i;
+
+ p_poll = (struct qlcnic_83xx_poll *)((char *)p_hdr +
+ sizeof(struct qlcnic_83xx_reset_entry_hdr));
+ p_entry = (struct qlcnic_83xx_quad_entry *)((char *)p_poll +
+ sizeof(struct qlcnic_83xx_poll));
+
+ delay = (long)p_hdr->delay;
+
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_wrt_reg_indirect(p_dev,
+ p_entry->dr_addr, p_entry->dr_value);
+ qlcnic_83xx_wrt_reg_indirect(p_dev,
+ p_entry->ar_addr, p_entry->ar_value);
+ if (delay) {
+ if (qlcnic_83xx_poll_reg(p_dev,
+ p_entry->ar_addr, delay,
+ p_poll->test_mask,
+ p_poll->test_value)){
+ dev_err(&p_dev->pdev->dev,
+ "Timeout Error: poll list ");
+ dev_err(&p_dev->pdev->dev,
+ "item_num = %d entry_num = %d\n",
+ i, p_dev->ahw->reset.seq_index);
+ }
+ }
+ }
+}
+
+static void
+qlcnic_83xx_read_modify_write(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ struct qlcnic_83xx_entry *p_entry;
+ struct qlcnic_83xx_rmw *p_rmw_hdr;
+ int i;
+
+ p_rmw_hdr = (struct qlcnic_83xx_rmw *)((char *)p_hdr +
+ sizeof(struct qlcnic_83xx_reset_entry_hdr));
+
+ p_entry = (struct qlcnic_83xx_entry *)((char *)p_rmw_hdr +
+ sizeof(struct qlcnic_83xx_rmw));
+
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_rmw_crb_reg(p_dev, p_entry->arg1,
+ p_entry->arg2, p_rmw_hdr);
+ if (p_hdr->delay)
+ udelay((u32)(p_hdr->delay));
+ }
+}
+
+static void
+qlcnic_83xx_pause(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ if (p_hdr->delay)
+ mdelay((u32)((long)p_hdr->delay));
+}
+
+static void
+qlcnic_83xx_poll_read_list(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ long delay;
+ int index, i, err;
+ struct qlcnic_83xx_quad_entry *p_entry;
+ struct qlcnic_83xx_poll *p_poll;
+
+ p_poll = (struct qlcnic_83xx_poll *)
+ ((char *)p_hdr + sizeof(struct qlcnic_83xx_reset_entry_hdr));
+
+ p_entry = (struct qlcnic_83xx_quad_entry *)
+ ((char *)p_poll + sizeof(struct qlcnic_83xx_poll));
+
+ delay = (long)p_hdr->delay;
+
+ for (i = 0; i < p_hdr->count; i++, p_entry++) {
+ qlcnic_83xx_wrt_reg_indirect(p_dev, p_entry->ar_addr,
+ p_entry->ar_value);
+ if (delay) {
+ if (qlcnic_83xx_poll_reg(p_dev, p_entry->ar_addr, delay,
+ p_poll->test_mask, p_poll->test_value)){
+ dev_err(&p_dev->pdev->dev,
+ "Timeout Error: poll list ");
+ dev_err(&p_dev->pdev->dev,
+ "item_num = %d entry_num = %d\n", i,
+ p_dev->ahw->reset.seq_index);
+ } else {
+ index = p_dev->ahw->reset.array_index;
+ p_dev->ahw->reset.array[index++] =
+ qlcnic_83xx_rd_reg_indirect(p_dev,
+ p_entry->dr_addr, &err);
+ if (index == QLC_83XX_MAX_RESET_SEQ_ENTRIES)
+ p_dev->ahw->reset.array_index = 1;
+ }
+ }
+ }
+}
+
+static inline void
+qlcnic_83xx_seq_end(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ p_dev->ahw->reset.seq_end = 1;
+}
+
+static void
+qlcnic_83xx_template_end(struct qlcnic_adapter *p_dev,
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr)
+{
+ p_dev->ahw->reset.template_end = 1;
+
+ if (p_dev->ahw->reset.seq_error == 0)
+ dev_err(&p_dev->pdev->dev,
+ "HW restart process completed successfully.\n");
+ else
+ dev_err(&p_dev->pdev->dev,
+ "HW restart completed with timeout errors.\n");
+}
+
+static void
+qlcnic_83xx_execute_template_instructions(struct qlcnic_adapter *p_dev,
+ char *p_buff)
+{
+ int index, entries;
+ struct qlcnic_83xx_reset_entry_hdr *p_hdr;
+ char *p_entry = p_buff;
+
+ p_dev->ahw->reset.seq_end = 0;
+ p_dev->ahw->reset.template_end = 0;
+ entries = p_dev->ahw->reset.hdr->entries;
+ index = p_dev->ahw->reset.seq_index;
+
+ for ( ; (!p_dev->ahw->reset.seq_end) && (index < entries); index++) {
+
+ p_hdr = (struct qlcnic_83xx_reset_entry_hdr *)p_entry;
+
+ switch (p_hdr->cmd) {
+ case OPCODE_NOP:
+ break;
+ case OPCODE_WRITE_LIST:
+ qlcnic_83xx_write_list(p_dev, p_hdr);
+ break;
+ case OPCODE_READ_WRITE_LIST:
+ qlcnic_83xx_read_write_list(p_dev, p_hdr);
+ break;
+ case OPCODE_POLL_LIST:
+ qlcnic_83xx_poll_list(p_dev, p_hdr);
+ break;
+ case OPCODE_POLL_WRITE_LIST:
+ qlcnic_83xx_poll_write_list(p_dev, p_hdr);
+ break;
+ case OPCODE_READ_MODIFY_WRITE:
+ qlcnic_83xx_read_modify_write(p_dev, p_hdr);
+ break;
+ case OPCODE_SEQ_PAUSE:
+ qlcnic_83xx_pause(p_dev, p_hdr);
+ break;
+ case OPCODE_SEQ_END:
+ qlcnic_83xx_seq_end(p_dev, p_hdr);
+ break;
+ case OPCODE_TMPL_END:
+ qlcnic_83xx_template_end(p_dev, p_hdr);
+ break;
+ case OPCODE_POLL_READ_LIST:
+ qlcnic_83xx_poll_read_list(p_dev, p_hdr);
+ break;
+ default:
+ dev_err(&p_dev->pdev->dev,
+ "%s: Unknown opcode 0x%04x in template entry %d\n",
+ __func__, p_hdr->cmd, index);
+ break;
+ }
+
+ /* Set pointer to next entry in the sequence. */
+ p_entry += p_hdr->size;
+ }
+
+ p_dev->ahw->reset.seq_index = index;
+}
+
+static void
+qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
+{
+ p_dev->ahw->reset.seq_index = 0;
+ qlcnic_83xx_execute_template_instructions(p_dev,
+ p_dev->ahw->reset.stop_offset);
+
+ if (p_dev->ahw->reset.seq_end != 1)
+ dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
+}
+
+static void
+qlcnic_83xx_start_hw(struct qlcnic_adapter *p_dev)
+{
+ qlcnic_83xx_execute_template_instructions(p_dev,
+ p_dev->ahw->reset.start_offset);
+
+ if (p_dev->ahw->reset.template_end != 1)
+ dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
+}
+
+static void
+qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)
+{
+ qlcnic_83xx_execute_template_instructions(p_dev,
+ p_dev->ahw->reset.init_offset);
+
+ if (p_dev->ahw->reset.seq_end != 1)
+ dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
+}
+
+int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int err = -EIO;
+
+ qlcnic_83xx_stop_hw(adapter);
+
+ /* Collect FW register dump if required */
+ val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+ if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
+ qlcnic_dump_fw(adapter);
+
+ qlcnic_83xx_init_hw(adapter);
+ if (qlcnic_83xx_copy_bootloader(adapter))
+ return err;
+ /* Boot either flash image or firmware image from host file system */
+ if (adapter->ahw->fw_info.load_from_file) {
+ if (request_firmware(&adapter->ahw->fw_info.fw,
+ QLC_83XX_FW_FILE_NAME, &(adapter->pdev->dev))) {
+ dev_err(&adapter->pdev->dev,
+ "No file FW image, loading flash FW image.\n");
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID,
+ QLC_83XX_BOOT_FROM_FLASH);
+ } else {
+ if (qlcnic_83xx_copy_fw_file(adapter))
+ return err;
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID,
+ QLC_83XX_BOOT_FROM_FILE);
+ }
+ } else {
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID, QLC_83XX_BOOT_FROM_FLASH);
+ }
+ qlcnic_83xx_start_hw(adapter);
+ if (qlcnic_83xx_check_hw_status(adapter))
+ return -EIO;
+
+ return 0;
+}
+
+/**
+* qlcnic_83xx_config_default_opmode
+*
+* @adapter: adapter structure
+*
+* Configure default driver operating mode
+*
+* Returns: 0 or -EIO
+* */
+int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter)
+{
+ u32 op_mode;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ ahw->hw_ops->get_func_no(adapter);
+ op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
+
+ if (op_mode == QLC_83XX_DEFAULT_OPMODE) {
+ adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
+ adapter->ahw->idc.ready_state_entry_action =
+ qlcnic_83xx_idc_ready_state_entry_action;
+ } else {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_info nic_info;
+ int err;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ err = ahw->hw_ops->get_nic_info(adapter, &nic_info, ahw->pci_func);
+ if (err)
+ return -EIO;
+
+ ahw->physical_port = (u8) nic_info.phys_port;
+ ahw->switch_mode = nic_info.switch_mode;
+ ahw->max_tx_ques = nic_info.max_tx_ques;
+ ahw->max_rx_ques = nic_info.max_rx_ques;
+ ahw->capabilities = nic_info.capabilities;
+ ahw->max_mac_filters = nic_info.max_mac_filters;
+ ahw->max_mtu = nic_info.max_mtu;
+
+ if (ahw->capabilities & BIT_23)
+ ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
+ else
+ ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
+
+ return ahw->nic_mode;
+}
+
+static int
+qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
+{
+ int ret;
+
+ ret = qlcnic_83xx_get_nic_configuration(adapter);
+ if (ret == -EIO)
+ return -EIO;
+
+ if (ret == QLC_83XX_DEFAULT_MODE) {
+ if (qlcnic_83xx_config_default_opmode(adapter))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void
+qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (ahw->port_type == QLCNIC_XGBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
+ adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+
+ } else if (ahw->port_type == QLCNIC_GBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
+ }
+ adapter->num_txd = MAX_CMD_DESCRIPTORS;
+ adapter->max_rds_rings = MAX_RDS_RINGS;
+}
+
+static int
+qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter)
+{
+ int err = -EIO;
+
+ qlcnic_83xx_get_minidump_template(adapter);
+ if (qlcnic_83xx_get_port_info(adapter))
+ return err;
+
+ qlcnic_83xx_config_buff_descriptors(adapter);
+ adapter->ahw->msix_supported = !!use_msi_x;
+ adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+
+ dev_info(&adapter->pdev->dev, "HAL Version: %d\n",
+ adapter->ahw->fw_hal_version);
+
+ return 0;
+}
+
+/*
+ * qlcnic_83xx_clear_function_resources
+ *
+ * @adapter: adapter structure
+ *
+ * Clean up the function resources if the function was used before
+ */
+static void
+qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_cmd_args cmd;
+ u32 presence_mask, audit_mask;
+ int status;
+
+ presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
+ audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
+
+ if (IS_QLCNIC_83XX_USED(adapter, presence_mask, audit_mask)) {
+ qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
+ cmd.req.arg[1] = cpu_to_le32(0 | BIT_31);
+
+ status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to clean up the function resources\n");
+ }
+
+ qlcnic_free_mbx_args(&cmd);
+ }
+}
+
+/**
+ * qlcnic_83xx_init
+ *
+ * @adapter: adapter structure
+ *
+ * 83xx adapter specific initialization
+ *
+ * Returns: Success(0) or Failure(-EIO)
+ *
+ **/
+int
+qlcnic_83xx_init(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (qlcnic_83xx_check_hw_status(adapter))
+ return -EIO;
+
+ /* Initilaize 83xx mailbox spinlock */
+ spin_lock_init(&ahw->mbx_lock);
+
+ set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+ qlcnic_83xx_clear_function_resources(adapter);
+
+ if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
+ qlcnic_83xx_read_flash_mfg_id(adapter);
+
+ if (qlcnic_83xx_idc_init(adapter))
+ return -EIO;
+
+ /* Configure default, SR-IOV or Virtual NIC mode of operation */
+ if (qlcnic_83xx_configure_opmode(adapter))
+ return -EIO;
+
+ /* Perform operating mode specific initialization */
+ if (adapter->nic_ops->init_driver(adapter))
+ return -EIO;
+
+ INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
+
+ /* register for NIC IDC AEN Events */
+ qlcnic_83xx_register_nic_idc_func(adapter, 1);
+
+ /* Periodically monitor device status */
+ qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
+
+ return adapter->ahw->idc.err_code;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index b1f3a4a..4b885c4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -680,7 +680,9 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
cmd.req.arg[2] = LSD(nic_dma_t);
cmd.req.arg[3] = (func_id << 16 | nic_size);
err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err != QLCNIC_RCODE_SUCCESS) {
+ if (err == QLCNIC_RCODE_SUCCESS)
+ qlcnic_set_npar_data(adapter, nic_info, npar_info);
+ else {
dev_err(&adapter->pdev->dev,
"Failed to get nic info%d\n", err);
err = -EIO;
@@ -1043,8 +1045,8 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
err_ret:
dev_err(&adapter->pdev->dev,
- "Invalid args func_esw %d port %d rx_ctx %d\n",
- func_esw, port, rx_tx);
+ "Invalid arguments func_esw=%d port=%d rx_ctx=%d\n",
+ func_esw, port, rx_tx);
return -EIO;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index bf6b1db..fa9e25e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -871,7 +871,7 @@ static int qlcnic_set_channels(struct net_device *dev,
if (err)
return err;
- err = qlcnic_set_max_rss(adapter, channel->rx_count);
+ err = qlcnic_set_max_rss(adapter, channel->rx_count, 0);
netdev_info(dev, "allocated 0x%x sds rings\n",
adapter->max_sds_rings);
return err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 2d08234..958ad02 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -322,12 +322,13 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
u32 qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
{
+ int err;
u32 data;
if (QLCNIC_IS_82XX(adapter))
qlcnic_read_dump_reg(addr, adapter->ahw->pci_base0, &data);
else
- return -EIO;
+ data = qlcnic_83xx_rd_reg_indirect(adapter, addr, &err);
return data;
}
@@ -335,6 +336,8 @@ void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
{
if (QLCNIC_IS_82XX(adapter))
qlcnic_write_dump_reg(addr, adapter->ahw->pci_base0, data);
+ else
+ qlcnic_83xx_wrt_reg_indirect(adapter, addr, data);
}
void
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 9304e71..9d1962f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -35,7 +35,6 @@ char qlcnic_driver_name[] = "qlcnic";
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
-static struct workqueue_struct *qlcnic_wq;
static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0444);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
@@ -253,7 +252,7 @@ qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, struct net_device *netdev)
return 0;
}
-static int
+int
qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
int ring;
@@ -518,8 +517,9 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
/* subtract 2 as 2 vectors are required for
mail box and tx ring */
adapter->max_sds_rings = num_msix - 2;
- } else
+ } else {
adapter->max_sds_rings = num_msix;
+ }
dev_info(&pdev->dev, "using msi-x interrupts\n");
return err;
} else if (err > 0) {
@@ -579,9 +579,10 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
if (!num_intr)
num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
- if (adapter->ahw->msix_supported)
+ if (adapter->ahw->msix_supported) {
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
num_intr));
+ }
else
num_msix = 1;
@@ -670,8 +671,11 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
j++;
}
- for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
+ for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) {
adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
+ if (QLCNIC_IS_83XX(adapter))
+ qlcnic_enable_eswitch(adapter, i, 1);
+ }
kfree(pci_info);
return 0;
@@ -723,7 +727,7 @@ err_lock:
return ret;
}
-static void
+void
qlcnic_check_vf(struct qlcnic_adapter *adapter, const struct pci_device_id *ent)
{
void __iomem *priv_op;
@@ -1104,6 +1108,7 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
struct qlcnic_npar_info *npar;
struct qlcnic_info nic_info;
u8 pci_func;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
if (QLCNIC_IS_82XX(adapter))
if (!adapter->need_fw_reset)
@@ -1113,13 +1118,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
npar = &adapter->npars[i];
pci_func = npar->pci_func;
- err = adapter->ahw->hw_ops->get_nic_info(adapter,
- &nic_info, pci_func);
+ err = ahw->hw_ops->get_nic_info(adapter, &nic_info, pci_func);
if (err)
return err;
nic_info.min_tx_bw = npar->min_bw;
nic_info.max_tx_bw = npar->max_bw;
- err = adapter->ahw->hw_ops->set_nic_info(adapter, &nic_info);
+ err = ahw->hw_ops->set_nic_info(adapter, &nic_info);
if (err)
return err;
@@ -1176,6 +1180,8 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
qlcnic_dev_set_npar_ready(adapter);
+ if (QLCNIC_IS_83XX(adapter))
+ qlcnic_83xx_register_nic_idc_func(adapter, 1);
return err;
}
@@ -1261,6 +1267,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
if (QLCNIC_IS_82XX(adapter))
handler = qlcnic_tmp_intr;
+ else
+ handler = qlcnic_83xx_tmp_intr;
if (!QLCNIC_IS_MSI_FAMILY(adapter))
flags |= IRQF_SHARED;
@@ -1560,6 +1568,7 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
+ kfree(adapter->ahw->reset.buff);
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
@@ -1580,6 +1589,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
adapter->max_sds_rings = 1;
adapter->ahw->diag_test = test;
+ adapter->ahw->linkup = 0;
ret = qlcnic_attach(adapter);
if (ret) {
@@ -1605,6 +1615,8 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
if (QLCNIC_IS_82XX(adapter)) {
QLCNIC_ENABLE_INTR(adapter,
sds_ring->crb_intr_mask);
+ } else {
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
}
}
}
@@ -1620,7 +1632,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
}
/* Reset context in hardware only */
-static int
+int
qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -1788,6 +1800,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) {
ahw->hw_ops = &qlcnic_hw_ops;
ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
+ } else if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE834X) {
+ qlcnic_83xx_register_map(ahw);
+ } else {
+ goto err_out_free_hw_res;
}
err = qlcnic_setup_pci_map(pdev, ahw);
@@ -1807,6 +1823,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->pdev = pdev;
adapter->ahw = ahw;
+ adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic");
+ if (adapter->qlcnic_wq == NULL) {
+ dev_err(&pdev->dev, "Failed to create workqueue\n");
+ goto err_out_free_netdev;
+ }
+
if (qlcnic_alloc_adapter_resources(adapter))
goto err_out_free_netdev;
@@ -1836,6 +1858,19 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_hw;
adapter->flags |= QLCNIC_NEED_FLR;
+ } else if (QLCNIC_IS_83XX(adapter)) {
+ qlcnic_83xx_check_vf(adapter, ent);
+ adapter->portnum = adapter->ahw->pci_func;
+ err = qlcnic_83xx_init(adapter);
+ if (err) {
+ dev_err(&pdev->dev,
+ "%s: failed. Please Reboot\n", __func__);
+ goto err_out_free_hw;
+ }
+ } else {
+ dev_err(&pdev->dev,
+ "%s: failed. Please Reboot\n", __func__);
+ goto err_out_free_hw;
}
if (qlcnic_read_mac_addr(adapter))
@@ -1852,6 +1887,11 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_out_disable_msi;
+ if (QLCNIC_IS_83XX(adapter)) {
+ err = qlcnic_83xx_setup_mbx_intr(adapter);
+ if (err)
+ goto err_out_disable_msi;
+ }
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
if (err)
@@ -1883,6 +1923,11 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_out_disable_mbx_intr:
+ if (QLCNIC_IS_83XX(adapter)) {
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ qlcnic_83xx_config_intrpt(adapter, 0);
+ qlcnic_83xx_free_mbx_intr(adapter);
+ }
err_out_disable_msi:
qlcnic_teardown_intr(adapter);
@@ -1927,6 +1972,12 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
+ if (QLCNIC_IS_83XX(adapter)) {
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ qlcnic_83xx_config_intrpt(adapter, 0);
+ qlcnic_83xx_free_mbx_intr(adapter);
+ }
+
qlcnic_detach(adapter);
if (adapter->npars != NULL)
kfree(adapter->npars);
@@ -1953,6 +2004,10 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
+ if (adapter->qlcnic_wq) {
+ destroy_workqueue(adapter->qlcnic_wq);
+ adapter->qlcnic_wq = NULL;
+ }
qlcnic_free_adapter_resources(adapter);
kfree(ahw);
free_netdev(netdev);
@@ -2076,6 +2131,11 @@ static int qlcnic_close(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
__qlcnic_down(adapter, netdev);
+ if (QLCNIC_IS_83XX(adapter)) {
+ qlcnic_83xx_register_nic_idc_func(adapter, 0);
+ cancel_delayed_work_sync(&adapter->idc_aen_work);
+ }
+
return 0;
}
@@ -2680,7 +2740,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
qlcnic_gb_set_gb3_mask(gb_val);
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val);
dev_info(&adapter->pdev->dev,
- "Pause control frames disabled on all ports\n");
+ "Pause control frames disabled on all ports\n");
adapter->need_fw_reset = 1;
if (adapter->ahw->hw_ops->api_lock(adapter))
@@ -2721,7 +2781,7 @@ qlcnic_schedule_work(struct qlcnic_adapter *adapter,
return;
INIT_DELAYED_WORK(&adapter->fw_work, func);
- queue_delayed_work(qlcnic_wq, &adapter->fw_work,
+ queue_delayed_work(adapter->qlcnic_wq, &adapter->fw_work,
round_jiffies_relative(delay));
}
@@ -2934,6 +2994,17 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
adapter->msix_entries = NULL;
err = ahw->hw_ops->setup_intr(adapter, 0);
+ if (QLCNIC_IS_83XX(adapter)) {
+ err = qlcnic_83xx_setup_mbx_intr(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "failed to setup mbx interrupt\n");
+ qlcnic_clr_all_drv_state(adapter, 1);
+ clear_bit(__QLCNIC_AER, &adapter->state);
+ goto done;
+ }
+ }
+
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
if (err) {
@@ -2974,6 +3045,12 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
if (netif_running(netdev))
qlcnic_down(adapter, netdev);
+ if (QLCNIC_IS_83XX(adapter)) {
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ qlcnic_83xx_config_intrpt(adapter, 0);
+ qlcnic_83xx_free_mbx_intr(adapter);
+ }
+
qlcnic_detach(adapter);
qlcnic_teardown_intr(adapter);
@@ -3056,23 +3133,39 @@ int qlcnic_validate_max_rss(u8 max_hw, u8 val)
return 0;
}
-int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
+int
+qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
{
+ int err;
struct net_device *netdev = adapter->netdev;
- int err = 0;
-
- if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
- return -EBUSY;
+ rtnl_lock();
netif_device_detach(netdev);
if (netif_running(netdev))
__qlcnic_down(adapter, netdev);
+
+ if (QLCNIC_IS_83XX(adapter)) {
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ qlcnic_83xx_config_intrpt(adapter, 0);
+ qlcnic_83xx_free_mbx_intr(adapter);
+ }
+
qlcnic_detach(adapter);
qlcnic_teardown_intr(adapter);
err = adapter->ahw->hw_ops->setup_intr(adapter, data);
if (err)
- netdev_info(netdev, "failed setting max_rss; rss disabled\n");
+ dev_err(&adapter->pdev->dev,
+ "failed setting max_rss; rss disabled\n");
+
+ if (QLCNIC_IS_83XX(adapter)) {
+ err = qlcnic_83xx_setup_mbx_intr(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "failed to setup mbx interrupt\n");
+ goto done;
+ }
+ }
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
@@ -3083,17 +3176,19 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
goto done;
qlcnic_restore_indev_addr(netdev, NETDEV_UP);
}
+ err = len;
done:
netif_device_attach(netdev);
- clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ rtnl_unlock();
return err;
+
}
#ifdef CONFIG_INET
#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
-static void
+void
qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
struct net_device *dev, unsigned long event)
{
@@ -3255,12 +3350,6 @@ static int __init qlcnic_init_module(void)
printk(KERN_INFO "%s\n", qlcnic_driver_string);
- qlcnic_wq = create_singlethread_workqueue("qlcnic");
- if (qlcnic_wq == NULL) {
- printk(KERN_ERR "qlcnic: cannot create workqueue\n");
- return -ENOMEM;
- }
-
#ifdef CONFIG_INET
register_netdevice_notifier(&qlcnic_netdev_cb);
register_inetaddr_notifier(&qlcnic_inetaddr_cb);
@@ -3272,7 +3361,6 @@ static int __init qlcnic_init_module(void)
unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
- destroy_workqueue(qlcnic_wq);
}
return ret;
@@ -3282,14 +3370,12 @@ module_init(qlcnic_init_module);
static void __exit qlcnic_exit_module(void)
{
-
pci_unregister_driver(&qlcnic_driver);
#ifdef CONFIG_INET
unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
- destroy_workqueue(qlcnic_wq);
}
module_exit(qlcnic_exit_module);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index c77a016..9f743bf 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -645,6 +645,9 @@ qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
struct qlcnic_esw_statistics port_stats;
int ret;
+ if (QLCNIC_IS_83XX(adapter))
+ return QL_STATUS_UNSUPPORTED_CMD;
+
if (size != sizeof(struct qlcnic_esw_statistics))
return QL_STATUS_INVALID_PARAM;
@@ -675,6 +678,9 @@ qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
struct qlcnic_esw_statistics esw_stats;
int ret;
+ if (QLCNIC_IS_83XX(adapter))
+ return QL_STATUS_UNSUPPORTED_CMD;
+
if (size != sizeof(struct qlcnic_esw_statistics))
return QL_STATUS_INVALID_PARAM;
@@ -704,6 +710,9 @@ qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
int ret;
+ if (QLCNIC_IS_83XX(adapter))
+ return QL_STATUS_UNSUPPORTED_CMD;
+
if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
return QL_STATUS_INVALID_PARAM;
@@ -729,6 +738,9 @@ qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
int ret;
+ if (QLCNIC_IS_83XX(adapter))
+ return QL_STATUS_UNSUPPORTED_CMD;
+
if (offset >= QLCNIC_MAX_PCI_FUNC)
return QL_STATUS_INVALID_PARAM;
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 12/15] qlcnic: enable 83xx virtual NIC mode
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Enable 83xx virtual NIC mode
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 8 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 262 ++++++++++++++++++++
3 files changed, 270 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index 799325d..25b73f1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -7,4 +7,4 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o
qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
- qlcnic_83xx_init.o
+ qlcnic_83xx_init.o qlcnic_83xx_vnic.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 1bb9ae9..6e14662 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -826,6 +826,9 @@ qlcnic_83xx_idc_need_reset_state_handler(struct qlcnic_adapter *adapter)
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
set_bit(__QLCNIC_RESETTING, &adapter->state);
clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
+ if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
+ qlcnic_83xx_disable_vnic_mode(adapter, 1);
+
qlcnic_83xx_idc_detach_driver(adapter);
}
@@ -1861,7 +1864,10 @@ qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
if (ret == -EIO)
return -EIO;
- if (ret == QLC_83XX_DEFAULT_MODE) {
+ if (ret == QLC_83XX_VIRTUAL_NIC_MODE) {
+ if (qlcnic_83xx_config_vnic_opmode(adapter))
+ return -EIO;
+ } else if (ret == QLC_83XX_DEFAULT_MODE) {
if (qlcnic_83xx_config_default_opmode(adapter))
return -EIO;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
new file mode 100644
index 0000000..1b3b637
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -0,0 +1,262 @@
+#include "qlcnic.h"
+#include "qlcnic_hw.h"
+
+int
+qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
+{
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+ QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_OPER);
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+int
+qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (lock) {
+ if (qlcnic_83xx_lock_driver(adapter))
+ return -EBUSY;
+ }
+
+ QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
+
+ if (lock)
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_set_vnic_opmode
+ *
+ * @adapter: adapter structure
+ *
+ * Returns:
+ *
+ **/
+static int
+qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
+{
+ u8 id;
+ int i, ret = -EBUSY;
+ u32 data = QLCNIC_MGMT_FUNC;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (qlcnic_83xx_lock_driver(adapter))
+ return ret;
+
+ if (qlcnic_config_npars) {
+ for (i = 0; i < ahw->act_pci_func; i++) {
+ id = adapter->npars[i].pci_func;
+ if (id == ahw->pci_func)
+ continue;
+ data |= (qlcnic_config_npars &
+ QLC_83XX_SET_FUNC_OPMODE(0x3, id));
+ }
+ } else {
+ data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
+ data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) |
+ (QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC,
+ ahw->pci_func));
+ }
+ QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);
+
+ qlcnic_83xx_unlock_driver(adapter);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_config_vnic_buff_descriptors
+ *
+ * @adapter: adapter structure
+ *
+ * Returns:
+ *
+ **/
+static inline void
+qlcnic_83xx_config_vnic_buff_descriptors(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ if (ahw->port_type == QLCNIC_XGBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
+ adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+
+ } else if (ahw->port_type == QLCNIC_GBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
+ }
+ adapter->num_txd = MAX_CMD_DESCRIPTORS;
+ adapter->max_rds_rings = MAX_RDS_RINGS;
+}
+
+
+/**
+ * qlcnic_83xx_init_mgmt_vnic
+ *
+ * @adapter: adapter structure
+ * Management vNIC sets the operational mode of other vNIC's and
+ * configures embedded switch (ESWITCH).
+ * Returns:
+ *
+ **/
+static int
+qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
+{
+ int err = -EIO;
+
+ /*qlcnic_83xx_get_minidump_template(adapter);*/
+ if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) {
+ if (qlcnic_init_pci_info(adapter))
+ return err;
+
+ if (qlcnic_83xx_set_vnic_opmode(adapter))
+ return err;
+
+ if (qlcnic_set_default_offload_settings(adapter))
+ return err;
+ } else {
+ if (qlcnic_reset_npar_config(adapter))
+ return err;
+ }
+
+ if (qlcnic_83xx_get_port_info(adapter))
+ return err;
+
+ qlcnic_83xx_config_vnic_buff_descriptors(adapter);
+ adapter->ahw->msix_supported = !!use_msi_x;
+ adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+ qlcnic_83xx_enable_vnic_mode(adapter, 1);
+
+ dev_info(&adapter->pdev->dev, "HAL Version: %d, Management function\n",
+ adapter->ahw->fw_hal_version);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_init_privileged_vnic
+ *
+ * @adapter: adapter structure
+ *
+ * Returns:
+ *
+ **/
+static int
+qlcnic_83xx_init_privileged_vnic(struct qlcnic_adapter *adapter)
+{
+ int err = -EIO;
+
+ if (qlcnic_83xx_get_port_info(adapter))
+ return err;
+
+ qlcnic_83xx_config_vnic_buff_descriptors(adapter);
+ adapter->ahw->msix_supported = !!use_msi_x;
+ adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+
+ dev_info(&adapter->pdev->dev,
+ "HAL Version: %d, Privileged function\n",
+ adapter->ahw->fw_hal_version);
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_init_non_privileged_vnic
+ *
+ * @adapter: adapter structure
+ *
+ * Returns:
+ *
+ **/
+static int
+qlcnic_83xx_init_non_privileged_vnic(struct qlcnic_adapter *adapter)
+{
+ int err = -EIO;
+
+ qlcnic_83xx_get_fw_version(adapter);
+ if (qlcnic_set_eswitch_port_config(adapter))
+ return err;
+
+ if (qlcnic_83xx_get_port_info(adapter))
+ return err;
+
+ qlcnic_83xx_config_vnic_buff_descriptors(adapter);
+ adapter->ahw->msix_supported = !!use_msi_x;
+ adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+
+ dev_info(&adapter->pdev->dev, "HAL Version: %d, Virtual function\n",
+ adapter->ahw->fw_hal_version);
+
+ return 0;
+}
+
+/**
+ * qlcnic_83xx_vnic_opmode
+ *
+ * @adapter: adapter structure
+ * Identify virtual NIC operational modes.
+ *
+ * Returns:
+ *
+ **/
+int
+qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
+{
+ u32 op_mode, priv_level;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ ahw->hw_ops->get_func_no(adapter);
+
+ op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
+
+ if (op_mode == QLC_83XX_DEFAULT_OPMODE)
+ priv_level = QLCNIC_MGMT_FUNC;
+ else
+ priv_level = QLC_83XX_GET_FUNC_PRIVILEGE_LEVEL(op_mode,
+ ahw->pci_func);
+
+ if (priv_level == QLCNIC_NON_PRIV_FUNC) {
+ ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
+ adapter->ahw->idc.ready_state_entry_action =
+ qlcnic_83xx_idc_ready_state_entry_action;
+ adapter->nic_ops->init_driver =
+ qlcnic_83xx_init_non_privileged_vnic;
+ } else if (priv_level == QLCNIC_PRIV_FUNC) {
+ ahw->op_mode = QLCNIC_PRIV_FUNC;
+ adapter->ahw->idc.ready_state_entry_action =
+ qlcnic_83xx_idc_vnic_pf_ready_state_entry_action;
+ adapter->nic_ops->init_driver =
+ qlcnic_83xx_init_privileged_vnic;
+ } else if (priv_level == QLCNIC_MGMT_FUNC) {
+ ahw->op_mode = QLCNIC_MGMT_FUNC;
+ adapter->ahw->idc.ready_state_entry_action =
+ qlcnic_83xx_idc_ready_state_entry_action;
+ adapter->nic_ops->init_driver =
+ qlcnic_83xx_init_mgmt_vnic;
+ } else {
+ return -EIO;
+ }
+
+ if (ahw->capabilities & BIT_23)
+ adapter->flags |= QLCNIC_ESWITCH_ENABLED;
+ else
+ adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+
+ adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
+ adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
+
+ return 0;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 11/15] qlcnic: 83xx adpater ethtool
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
83xx ethtool interface routines
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 341 +++++++++++++++++++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 4 -
2 files changed, 325 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index fa9e25e..1f21c39 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -23,6 +23,10 @@ struct qlcnic_stats {
#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
+
+static const u32 qlcnic_fw_dump_level[] = {
+ 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
+
static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
{"xmit_called",
QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
@@ -78,13 +82,84 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx numbytes",
};
+static const char qlc_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
+ "ctx_tx_bytes",
+ "ctx_tx_pkts",
+ "ctx_tx_errors",
+ "ctx_tx_dropped_pkts",
+ "ctx_tx_num_buffers",
+};
+
+static const char qlc_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
+ "mac_tx_frames",
+ "mac_tx_bytes",
+ "mac_tx_mcast_pkts",
+ "mac_tx_bcast_pkts",
+ "mac_tx_pause_cnt",
+ "mac_tx_ctrl_pkt",
+ "mac_tx_lt_64b_pkts",
+ "mac_tx_lt_127b_pkts",
+ "mac_tx_lt_255b_pkts",
+ "mac_tx_lt_511b_pkts",
+ "mac_tx_lt_1023b_pkts",
+ "mac_tx_lt_1518b_pkts",
+ "mac_tx_gt_1518b_pkts",
+ "mac_rx_frames",
+ "mac_rx_bytes",
+ "mac_rx_mcast_pkts",
+ "mac_rx_bcast_pkts",
+ "mac_rx_pause_cnt",
+ "mac_rx_ctrl_pkt",
+ "mac_rx_lt_64b_pkts",
+ "mac_rx_lt_127b_pkts",
+ "mac_rx_lt_255b_pkts",
+ "mac_rx_lt_511b_pkts",
+ "mac_rx_lt_1023b_pkts",
+ "mac_rx_lt_1518b_pkts",
+ "mac_rx_gt_1518b_pkts",
+ "mac_rx_length_error",
+ "mac_rx_length_small",
+ "mac_rx_length_large",
+ "mac_rx_jabber",
+ "mac_rx_dropped",
+ "mac_crc_error",
+ "mac_align_error",
+};
+
+static const char qlc_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
+ "ctx_rx_bytes",
+ "ctx_rx_pkts",
+ "ctx_lro_pkt_cnt",
+ "ctx_ip_csum_error",
+ "ctx_rx_pkts_wo_ctx",
+ "ctx_rx_pkts_dropped_wo_sts",
+ "ctx_rx_osized_pkts",
+ "ctx_rx_pkts_dropped_wo_rds",
+ "ctx_rx_unexpected_mcast_pkts",
+ "ctx_invalid_mac_address",
+ "ctx_rx_rds_ring_prim_attemoted",
+ "ctx_rx_rds_ring_prim_success",
+ "ctx_num_lro_flows_added",
+ "ctx_num_lro_flows_removed",
+ "ctx_num_lro_flows_active",
+ "ctx_pkts_dropped_unknown",
+};
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
-#define QLCNIC_82XX_STATS QLCNIC_STATS_LEN
-#define QLCNIC_DEVICE_STATS_LEN(adapter) \
- ARRAY_SIZE(qlcnic_device_gstrings_stats)
+#define QLCNIC_83XX_STATS (ARRAY_SIZE(qlc_83xx_tx_stats_strings) \
+ + ARRAY_SIZE(qlc_83xx_mac_stats_strings) \
+ + ARRAY_SIZE(qlc_83xx_rx_stats_strings))
+#define QLCNIC_82XX_STATS (QLCNIC_STATS_LEN \
+ + ARRAY_SIZE(qlc_83xx_mac_stats_strings))
+#define QLCNIC_DEVICE_STATS_LEN(adapter) \
+ (QLCNIC_IS_83XX(adapter) ? \
+ QLCNIC_83XX_STATS :\
+ (ARRAY_SIZE(qlc_83xx_mac_stats_strings) \
+ + ARRAY_SIZE(qlcnic_device_gstrings_stats)))
+
+#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
@@ -131,9 +206,13 @@ static const u32 ext_diag_registers[] = {
static int qlcnic_get_regs_len(struct net_device *dev)
{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 len;
- len = sizeof(ext_diag_registers) + sizeof(diag_registers);
+ if (QLCNIC_IS_83XX(adapter))
+ len = qlcnic_83xx_get_regs_len(adapter);
+ else
+ len = sizeof(ext_diag_registers) + sizeof(diag_registers);
return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1;
}
@@ -189,8 +268,11 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else if (ahw->port_type == QLCNIC_XGBE) {
u32 val = 0;
- val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
-
+ if (QLCNIC_IS_83XX(adapter)) {
+ qlcnic_83xx_get_settings(adapter);
+ } else {
+ val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
+ }
if (val == QLCNIC_PORT_MODE_802_3_AP) {
ecmd->supported = SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_1000baseT_Full;
@@ -273,6 +355,13 @@ skip:
ecmd->port = PORT_TP;
}
break;
+ case QLCNIC_BRDTYPE_83XX_10G:
+ ecmd->autoneg = AUTONEG_DISABLE;
+ ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
+ ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP);
+ ecmd->port = PORT_FIBRE;
+ check_sfp_module = netif_running(dev) && ahw->has_link_events;
+ break;
default:
dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
ahw->board_type);
@@ -344,7 +433,10 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if (adapter->ahw->port_type != QLCNIC_GBE)
return -EOPNOTSUPP;
- ret = qlcnic_set_port_config(adapter, ecmd);
+ if (QLCNIC_IS_83XX(adapter))
+ ret = qlcnic_83xx_set_settings(adapter, ecmd);
+ else
+ ret = qlcnic_set_port_config(adapter, ecmd);
if (!ret)
return ret;
@@ -394,6 +486,8 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
if (QLCNIC_IS_82XX(adapter))
i = qlcnic_get_registers(adapter, regs_buff);
+ else
+ i = qlcnic_83xx_get_registers(adapter, regs_buff);
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;
@@ -422,6 +516,10 @@ static u32 qlcnic_test_link(struct net_device *dev)
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 val;
+ if (QLCNIC_IS_83XX(adapter)) {
+ val = qlcnic_83xx_test_link(adapter);
+ return (val & 1) ? 0 : 1;
+ }
val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err);
val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
return (val == XG_LINK_UP_P3P) ? 0 : 1;
@@ -435,6 +533,8 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
int offset;
int ret = -1;
+ if (QLCNIC_IS_83XX(adapter))
+ return 0;
if (eeprom->len == 0)
return -EINVAL;
@@ -523,6 +623,10 @@ qlcnic_get_pauseparam(struct net_device *netdev,
int port = adapter->ahw->physical_port;
__u32 val;
+ if (QLCNIC_IS_83XX(adapter)) {
+ qlcnic_83xx_get_pauseparam(adapter, pause);
+ return;
+ }
if (ahw->port_type == QLCNIC_GBE) {
if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
return;
@@ -569,6 +673,8 @@ qlcnic_set_pauseparam(struct net_device *netdev,
int err, port = adapter->ahw->physical_port;
__u32 val;
+ if (QLCNIC_IS_83XX(adapter))
+ return qlcnic_83xx_set_pauseparam(adapter, pause);
/* read mode */
if (ahw->port_type == QLCNIC_GBE) {
@@ -646,6 +752,8 @@ static int qlcnic_reg_test(struct net_device *dev)
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 data_read;
+ if (QLCNIC_IS_83XX(adapter))
+ return qlcnic_83xx_reg_test(adapter);
data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err);
if ((data_read & 0xffff) != adapter->pdev->vendor)
@@ -656,14 +764,26 @@ static int qlcnic_reg_test(struct net_device *dev)
static int qlcnic_eeprom_test(struct net_device *dev)
{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if (QLCNIC_IS_82XX(adapter))
return 0;
+
+ return qlcnic_83xx_flash_test(adapter);
}
static int qlcnic_get_sset_count(struct net_device *dev, int sset)
{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
switch (sset) {
case ETH_SS_TEST:
return QLCNIC_TEST_LEN;
+ case ETH_SS_STATS:
+ if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ QLCNIC_IS_83XX(adapter))
+ return QLCNIC_STATS_LEN +
+ QLCNIC_DEVICE_STATS_LEN(adapter);
+ return QLCNIC_82XX_STATS;
default:
return -EOPNOTSUPP;
}
@@ -671,7 +791,43 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
static int qlcnic_irq_test(struct net_device *netdev)
{
- return 0;
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ int max_sds_rings = adapter->max_sds_rings;
+ int ret;
+ struct qlcnic_cmd_args cmd;
+
+ if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EIO;
+
+ ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
+ if (ret)
+ goto clear_it;
+
+ adapter->ahw->diag_cnt = 0;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_INTRPT_TEST);
+
+ if (QLCNIC_IS_83XX(adapter)) {
+ ret = qlcnic_83xx_interrupt_test(adapter, &cmd);
+ } else {
+ cmd.req.arg[1] = cpu_to_le32(adapter->ahw->pci_func);
+ ret = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ }
+
+ if (ret)
+ goto done;
+
+ usleep_range(1000, 12000);
+ ret = !adapter->ahw->diag_cnt;
+
+done:
+ qlcnic_free_mbx_args(&cmd);
+ qlcnic_diag_free_res(netdev, max_sds_rings);
+
+clear_it:
+ adapter->max_sds_rings = max_sds_rings;
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ return ret;
}
#define QLCNIC_ILB_PKT_SIZE 64
@@ -724,7 +880,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
dev_kfree_skb_any(skb);
if (!ahw->diag_cnt)
- QLCDB(adapter, DRV,
+ netif_warn(adapter->ahw, pktdata, adapter->netdev,
"LB Test: packet #%d was not received\n", i + 1);
else
cnt++;
@@ -749,13 +905,17 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
int loop = 0;
int ret;
+ if (QLCNIC_IS_83XX(adapter))
+ goto skip_cap;
if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
- dev_info(&adapter->pdev->dev,
+ netdev_err(netdev,
"Firmware is not loopback test capable\n");
return -EOPNOTSUPP;
}
- QLCDB(adapter, DRV, "%s loopback test in progress\n",
- mode == QLCNIC_ILB_MODE ? "internal" : "external");
+skip_cap:
+ netif_info(adapter->ahw, drv, netdev,
+ "%s loopback test in progress\n",
+ mode == QLCNIC_ILB_MODE ? "internal" : "external");
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
dev_warn(&adapter->pdev->dev,
"Loopback test invalid for non privileged function\n");
@@ -774,12 +934,15 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
if (ret)
goto free_res;
+ if (QLCNIC_IS_83XX(adapter))
+ goto skip_fw_msg;
+
ahw->diag_cnt = 0;
do {
msleep(500);
ahw->hw_ops->process_lb_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
- dev_info(&adapter->pdev->dev,
+ netdev_err(netdev,
"No response for loopback configure request\n");
ret = -QLCNIC_FW_NOT_RESPOND;
goto free_res;
@@ -788,6 +951,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
goto free_res;
}
} while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
+skip_fw_msg:
/* allowing firmware to settle before running traffic */
msleep(2000);
ret = qlcnic_do_lb_test(adapter, mode);
@@ -835,15 +999,153 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
static void
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+ int index, i, num_stats;
switch (stringset) {
case ETH_SS_TEST:
memcpy(data, *qlcnic_gstrings_test,
QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
break;
+ case ETH_SS_STATS:
+ for (index = 0; index < QLCNIC_STATS_LEN; index++) {
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlcnic_gstrings_stats[index].stat_string,
+ ETH_GSTRING_LEN);
+ }
+ if (QLCNIC_IS_83XX(adapter)) {
+ num_stats = ARRAY_SIZE(qlc_83xx_tx_stats_strings);
+ for (i = 0; i < num_stats; i++, index++)
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlc_83xx_tx_stats_strings[i],
+ ETH_GSTRING_LEN);
+ num_stats = ARRAY_SIZE(qlc_83xx_mac_stats_strings);
+ for (i = 0; i < num_stats; i++, index++)
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlc_83xx_mac_stats_strings[i],
+ ETH_GSTRING_LEN);
+ num_stats = ARRAY_SIZE(qlc_83xx_rx_stats_strings);
+ for (i = 0; i < num_stats; i++, index++)
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlc_83xx_rx_stats_strings[i],
+ ETH_GSTRING_LEN);
+ return;
+ } else {
+ num_stats = ARRAY_SIZE(qlc_83xx_mac_stats_strings);
+ for (i = 0; i < num_stats; i++, index++)
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlc_83xx_mac_stats_strings[i],
+ ETH_GSTRING_LEN);
+ }
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
+ for (i = 0; i < num_stats; index++, i++) {
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlcnic_device_gstrings_stats[i],
+ ETH_GSTRING_LEN);
+ }
+ }
+}
+
+static void
+qlcnic_fill_stats(u64 *data, void *stats, int type)
+{
+ if (type == QLCNIC_MAC_STATS) {
+ struct qlcnic_mac_statistics *mac_stats =
+ (struct qlcnic_mac_statistics *)stats;
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_FCS_error);
+ *data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
+ } else if (type == QLCNIC_ESW_STATS) {
+ struct __qlcnic_esw_statistics *esw_stats =
+ (struct __qlcnic_esw_statistics *)stats;
+ *data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->errors);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
+ *data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
}
}
+static void
+qlcnic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+ struct qlcnic_esw_statistics port_stats;
+ struct qlcnic_mac_statistics mac_stats;
+ int index, ret, length;
+
+ length = QLCNIC_STATS_LEN;
+ for (index = 0; index < length; index++) {
+ char *p =
+ (char *)adapter +
+ qlcnic_gstrings_stats[index].stat_offset;
+ *data++ = (qlcnic_gstrings_stats[index].sizeof_stat ==
+ sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p));
+ }
+
+ if (QLCNIC_IS_83XX(adapter)) {
+ return qlcnic_83xx_get_stats(adapter, stats, data);
+ } else {
+ /* Retrieve MAC statistics from firmware */
+ memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
+ qlcnic_get_mac_stats(adapter, &mac_stats);
+ qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
+ }
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+
+ memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
+ ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
+ QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
+ if (ret)
+ return;
+
+ qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
+
+ ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
+ QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
+ if (ret)
+ return;
+
+ qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS);
+}
+
static void qlcnic_get_channels(struct net_device *dev,
struct ethtool_channels *channel)
{
@@ -884,6 +1186,8 @@ qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 wol_cfg;
+ if (QLCNIC_IS_83XX(adapter))
+ return;
wol->supported = 0;
wol->wolopts = 0;
@@ -903,6 +1207,8 @@ qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 wol_cfg;
+ if (QLCNIC_IS_83XX(adapter))
+ return -EOPNOTSUPP;
if (wol->wolopts & ~WAKE_MAGIC)
return -EOPNOTSUPP;
@@ -928,6 +1234,8 @@ static int qlcnic_set_led(struct net_device *dev,
int max_sds_rings = adapter->max_sds_rings;
int err = -EIO, active = 1;
+ if (QLCNIC_IS_83XX(adapter))
+ return -EOPNOTSUPP;
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(dev, "LED test not supported for non "
"privilege function\n");
@@ -1196,8 +1504,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
netdev_err(netdev, "FW dump not supported\n");
return -ENOTSUPP;
}
- for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
- if (val->flag == FW_DUMP_LEVELS[i]) {
+ for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
+ if (val->flag == qlcnic_fw_dump_level[i]) {
fw_dump->tmpl_hdr->drv_cap_mask =
val->flag;
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
@@ -1205,7 +1513,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return 0;
}
}
- netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag);
+ netdev_err(netdev, "Invalid dump level: 0x%x\n", val->flag);
return -EINVAL;
}
return 0;
@@ -1230,6 +1538,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.set_wol = qlcnic_set_wol,
.self_test = qlcnic_diag_test,
.get_strings = qlcnic_get_strings,
+ .get_ethtool_stats = qlcnic_get_ethtool_stats,
.get_sset_count = qlcnic_get_sset_count,
.get_coalesce = qlcnic_get_intr_coalesce,
.set_coalesce = qlcnic_set_intr_coalesce,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 72615d1..8264722 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -727,10 +727,6 @@ struct qlcnic_legacy_intr_set {
#define FLASH_ROM_WINDOW 0x42110030
#define FLASH_ROM_DATA 0x42150000
-
-static const u32 FW_DUMP_LEVELS[] = {
- 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
-
#define QLCNIC_FW_DUMP_REG1 0x00130060
#define QLCNIC_FW_DUMP_REG2 0x001e0000
#define QLCNIC_FLASH_SEM2_LK 0x0013C010
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 14/15] qlcnic: restructure file layout of combined driver
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
File layout of common driver for 82xx and 83xx
qlcnic_82xx_hw.c, qlcnic_82xx_init.c - 82xx adapter specific files
qlcnic_83xx_hw.c, qlcnic_83xx_init.c - 83xx adapter specicic files
qlcnic_io.c - common file for 82xx and 83xx data path routines
qlcnic_ethtool.c - common file for 82xx and 83xx ethtool interface
qlcnic_sysfs.c - common file for 82xx and 83xx sysfs interface
qlcnic_main.c - common main file for 82xx and 83xx
qlcnic_83xx_vnic.c - 83xx virtual NIC routines
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_82xx_init.c | 1297 ++++++++++++++++++++
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 477 +-------
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 44 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 4 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 34 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 14 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1297 --------------------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 439 +++++++
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 5 +-
10 files changed, 1806 insertions(+), 1807 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_init.c
delete mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index fe61793..50e0e6f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_QLCNIC) := qlcnic.o
-qlcnic-y := qlcnic_82xx_hw.o qlcnic_main.o qlcnic_init.o \
+qlcnic-y := qlcnic_82xx_hw.o qlcnic_main.o qlcnic_82xx_init.o \
qlcnic_ethtool.o qlcnic_io.o \
qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
qlcnic_83xx_init.o qlcnic_83xx_vnic.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_init.c
new file mode 100644
index 0000000..52020ce
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_init.c
@@ -0,0 +1,1297 @@
+/*
+ * QLogic qlcnic NIC Driver
+ * Copyright (c) 2009-2010 QLogic Corporation
+ *
+ * See LICENSE.qlcnic for copyright and licensing details.
+ */
+
+#include "qlcnic.h"
+#include "qlcnic_hw.h"
+
+struct crb_addr_pair {
+ u32 addr;
+ u32 data;
+};
+
+#define QLCNIC_MAX_CRB_XFORM 60
+static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
+
+#define crb_addr_transform(name) \
+ (crb_addr_xform[QLCNIC_HW_PX_MAP_CRB_##name] = \
+ QLCNIC_HW_CRB_HUB_AGT_ADR_##name << 20)
+
+#define QLCNIC_ADDR_ERROR (0xffffffff)
+
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
+
+static void crb_addr_transform_setup(void)
+{
+ crb_addr_transform(XDMA);
+ crb_addr_transform(TIMR);
+ crb_addr_transform(SRE);
+ crb_addr_transform(SQN3);
+ crb_addr_transform(SQN2);
+ crb_addr_transform(SQN1);
+ crb_addr_transform(SQN0);
+ crb_addr_transform(SQS3);
+ crb_addr_transform(SQS2);
+ crb_addr_transform(SQS1);
+ crb_addr_transform(SQS0);
+ crb_addr_transform(RPMX7);
+ crb_addr_transform(RPMX6);
+ crb_addr_transform(RPMX5);
+ crb_addr_transform(RPMX4);
+ crb_addr_transform(RPMX3);
+ crb_addr_transform(RPMX2);
+ crb_addr_transform(RPMX1);
+ crb_addr_transform(RPMX0);
+ crb_addr_transform(ROMUSB);
+ crb_addr_transform(SN);
+ crb_addr_transform(QMN);
+ crb_addr_transform(QMS);
+ crb_addr_transform(PGNI);
+ crb_addr_transform(PGND);
+ crb_addr_transform(PGN3);
+ crb_addr_transform(PGN2);
+ crb_addr_transform(PGN1);
+ crb_addr_transform(PGN0);
+ crb_addr_transform(PGSI);
+ crb_addr_transform(PGSD);
+ crb_addr_transform(PGS3);
+ crb_addr_transform(PGS2);
+ crb_addr_transform(PGS1);
+ crb_addr_transform(PGS0);
+ crb_addr_transform(PS);
+ crb_addr_transform(PH);
+ crb_addr_transform(NIU);
+ crb_addr_transform(I2Q);
+ crb_addr_transform(EG);
+ crb_addr_transform(MN);
+ crb_addr_transform(MS);
+ crb_addr_transform(CAS2);
+ crb_addr_transform(CAS1);
+ crb_addr_transform(CAS0);
+ crb_addr_transform(CAM);
+ crb_addr_transform(C2C1);
+ crb_addr_transform(C2C0);
+ crb_addr_transform(SMB);
+ crb_addr_transform(OCM0);
+ crb_addr_transform(I2C0);
+}
+
+void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_rx_buffer *rx_buf;
+ int i, ring;
+
+ recv_ctx = adapter->recv_ctx;
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ for (i = 0; i < rds_ring->num_desc; ++i) {
+ rx_buf = &(rds_ring->rx_buf_arr[i]);
+ if (rx_buf->skb == NULL)
+ continue;
+
+ pci_unmap_single(adapter->pdev,
+ rx_buf->dma,
+ rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+
+ dev_kfree_skb_any(rx_buf->skb);
+ }
+ }
+}
+
+void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_rx_buffer *rx_buf;
+ int i, ring;
+
+ recv_ctx = adapter->recv_ctx;
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ INIT_LIST_HEAD(&rds_ring->free_list);
+
+ rx_buf = rds_ring->rx_buf_arr;
+ for (i = 0; i < rds_ring->num_desc; i++) {
+ list_add_tail(&rx_buf->list,
+ &rds_ring->free_list);
+ rx_buf++;
+ }
+ }
+}
+
+void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_cmd_buffer *cmd_buf;
+ struct qlcnic_skb_frag *buffrag;
+ int i, j;
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+ cmd_buf = tx_ring->cmd_buf_arr;
+ for (i = 0; i < tx_ring->num_desc; i++) {
+ buffrag = cmd_buf->frag_array;
+ if (buffrag->dma) {
+ pci_unmap_single(adapter->pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ for (j = 0; j < cmd_buf->frag_count; j++) {
+ buffrag++;
+ if (buffrag->dma) {
+ pci_unmap_page(adapter->pdev, buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ }
+ if (cmd_buf->skb) {
+ dev_kfree_skb_any(cmd_buf->skb);
+ cmd_buf->skb = NULL;
+ }
+ cmd_buf++;
+ }
+}
+
+void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int ring;
+
+ recv_ctx = adapter->recv_ctx;
+
+ if (recv_ctx->rds_rings == NULL)
+ return;
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ vfree(rds_ring->rx_buf_arr);
+ rds_ring->rx_buf_arr = NULL;
+ }
+ kfree(recv_ctx->rds_rings);
+}
+
+int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_rx_buffer *rx_buf;
+ int ring, i, size;
+
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ recv_ctx = adapter->recv_ctx;
+
+ size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring);
+ rds_ring = kzalloc(size, GFP_KERNEL);
+ if (rds_ring == NULL) {
+ dev_err(&netdev->dev, "failed to allocate rds ring struct\n");
+ goto err_out;
+ }
+ recv_ctx->rds_rings = rds_ring;
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ switch (ring) {
+ case RCV_RING_NORMAL:
+ rds_ring->num_desc = adapter->num_rxd;
+ rds_ring->dma_size = QLCNIC_P3P_RX_BUF_MAX_LEN;
+ rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
+ break;
+
+ case RCV_RING_JUMBO:
+ rds_ring->num_desc = adapter->num_jumbo_rxd;
+ rds_ring->dma_size =
+ QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
+
+ if (ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
+
+ rds_ring->skb_size =
+ rds_ring->dma_size + NET_IP_ALIGN;
+ break;
+ }
+ rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
+ vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
+ if (rds_ring->rx_buf_arr == NULL) {
+ dev_err(&netdev->dev,
+ "Failed to allocate rx buffer ring %d\n", ring);
+ goto err_out;
+ }
+ memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
+ INIT_LIST_HEAD(&rds_ring->free_list);
+ /*
+ * Now go through all of them, set reference handles
+ * and put them in the queues.
+ */
+ rx_buf = rds_ring->rx_buf_arr;
+ for (i = 0; i < rds_ring->num_desc; i++) {
+ list_add_tail(&rx_buf->list,
+ &rds_ring->free_list);
+ rx_buf->ref_handle = i;
+ rx_buf++;
+ }
+ spin_lock_init(&rds_ring->lock);
+ }
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ sds_ring->irq = adapter->msix_entries[ring].vector;
+ sds_ring->adapter = adapter;
+ sds_ring->num_desc = adapter->num_rxd;
+
+ for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
+ INIT_LIST_HEAD(&sds_ring->free_list[i]);
+ }
+
+ return 0;
+
+err_out:
+ qlcnic_free_sw_resources(adapter);
+ return -ENOMEM;
+}
+
+/*
+ * Utility to translate from internal Phantom CRB address
+ * to external PCI CRB address.
+ */
+static u32 qlcnic_decode_crb_addr(u32 addr)
+{
+ int i;
+ u32 base_addr, offset, pci_base;
+
+ crb_addr_transform_setup();
+
+ pci_base = QLCNIC_ADDR_ERROR;
+ base_addr = addr & 0xfff00000;
+ offset = addr & 0x000fffff;
+
+ for (i = 0; i < QLCNIC_MAX_CRB_XFORM; i++) {
+ if (crb_addr_xform[i] == base_addr) {
+ pci_base = i << 20;
+ break;
+ }
+ }
+ if (pci_base == QLCNIC_ADDR_ERROR)
+ return pci_base;
+ else
+ return pci_base + offset;
+}
+
+#define QLCNIC_MAX_ROM_WAIT_USEC 100
+
+static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter)
+{
+ long timeout = 0;
+ long done = 0;
+ int err;
+
+ cond_resched();
+
+ while (done == 0) {
+ done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS, &err);
+ done &= 2;
+ if (++timeout >= QLCNIC_MAX_ROM_WAIT_USEC) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout reached waiting for rom done");
+ return -EIO;
+ }
+ udelay(1);
+ }
+ return 0;
+}
+
+static int do_rom_fast_read(struct qlcnic_adapter *adapter,
+ u32 addr, u32 *valp)
+{
+ int err;
+
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr);
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 3);
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+ if (qlcnic_wait_rom_done(adapter)) {
+ dev_err(&adapter->pdev->dev, "Error waiting for rom done\n");
+ return -EIO;
+ }
+ /* reset abyte_cnt and dummy_byte_cnt */
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 0);
+ udelay(10);
+ QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+
+ *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA, &err);
+ return 0;
+}
+
+static int do_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
+ u8 *bytes, size_t size)
+{
+ int addridx;
+ int ret = 0;
+
+ for (addridx = addr; addridx < (addr + size); addridx += 4) {
+ int v;
+ ret = do_rom_fast_read(adapter, addridx, &v);
+ if (ret != 0)
+ break;
+ *(__le32 *)bytes = cpu_to_le32(v);
+ bytes += 4;
+ }
+
+ return ret;
+}
+
+int
+qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
+ u8 *bytes, size_t size)
+{
+ int ret;
+
+ ret = qlcnic_rom_lock(adapter);
+ if (ret < 0)
+ return ret;
+
+ ret = do_rom_fast_read_words(adapter, addr, bytes, size);
+
+ qlcnic_rom_unlock(adapter);
+ return ret;
+}
+
+int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp)
+{
+ int ret;
+
+ if (qlcnic_rom_lock(adapter) != 0)
+ return -EIO;
+
+ ret = do_rom_fast_read(adapter, addr, valp);
+ qlcnic_rom_unlock(adapter);
+ return ret;
+}
+
+int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
+{
+ int addr, val, err;
+ int i, n, init_delay;
+ struct crb_addr_pair *buf;
+ unsigned offset;
+ u32 off;
+ struct pci_dev *pdev = adapter->pdev;
+
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, 0);
+ QLCWR(adapter, QLCNIC_RCVPEG_STATE, 0);
+
+ /* Halt all the indiviual PEGs and other blocks */
+ /* disable all I2Q */
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x10, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x14, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x18, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x1c, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x20, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x24, 0x0);
+
+ /* disable all niu interrupts */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x40, 0xff);
+ /* disable xge rx/tx */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x70000, 0x00);
+ /* disable xg1 rx/tx */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x80000, 0x00);
+ /* disable sideband mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x90000, 0x00);
+ /* disable ap0 mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0xa0000, 0x00);
+ /* disable ap1 mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0xb0000, 0x00);
+
+ /* halt sre */
+ val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000, &err);
+ QLCWR32(adapter, QLCNIC_CRB_SRE + 0x1000, val & (~(0x1)));
+
+ /* halt epg */
+ QLCWR32(adapter, QLCNIC_CRB_EPG + 0x1300, 0x1);
+
+ /* halt timers */
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x0, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x8, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x10, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x18, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x100, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x200, 0x0);
+ /* halt pegs */
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
+ usleep_range(15000, 20000);
+
+ qlcnic_rom_unlock(adapter);
+ /* big hammer don't reset CAM block on reset */
+ QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
+
+ /* Init HW CRB block */
+ if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
+ qlcnic_rom_fast_read(adapter, 4, &n) != 0) {
+ dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n);
+ return -EIO;
+ }
+ offset = n & 0xffffU;
+ n = (n >> 16) & 0xffffU;
+
+ if (n >= 1024) {
+ dev_err(&pdev->dev, "QLOGIC card flash not initialized.\n");
+ return -EIO;
+ }
+
+ buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+ if (buf == NULL) {
+ dev_err(&pdev->dev, "Unable to calloc memory for rom read.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+ qlcnic_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
+ kfree(buf);
+ return -EIO;
+ }
+
+ buf[i].addr = addr;
+ buf[i].data = val;
+ }
+
+ for (i = 0; i < n; i++) {
+
+ off = qlcnic_decode_crb_addr(buf[i].addr);
+ if (off == QLCNIC_ADDR_ERROR) {
+ dev_err(&pdev->dev, "CRB init value out of range %x\n",
+ buf[i].addr);
+ continue;
+ }
+ off += QLCNIC_PCI_CRBSPACE;
+
+ if (off & 1)
+ continue;
+
+ /* skipping cold reboot MAGIC */
+ if (off == QLCNIC_CAM_RAM(0x1fc))
+ continue;
+ if (off == (QLCNIC_CRB_I2C0 + 0x1c))
+ continue;
+ if (off == (ROMUSB_GLB + 0xbc)) /* do not reset PCI */
+ continue;
+ if (off == (ROMUSB_GLB + 0xa8))
+ continue;
+ if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
+ continue;
+ if ((off & 0x0ff00000) == QLCNIC_CRB_DDR_NET)
+ continue;
+ /* skip the function enable register */
+ if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION))
+ continue;
+ if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION2))
+ continue;
+ if ((off & 0x0ff00000) == QLCNIC_CRB_SMB)
+ continue;
+
+ init_delay = 1;
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == QLCNIC_ROMUSB_GLB_SW_RESET)
+ init_delay = 1000;
+
+ QLCWR32(adapter, off, buf[i].data);
+
+ msleep(init_delay);
+ }
+ kfree(buf);
+
+ /* Initialize protocol process engine */
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0xc, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
+ usleep_range(1000, 2000);
+
+ QLCWR(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
+ QLCWR(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
+
+ return 0;
+}
+
+static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
+
+ do {
+ val = QLCRD(adapter, QLCNIC_CMDPEG_STATE);
+
+ switch (val) {
+ case PHAN_INITIALIZE_COMPLETE:
+ case PHAN_INITIALIZE_ACK:
+ return 0;
+ case PHAN_INITIALIZE_FAILED:
+ goto out_err;
+ default:
+ break;
+ }
+
+ msleep(QLCNIC_CMDPEG_CHECK_DELAY);
+
+ } while (--retries);
+
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+ dev_err(&adapter->pdev->dev,
+ "Command Peg not ready, state: 0x%x.\n", val);
+ return -EIO;
+}
+
+static int
+qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
+
+ do {
+ val = QLCRD(adapter, QLCNIC_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(QLCNIC_RCVPEG_CHECK_DELAY);
+
+ } while (--retries);
+
+ if (!retries) {
+ dev_err(&adapter->pdev->dev,
+ "RX Peg not ready, state: 0x%x.\n", val);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
+{
+ int err;
+
+ err = qlcnic_cmd_peg_ready(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_receive_peg_ready(adapter);
+ if (err)
+ return err;
+
+ QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+ return err;
+}
+
+int
+qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
+
+ int timeo;
+ u32 val;
+
+ val = QLCRD(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
+ val = QLC_DEV_GET_DRV(val, adapter->portnum);
+ if ((val & 0x3) != QLCNIC_TYPE_NIC) {
+ dev_err(&adapter->pdev->dev,
+ "Not an Ethernet NIC func=%u\n", val);
+ return -EIO;
+ }
+ adapter->ahw->physical_port = (val >> 2);
+ if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
+ timeo = QLCNIC_INIT_TIMEOUT_SECS;
+
+ adapter->dev_init_timeo = timeo;
+
+ if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo))
+ timeo = QLCNIC_RESET_TIMEOUT_SECS;
+
+ adapter->reset_ack_timeo = timeo;
+
+ return 0;
+}
+
+static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
+ struct qlcnic_flt_entry *region_entry)
+{
+ struct qlcnic_flt_header flt_hdr;
+ struct qlcnic_flt_entry *flt_entry;
+ int i = 0, ret;
+ u32 entry_size;
+
+ memset(region_entry, 0, sizeof(struct qlcnic_flt_entry));
+ ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION,
+ (u8 *)&flt_hdr,
+ sizeof(struct qlcnic_flt_header));
+ if (ret) {
+ dev_warn(&adapter->pdev->dev,
+ "error reading flash layout header\n");
+ return -EIO;
+ }
+
+ entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
+ flt_entry = vmalloc(entry_size);
+ if (flt_entry == NULL) {
+ dev_err(&adapter->pdev->dev, "error allocating memory\n");
+ return -EIO;
+ }
+ memset(flt_entry, 0, entry_size);
+
+ ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
+ sizeof(struct qlcnic_flt_header),
+ (u8 *)flt_entry, entry_size);
+ if (ret) {
+ dev_warn(&adapter->pdev->dev,
+ "error reading flash layout entries\n");
+ goto err_out;
+ }
+
+ while (i < (entry_size/sizeof(struct qlcnic_flt_entry))) {
+ if (flt_entry[i].region == region)
+ break;
+ i++;
+ }
+ if (i >= (entry_size/sizeof(struct qlcnic_flt_entry))) {
+ dev_warn(&adapter->pdev->dev,
+ "region=%x not found in %d regions\n", region, i);
+ ret = -EIO;
+ goto err_out;
+ }
+ memcpy(region_entry, &flt_entry[i], sizeof(struct qlcnic_flt_entry));
+
+err_out:
+ vfree(flt_entry);
+ return ret;
+}
+
+int
+qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_flt_entry fw_entry;
+ u32 ver = -1, min_ver;
+ int ret;
+
+ if (adapter->ahw->revision_id == QLCNIC_P3P_C0)
+ ret = qlcnic_get_flt_entry(adapter, QLCNIC_C0_FW_IMAGE_REGION,
+ &fw_entry);
+ else
+ ret = qlcnic_get_flt_entry(adapter, QLCNIC_B0_FW_IMAGE_REGION,
+ &fw_entry);
+
+ if (!ret)
+ /* 0-4:-signature, 4-8:-fw version */
+ qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
+ (int *)&ver);
+ else
+ qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET,
+ (int *)&ver);
+
+ ver = QLCNIC_DECODE_VERSION(ver);
+ min_ver = QLCNIC_MIN_FW_VERSION;
+
+ if (ver < min_ver) {
+ dev_err(&adapter->pdev->dev,
+ "firmware version %d.%d.%d unsupported."
+ "Min supported version %d.%d.%d\n",
+ _major(ver), _minor(ver), _build(ver),
+ _major(min_ver), _minor(min_ver), _build(min_ver));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_has_mn(struct qlcnic_adapter *adapter)
+{
+ int err;
+ u32 capability;
+ capability = 0;
+
+ capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY, &err);
+ if (capability & QLCNIC_PEG_TUNE_MN_PRESENT)
+ return 1;
+
+ return 0;
+}
+
+static
+struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
+{
+ u32 i;
+ struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
+ __le32 entries = cpu_to_le32(directory->num_entries);
+
+ for (i = 0; i < entries; i++) {
+
+ __le32 offs = cpu_to_le32(directory->findex) +
+ (i * cpu_to_le32(directory->entry_size));
+ __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
+
+ if (tab_type == section)
+ return (struct uni_table_desc *) &unirom[offs];
+ }
+
+ return NULL;
+}
+
+#define FILEHEADER_SIZE (14 * 4)
+
+static int
+qlcnic_validate_header(struct qlcnic_adapter *adapter)
+{
+ const u8 *unirom = adapter->fw->data;
+ struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
+ __le32 fw_file_size = adapter->fw->size;
+ __le32 entries;
+ __le32 entry_size;
+ __le32 tab_size;
+
+ if (fw_file_size < FILEHEADER_SIZE)
+ return -EINVAL;
+
+ entries = cpu_to_le32(directory->num_entries);
+ entry_size = cpu_to_le32(directory->entry_size);
+ tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
+
+ if (fw_file_size < tab_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int
+qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
+{
+ struct uni_table_desc *tab_desc;
+ struct uni_data_desc *descr;
+ const u8 *unirom = adapter->fw->data;
+ int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
+ QLCNIC_UNI_BOOTLD_IDX_OFF));
+ __le32 offs;
+ __le32 tab_size;
+ __le32 data_size;
+
+ tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
+
+ if (!tab_desc)
+ return -EINVAL;
+
+ tab_size = cpu_to_le32(tab_desc->findex) +
+ (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+
+ if (adapter->fw->size < tab_size)
+ return -EINVAL;
+
+ offs = cpu_to_le32(tab_desc->findex) +
+ (cpu_to_le32(tab_desc->entry_size) * (idx));
+ descr = (struct uni_data_desc *)&unirom[offs];
+
+ data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+
+ if (adapter->fw->size < data_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int
+qlcnic_validate_fw(struct qlcnic_adapter *adapter)
+{
+ struct uni_table_desc *tab_desc;
+ struct uni_data_desc *descr;
+ const u8 *unirom = adapter->fw->data;
+ int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
+ QLCNIC_UNI_FIRMWARE_IDX_OFF));
+ __le32 offs;
+ __le32 tab_size;
+ __le32 data_size;
+
+ tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
+
+ if (!tab_desc)
+ return -EINVAL;
+
+ tab_size = cpu_to_le32(tab_desc->findex) +
+ (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+
+ if (adapter->fw->size < tab_size)
+ return -EINVAL;
+
+ offs = cpu_to_le32(tab_desc->findex) +
+ (cpu_to_le32(tab_desc->entry_size) * (idx));
+ descr = (struct uni_data_desc *)&unirom[offs];
+ data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+
+ if (adapter->fw->size < data_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int
+qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
+{
+ struct uni_table_desc *ptab_descr;
+ const u8 *unirom = adapter->fw->data;
+ int mn_present = qlcnic_has_mn(adapter);
+ __le32 entries;
+ __le32 entry_size;
+ __le32 tab_size;
+ u32 i;
+
+ ptab_descr = qlcnic_get_table_desc(unirom,
+ QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
+ if (!ptab_descr)
+ return -EINVAL;
+
+ entries = cpu_to_le32(ptab_descr->num_entries);
+ entry_size = cpu_to_le32(ptab_descr->entry_size);
+ tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
+
+ if (adapter->fw->size < tab_size)
+ return -EINVAL;
+
+nomn:
+ for (i = 0; i < entries; i++) {
+
+ __le32 flags, file_chiprev, offs;
+ u8 chiprev = adapter->ahw->revision_id;
+ u32 flagbit;
+
+ offs = cpu_to_le32(ptab_descr->findex) +
+ (i * cpu_to_le32(ptab_descr->entry_size));
+ flags = cpu_to_le32(*((int *)&unirom[offs] +
+ QLCNIC_UNI_FLAGS_OFF));
+ file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
+ QLCNIC_UNI_CHIP_REV_OFF));
+
+ flagbit = mn_present ? 1 : 2;
+
+ if ((chiprev == file_chiprev) &&
+ ((1ULL << flagbit) & flags)) {
+ adapter->file_prd_off = offs;
+ return 0;
+ }
+ }
+ if (mn_present) {
+ mn_present = 0;
+ goto nomn;
+ }
+ return -EINVAL;
+}
+
+static int
+qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter)
+{
+ if (qlcnic_validate_header(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "unified image: header validation failed\n");
+ return -EINVAL;
+ }
+
+ if (qlcnic_validate_product_offs(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "unified image: product validation failed\n");
+ return -EINVAL;
+ }
+
+ if (qlcnic_validate_bootld(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "unified image: bootld validation failed\n");
+ return -EINVAL;
+ }
+
+ if (qlcnic_validate_fw(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "unified image: firmware validation failed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static
+struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
+ u32 section, u32 idx_offset)
+{
+ const u8 *unirom = adapter->fw->data;
+ int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
+ idx_offset));
+ struct uni_table_desc *tab_desc;
+ __le32 offs;
+
+ tab_desc = qlcnic_get_table_desc(unirom, section);
+
+ if (tab_desc == NULL)
+ return NULL;
+
+ offs = cpu_to_le32(tab_desc->findex) +
+ (cpu_to_le32(tab_desc->entry_size) * idx);
+
+ return (struct uni_data_desc *)&unirom[offs];
+}
+
+static u8 *
+qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
+{
+ u32 offs = QLCNIC_BOOTLD_START;
+
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
+ QLCNIC_UNI_DIR_SECT_BOOTLD,
+ QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
+
+ return (u8 *)&adapter->fw->data[offs];
+}
+
+static u8 *
+qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
+{
+ u32 offs = QLCNIC_IMAGE_START;
+
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
+ QLCNIC_UNI_DIR_SECT_FW,
+ QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
+
+ return (u8 *)&adapter->fw->data[offs];
+}
+
+static __le32
+qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
+{
+ if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+ return cpu_to_le32((qlcnic_get_data_desc(adapter,
+ QLCNIC_UNI_DIR_SECT_FW,
+ QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
+ else
+ return cpu_to_le32(
+ *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]);
+}
+
+static __le32
+qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
+{
+ struct uni_data_desc *fw_data_desc;
+ const struct firmware *fw = adapter->fw;
+ __le32 major, minor, sub;
+ const u8 *ver_str;
+ int i, ret;
+
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
+ return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
+
+ fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+ QLCNIC_UNI_FIRMWARE_IDX_OFF);
+ ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
+ cpu_to_le32(fw_data_desc->size) - 17;
+
+ for (i = 0; i < 12; i++) {
+ if (!strncmp(&ver_str[i], "REV=", 4)) {
+ ret = sscanf(&ver_str[i+4], "%u.%u.%u ",
+ &major, &minor, &sub);
+ if (ret != 3)
+ return 0;
+ else
+ return major + (minor << 8) + (sub << 16);
+ }
+ }
+
+ return 0;
+}
+
+static __le32
+qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
+{
+ const struct firmware *fw = adapter->fw;
+ __le32 bios_ver, prd_off = adapter->file_prd_off;
+
+ if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
+ return cpu_to_le32(
+ *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
+
+ bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
+ + QLCNIC_UNI_BIOS_VERSION_OFF));
+
+ return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
+}
+
+static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
+{
+ if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID))
+ dev_info(&adapter->pdev->dev, "Resetting rom_lock\n");
+
+ qlcnic_pcie_sem_unlock(adapter, 2);
+}
+
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
+{
+ u32 heartbeat, ret = -EIO;
+ int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
+
+ adapter->heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+
+ do {
+ msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
+ heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != adapter->heartbeat) {
+ ret = QLCNIC_RCODE_SUCCESS;
+ break;
+ }
+ } while (--retries);
+
+ return ret;
+}
+
+int
+qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
+{
+ if ((adapter->flags & QLCNIC_FW_HANG) ||
+ qlcnic_check_fw_hearbeat(adapter)) {
+ qlcnic_rom_lock_recovery(adapter);
+ return 1;
+ }
+
+ if (adapter->need_fw_reset)
+ return 1;
+
+ if (adapter->fw)
+ return 1;
+
+ return 0;
+}
+
+static char *fw_name[] = {
+ QLCNIC_UNIFIED_ROMIMAGE_NAME,
+ QLCNIC_FLASH_ROMIMAGE_NAME,
+};
+
+int
+qlcnic_load_firmware(struct qlcnic_adapter *adapter)
+{
+ u64 *ptr64;
+ u32 i, flashaddr, size;
+ const struct firmware *fw = adapter->fw;
+ struct pci_dev *pdev = adapter->pdev;
+
+ dev_info(&pdev->dev, "loading firmware from %s\n",
+ fw_name[adapter->ahw->fw_type]);
+
+ if (fw) {
+ __le64 data;
+
+ size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
+
+ ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter);
+ flashaddr = QLCNIC_BOOTLD_START;
+
+ for (i = 0; i < size; i++) {
+ data = cpu_to_le64(ptr64[i]);
+
+ if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
+ return -EIO;
+
+ flashaddr += 8;
+ }
+
+ size = (__force u32)qlcnic_get_fw_size(adapter) / 8;
+
+ ptr64 = (u64 *)qlcnic_get_fw_offs(adapter);
+ flashaddr = QLCNIC_IMAGE_START;
+
+ for (i = 0; i < size; i++) {
+ data = cpu_to_le64(ptr64[i]);
+
+ if (qlcnic_pci_mem_write_2M(adapter,
+ flashaddr, data))
+ return -EIO;
+
+ flashaddr += 8;
+ }
+
+ size = (__force u32)qlcnic_get_fw_size(adapter) % 8;
+ if (size) {
+ data = cpu_to_le64(ptr64[i]);
+
+ if (qlcnic_pci_mem_write_2M(adapter,
+ flashaddr, data))
+ return -EIO;
+ }
+
+ } else {
+ u64 data;
+ u32 hi, lo;
+ int ret;
+ struct qlcnic_flt_entry bootld_entry;
+
+ ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION,
+ &bootld_entry);
+ if (!ret) {
+ size = bootld_entry.size / 8;
+ flashaddr = bootld_entry.start_addr;
+ } else {
+ size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
+ flashaddr = QLCNIC_BOOTLD_START;
+ dev_info(&pdev->dev,
+ "using legacy method to get flash fw region");
+ }
+
+ for (i = 0; i < size; i++) {
+ if (qlcnic_rom_fast_read(adapter,
+ flashaddr, (int *)&lo) != 0)
+ return -EIO;
+ if (qlcnic_rom_fast_read(adapter,
+ flashaddr + 4, (int *)&hi) != 0)
+ return -EIO;
+
+ data = (((u64)hi << 32) | lo);
+
+ if (qlcnic_pci_mem_write_2M(adapter,
+ flashaddr, data))
+ return -EIO;
+
+ flashaddr += 8;
+ }
+ }
+ usleep_range(1000, 2000);
+
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x18, 0x1020);
+ QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0x80001e);
+ return 0;
+}
+
+static int
+qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
+{
+ __le32 val;
+ u32 ver, bios, min_size;
+ struct pci_dev *pdev = adapter->pdev;
+ const struct firmware *fw = adapter->fw;
+ u8 fw_type = adapter->ahw->fw_type;
+
+ if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
+ if (qlcnic_validate_unified_romimage(adapter))
+ return -EINVAL;
+
+ min_size = QLCNIC_UNI_FW_MIN_SIZE;
+ } else {
+ val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
+ if ((__force u32)val != QLCNIC_BDINFO_MAGIC)
+ return -EINVAL;
+
+ min_size = QLCNIC_FW_MIN_SIZE;
+ }
+
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ val = qlcnic_get_fw_version(adapter);
+ ver = QLCNIC_DECODE_VERSION(val);
+
+ if (ver < QLCNIC_MIN_FW_VERSION) {
+ dev_err(&pdev->dev,
+ "%s: firmware version %d.%d.%d unsupported\n",
+ fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
+ return -EINVAL;
+ }
+
+ val = qlcnic_get_bios_version(adapter);
+ qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
+ if ((__force u32)val != bios) {
+ dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+ fw_name[fw_type]);
+ return -EINVAL;
+ }
+
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID, QLCNIC_BDINFO_MAGIC);
+ return 0;
+}
+
+static void
+qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
+{
+ u8 fw_type;
+
+ switch (adapter->ahw->fw_type) {
+ case QLCNIC_UNKNOWN_ROMIMAGE:
+ fw_type = QLCNIC_UNIFIED_ROMIMAGE;
+ break;
+
+ case QLCNIC_UNIFIED_ROMIMAGE:
+ default:
+ fw_type = QLCNIC_FLASH_ROMIMAGE;
+ break;
+ }
+
+ adapter->ahw->fw_type = fw_type;
+}
+
+
+
+void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int rc;
+
+ adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
+
+next:
+ qlcnic_get_next_fwtype(adapter);
+
+ if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
+ adapter->fw = NULL;
+ } else {
+ rc = request_firmware(&adapter->fw,
+ fw_name[adapter->ahw->fw_type], &pdev->dev);
+ if (rc != 0)
+ goto next;
+
+ rc = qlcnic_validate_firmware(adapter);
+ if (rc != 0) {
+ release_firmware(adapter->fw);
+ usleep_range(1000, 2000);
+ goto next;
+ }
+ }
+}
+
+
+void
+qlcnic_release_firmware(struct qlcnic_adapter *adapter)
+{
+ if (adapter->fw)
+ release_firmware(adapter->fw);
+ adapter->fw = NULL;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 118b2b2..08c2aa8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -300,9 +300,9 @@ qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
return -ENOMEM;
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
/* MSI-X enablement failed, use legacy interrupt */
- adapter->tgt_status_reg = ahw->pci_base0 + QLCNIC_83XX_INTX_PTR;
- adapter->tgt_mask_reg = ahw->pci_base0 + QLCNIC_83XX_INTX_MASK;
- adapter->isr_int_vec = ahw->pci_base0 + QLCNIC_83XX_INTX_TRGR;
+ adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
+ adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
+ adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
adapter->msix_entries[0].vector = adapter->pdev->irq;
dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
}
@@ -349,10 +349,10 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
intr_val = readl(adapter->tgt_status_reg);
- if (!QLCNIC_83XX_VALID_INTX_BIT31(intr_val))
+ if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
return IRQ_NONE;
- if (QLCNIC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
+ if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
dev_info(&adapter->pdev->dev,
"Interrupt for wrong func: 0x%x\n", intr_val);
return IRQ_NONE;
@@ -363,10 +363,10 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
/* Legacy Workaround for A0 & B0 */
do {
intr_val = readl(adapter->tgt_status_reg);
- if (QLCNIC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
+ if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
break;
retries++;
- } while (QLCNIC_83XX_VALID_INTX_BIT30(intr_val) &&
+ } while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
(retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
if (retries == QLC_83XX_LEGACY_INTX_MAX_RETRY) {
@@ -630,445 +630,6 @@ qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
}
-static struct qlcnic_rx_buffer *
-qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- u8 ring, u64 sts_data[])
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum;
- u16 vid = 0xffff;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_83xx_hndl(sts_data[0]);
- if (unlikely(index >= rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- length = qlcnic_83xx_pktln(sts_data[0]);
- cksum = qlcnic_83xx_csum_status(sts_data[1]);
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
- if (!skb)
- return buffer;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
-
- napi_gro_receive(&sds_ring->napi, skb);
-
- adapter->stats.rx_pkts++;
- adapter->stats.rxbytes += length;
-
- return buffer;
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- u8 ring, u64 sts_data[])
-{
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_rx_buffer *buffer;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- struct iphdr *iph;
- struct ipv6hdr *ipv6h;
- struct tcphdr *th;
- bool push;
- int l2_hdr_offset, l4_hdr_offset;
- int index;
- u16 lro_length, length, data_offset;
- u16 vid = 0xffff;
-
- if (unlikely(ring > adapter->max_rds_rings))
- return NULL;
-
- rds_ring = &recv_ctx->rds_rings[ring];
-
- index = qlcnic_83xx_hndl(sts_data[0]);
- if (unlikely(index > rds_ring->num_desc))
- return NULL;
-
- buffer = &rds_ring->rx_buf_arr[index];
-
- lro_length = qlcnic_83xx_lro_pktln(sts_data[0]);
- l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]);
- l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]);
- push = qlcnic_83xx_is_psh_bit(sts_data[1]);
-
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
- if (!skb)
- return buffer;
- if (qlcnic_83xx_is_tstamp(sts_data[1]))
- data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
- else
- data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
-
- skb_put(skb, lro_length + data_offset);
-
- skb_pull(skb, l2_hdr_offset);
-
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
- adapter->stats.rxdropped++;
- dev_kfree_skb(skb);
- return buffer;
- }
-
- skb->protocol = eth_type_trans(skb, netdev);
-
- if (htons(skb->protocol) == ETH_P_IPV6) {
- ipv6h = (struct ipv6hdr *)skb->data;
- th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
-
- length = (th->doff << 2) + lro_length;
- ipv6h->payload_len = htons(length);
- } else {
- iph = (struct iphdr *)skb->data;
- th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-
- length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
- iph->tot_len = htons(length);
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
- }
-
-
- th->psh = push;
-
- length = skb->len;
-
- if (vid != 0xffff)
- __vlan_hwaccel_put_tag(skb, vid);
- netif_receive_skb(skb);
-
- adapter->stats.lro_pkts++;
- adapter->stats.lrobytes += length;
- return buffer;
-}
-
-static int
-qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct list_head *cur;
- struct status_desc *desc;
- struct qlcnic_rx_buffer *rxbuf = NULL;
- u64 sts_data[2];
-
- int count = 0, opcode;
- u8 ring;
- u32 consumer = sds_ring->consumer;
-
- while (count < max) {
- desc = &sds_ring->desc_head[consumer];
- sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
- opcode = qlcnic_83xx_opcode(sts_data[1]);
- if (!opcode)
- break;
- sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
- ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
-
- switch (opcode) {
- case QLCNIC_83XX_REG_DESC:
- rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring,
- ring, sts_data);
- break;
- case QLCNIC_83XX_LRO_DESC:
- rxbuf = qlcnic_83xx_process_lro(adapter, sds_ring,
- ring, sts_data);
- break;
- default:
- dev_info(&adapter->pdev->dev,
- "Unkonwn opcode: 0x%x\n", opcode);
- goto skip;
- }
-
- if (likely(rxbuf))
- list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
- else
- adapter->stats.null_rxbuf++;
-
-skip:
- desc = &sds_ring->desc_head[consumer];
- /* Reset the descriptor */
- desc->status_desc_data[1] = 0;
- consumer = get_next_index(consumer, sds_ring->num_desc);
- count++;
- }
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- struct qlcnic_host_rds_ring *rds_ring =
- &adapter->recv_ctx->rds_rings[ring];
-
- if (!list_empty(&sds_ring->free_list[ring])) {
- list_for_each(cur, &sds_ring->free_list[ring]) {
- rxbuf = list_entry(cur,
- struct qlcnic_rx_buffer, list);
- qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
- }
- spin_lock(&rds_ring->lock);
- list_splice_tail_init(&sds_ring->free_list[ring],
- &rds_ring->free_list);
- spin_unlock(&rds_ring->lock);
- }
-
- qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
- }
-
- if (count) {
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
- }
- return count;
-}
-
-static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
-
- /* there is only 1 tx ring in this path */
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
- int tx_complete;
- int work_done;
-
- if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
- qlcnic_83xx_process_aen(adapter);
-
- tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
-
- work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
-
- if ((work_done < budget) && tx_complete) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_83xx_enable_intr(adapter, sds_ring);
- }
-
- return work_done;
-}
-
-static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_tx_ring *tx_ring =
- container_of(napi, struct qlcnic_host_tx_ring, napi);
-
- struct qlcnic_adapter *adapter = tx_ring->adapter;
- int work_done;
-
- work_done = qlcnic_process_cmd_ring(adapter, tx_ring,
- QLCNIC_TX_POLL_BUDGET);
-
- if (work_done) {
- napi_complete(&tx_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
- qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
- }
-
- return work_done;
-}
-
-static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
-{
- struct qlcnic_host_sds_ring *sds_ring =
- container_of(napi, struct qlcnic_host_sds_ring, napi);
-
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- int work_done;
-
- work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
-
- if (work_done < budget) {
- napi_complete(&sds_ring->napi);
- if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_83xx_enable_intr(adapter, sds_ring);
- }
-
- return work_done;
-}
-
-void
-qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
- return;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- napi_enable(&sds_ring->napi);
- qlcnic_83xx_enable_intr(adapter, sds_ring);
- }
-
- if (adapter->flags & QLCNIC_MSIX_ENABLED) {
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- tx_ring = &adapter->tx_ring[ring];
- napi_enable(&tx_ring->napi);
- qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
- }
- }
-}
-
-void
-qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct qlcnic_host_tx_ring *tx_ring;
-
- if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
- return;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- writel(1, sds_ring->crb_intr_mask);
- napi_synchronize(&sds_ring->napi);
- napi_disable(&sds_ring->napi);
- }
-
- if (adapter->flags & QLCNIC_MSIX_ENABLED) {
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- tx_ring = &adapter->tx_ring[ring];
- qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
- napi_synchronize(&tx_ring->napi);
- napi_disable(&tx_ring->napi);
- }
- }
-}
-
-int
-qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
-{
- int ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
- return -ENOMEM;
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- if (adapter->flags & QLCNIC_MSIX_ENABLED)
- netif_napi_add(netdev, &sds_ring->napi,
- qlcnic_83xx_rx_poll, QLCNIC_NETDEV_WEIGHT * 2);
- else
- netif_napi_add(netdev, &sds_ring->napi,
- qlcnic_83xx_poll,
- QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
- }
-
- if (qlcnic_alloc_tx_rings(adapter, netdev)) {
- qlcnic_free_sds_rings(recv_ctx);
- return -ENOMEM;
- }
-
- if (adapter->flags & QLCNIC_MSIX_ENABLED) {
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- tx_ring = &adapter->tx_ring[ring];
- netif_napi_add(netdev, &tx_ring->napi,
- qlcnic_83xx_msix_tx_poll,
- QLCNIC_NETDEV_WEIGHT);
- }
- }
-
- return 0;
-}
-
-void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
- struct qlcnic_host_sds_ring *sds_ring,
- int ring, u64 sts_data[])
-{
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- struct sk_buff *skb;
- struct qlcnic_host_rds_ring *rds_ring;
- int index, length, cksum;
-
- if (unlikely(ring >= adapter->max_rds_rings))
- return;
-
- rds_ring = &recv_ctx->rds_rings[ring];
- index = qlcnic_83xx_hndl(sts_data[0]);
- if (unlikely(index >= rds_ring->num_desc))
- return;
-
- length = qlcnic_83xx_pktln(sts_data[0]);
- cksum = qlcnic_83xx_csum_status(sts_data[0]);
- skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
- if (!skb)
- return;
-
- if (length > rds_ring->skb_size)
- skb_put(skb, rds_ring->skb_size);
- else
- skb_put(skb, length);
-
- if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
- adapter->ahw->diag_cnt++;
- else
- dump_skb(skb, adapter);
-
- dev_kfree_skb_any(skb);
- return;
-}
-
-void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
- struct qlcnic_adapter *adapter = sds_ring->adapter;
- struct status_desc *desc;
- u64 sts_data[2];
- int ring, opcode;
-
- u32 consumer = sds_ring->consumer;
-
- desc = &sds_ring->desc_head[consumer];
- sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
- sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
- opcode = qlcnic_83xx_opcode(sts_data[1]);
- if (!opcode)
- return;
-
- ring = QLCNIC_FETCH_RING_ID(qlcnic_83xx_hndl(sts_data[0]));
- qlcnic_83xx_process_rcv_diag(adapter, sds_ring, ring, sts_data);
-
- desc = &sds_ring->desc_head[consumer];
- desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
- consumer = get_next_index(consumer, sds_ring->num_desc);
-
- sds_ring->consumer = consumer;
- writel(consumer, sds_ring->crb_sts_consumer);
-}
-
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
{
int status;
@@ -1215,7 +776,7 @@ qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
}
total_regs = cmd->rsp.num;
switch (type) {
- case QLCNIC_83XX_STAT_MAC:
+ case QLC_83XX_STAT_MAC:
/* fill in MAC tx counters */
for (k = 2; k < 28; k += 2)
data = qlcnic_83xx_copy_stats(cmd, data, k);
@@ -1228,7 +789,7 @@ qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
for (k += 6; k < 80; k += 2)
data = qlcnic_83xx_copy_stats(cmd, data, k);
break;
- case QLCNIC_83XX_STAT_RX:
+ case QLC_83XX_STAT_RX:
for (k = 2; k < 8; k += 2)
data = qlcnic_83xx_copy_stats(cmd, data, k);
/* skip 8 bytes of reserved data */
@@ -1238,7 +799,7 @@ qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
for (k += 2; k < total_regs; k += 2)
data = qlcnic_83xx_copy_stats(cmd, data, k);
break;
- case QLCNIC_83XX_STAT_TX:
+ case QLC_83XX_STAT_TX:
for (k = 2; k < 10; k += 2)
data = qlcnic_83xx_copy_stats(cmd, data, k);
/* skip 8 bytes of reserved data */
@@ -1265,9 +826,9 @@ qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter,
if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
cmd.req.arg[1] = cpu_to_le32(BIT_1 |
(adapter->tx_ring->ctx_id << 16));
- cmd.rsp.num = QLCNIC_83XX_TX_STAT_REGS;
+ cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
- QLCNIC_83XX_STAT_TX, &ret);
+ QLC_83XX_STAT_TX, &ret);
if (ret) {
dev_info(&adapter->pdev->dev,
"Error getting MAC stats\n");
@@ -1275,10 +836,10 @@ qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter,
}
/* Get MAC stats */
cmd.req.arg[1] = cpu_to_le32(BIT_2 | (adapter->portnum << 16));
- cmd.rsp.num = QLCNIC_83XX_MAC_STAT_REGS;
+ cmd.rsp.num = QLC_83XX_MAC_STAT_REGS;
memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
- QLCNIC_83XX_STAT_MAC, &ret);
+ QLC_83XX_STAT_MAC, &ret);
if (ret) {
dev_info(&adapter->pdev->dev,
"Error getting Rx stats\n");
@@ -1287,10 +848,10 @@ qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter,
/* Get Rx stats */
cmd.req.arg[1] =
cpu_to_le32(adapter->recv_ctx->context_id << 16);
- cmd.rsp.num = QLCNIC_83XX_RX_STAT_REGS;
+ cmd.rsp.num = QLC_83XX_RX_STAT_REGS;
memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
- QLCNIC_83XX_STAT_RX, &ret);
+ QLC_83XX_STAT_RX, &ret);
if (ret)
dev_info(&adapter->pdev->dev,
"Error in getting Tx stats\n");
@@ -1964,15 +1525,15 @@ void qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 val, u32 beacon)
mbreg4 = cmd.rsp.arg[4];
}
/* Set LED Configuration */
- mbx_in = (LSW(QLCNIC_83XX_LED_CONFIG) << 16) |
- LSW(QLCNIC_83XX_LED_CONFIG);
+ mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
+ LSW(QLC_83XX_LED_CONFIG);
adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
QLCNIC_CMD_SET_LED_CONFIG);
cmd.req.arg[1] = cpu_to_le32(mbx_in);
cmd.req.arg[2] = cpu_to_le32(mbx_in);
cmd.req.arg[3] = cpu_to_le32(mbx_in);
if (beacon)
- cmd.req.arg[4] = QLCNIC_83XX_ENABLE_BEACON;
+ cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
status = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
if (status)
dev_info(&adapter->pdev->dev, "Set led config failed.\n");
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index c725b07..ed4f548 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -5,7 +5,7 @@
#include <linux/etherdevice.h>
#include "qlcnic_hw.h"
-#define IS_QLCNIC_83XX_USED(a, b, c) \
+#define IS_QLC_83XX_USED(a, b, c) \
(((1 << a->portnum) & b) || ((c >> 6) & 0x1))
/* Directly mapped registers */
@@ -19,9 +19,9 @@
#define QLC_83XX_LINK_SPEED(f) (0x36E0+(((f) >> 2) * 4))
#define QLC_83XX_LINK_SPEED_FACTOR 10
#define QLC_83xx_FUNC_VAL(v, f) ((v) & (1 << (f * 4)))
-#define QLCNIC_83XX_INTX_PTR 0x38C0
-#define QLCNIC_83XX_INTX_TRGR 0x38C4
-#define QLCNIC_83XX_INTX_MASK 0x38C8
+#define QLC_83XX_INTX_PTR 0x38C0
+#define QLC_83XX_INTX_TRGR 0x38C4
+#define QLC_83XX_INTX_MASK 0x38C8
/* Indirectly mapped registers */
#define QLC_83XX_FLASH_SPI_STATUS 0x2808E010
@@ -138,20 +138,20 @@
#define qlcnic_83xx_has_vlan_tag(sts) \
(((sts) >> 47) & 1)
-#define QLCNIC_83XX_VALID_INTX_BIT30(val) \
+#define QLC_83XX_VALID_INTX_BIT30(val) \
((val) & BIT_30)
-#define QLCNIC_83XX_VALID_INTX_BIT31(val) \
+#define QLC_83XX_VALID_INTX_BIT31(val) \
((val) & BIT_31)
-#define QLCNIC_83XX_INTX_FUNC(val) \
+#define QLC_83XX_INTX_FUNC(val) \
((val) & 0xFF)
#define QLC_83XX_LEGACY_INTX_MAX_RETRY 100
#define QLC_83XX_LEGACY_INTX_DELAY 4
-#define QLCNIC_83XX_REG_DESC 1
-#define QLCNIC_83XX_LRO_DESC 2
-#define QLCNIC_83XX_CTRL_DESC 3
+#define QLC_83XX_REG_DESC 1
+#define QLC_83XX_LRO_DESC 2
+#define QLC_83XX_CTRL_DESC 3
#define QLCNIC_FW_83XX_CAPABILITY_TSO BIT_6
@@ -390,26 +390,26 @@ struct qlcnic_83xx_idc {
#define QLC_83XX_CFG_LOOPBACK_EXT (4 << 1) /* External Loopback Mode */
/* LED configuration settings */
-#define QLCNIC_83XX_ENABLE_BEACON 0xe
-#define QLCNIC_83XX_LED_RATE 0xff
-#define QLCNIC_83XX_LED_ACT (1 << 10)
-#define QLCNIC_83XX_LED_MOD (0 << 13)
-#define QLCNIC_83XX_LED_CONFIG (QLCNIC_83XX_LED_RATE | QLCNIC_83XX_LED_ACT |\
- QLCNIC_83XX_LED_MOD)
+#define QLC_83XX_ENABLE_BEACON 0xe
+#define QLC_83XX_LED_RATE 0xff
+#define QLC_83XX_LED_ACT (1 << 10)
+#define QLC_83XX_LED_MOD (0 << 13)
+#define QLC_83XX_LED_CONFIG (QLC_83XX_LED_RATE | QLC_83XX_LED_ACT |\
+ QLC_83XX_LED_MOD)
#define QLC_83XX_10M_LINK 1
#define QLC_83XX_100M_LINK 2
#define QLC_83XX_1G_LINK 3
#define QLC_83XX_10G_LINK 4
-#define QLCNIC_83XX_STAT_TX 3
-#define QLCNIC_83XX_STAT_RX 2
+#define QLC_83XX_STAT_TX 3
+#define QLC_83XX_STAT_RX 2
-#define QLCNIC_83XX_STAT_MAC 1
+#define QLC_83XX_STAT_MAC 1
-#define QLCNIC_83XX_TX_STAT_REGS 14
-#define QLCNIC_83XX_RX_STAT_REGS 40
-#define QLCNIC_83XX_MAC_STAT_REGS 80
+#define QLC_83XX_TX_STAT_REGS 14
+#define QLC_83XX_RX_STAT_REGS 40
+#define QLC_83XX_MAC_STAT_REGS 80
#define QLC_83XX_GET_FUNC_PRIVILEGE_LEVEL(VAL, FN) (0x3 & ((VAL) >> (FN * 2)))
#define QLC_83XX_SET_FUNC_OPMODE(VAL, FN) ((VAL) << (FN * 2))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index ffd1028..a6eef3c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -18,7 +18,7 @@ static const char * const qlcnic_83xx_idc_states[] = {
};
/* IDC Device States */
-enum qlc_83xx_states {
+enum qlcnic_83xx_states {
QLC_83XX_IDC_DEV_UNKNOWN,
QLC_83XX_IDC_DEV_COLD,
QLC_83XX_IDC_DEV_INIT,
@@ -1946,7 +1946,7 @@ qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);
audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
- if (IS_QLCNIC_83XX_USED(adapter, presence_mask, audit_mask)) {
+ if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) {
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
cmd.req.arg[1] = cpu_to_le32(0 | BIT_31);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 1f21c39..4a72b93 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -82,7 +82,7 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx numbytes",
};
-static const char qlc_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
+static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
"ctx_tx_bytes",
"ctx_tx_pkts",
"ctx_tx_errors",
@@ -90,7 +90,7 @@ static const char qlc_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
"ctx_tx_num_buffers",
};
-static const char qlc_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
+static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
"mac_tx_frames",
"mac_tx_bytes",
"mac_tx_mcast_pkts",
@@ -126,7 +126,7 @@ static const char qlc_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
"mac_align_error",
};
-static const char qlc_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
+static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
"ctx_rx_bytes",
"ctx_rx_pkts",
"ctx_lro_pkt_cnt",
@@ -146,17 +146,17 @@ static const char qlc_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
};
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
-#define QLCNIC_83XX_STATS (ARRAY_SIZE(qlc_83xx_tx_stats_strings) \
- + ARRAY_SIZE(qlc_83xx_mac_stats_strings) \
- + ARRAY_SIZE(qlc_83xx_rx_stats_strings))
+#define QLC_83XX_STATS (ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) \
+ + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) \
+ + ARRAY_SIZE(qlcnic_83xx_rx_stats_strings))
#define QLCNIC_82XX_STATS (QLCNIC_STATS_LEN \
- + ARRAY_SIZE(qlc_83xx_mac_stats_strings))
+ + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings))
#define QLCNIC_DEVICE_STATS_LEN(adapter) \
(QLCNIC_IS_83XX(adapter) ? \
- QLCNIC_83XX_STATS :\
- (ARRAY_SIZE(qlc_83xx_mac_stats_strings) \
+ QLC_83XX_STATS :\
+ (ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) \
+ ARRAY_SIZE(qlcnic_device_gstrings_stats)))
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
@@ -1014,27 +1014,27 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
ETH_GSTRING_LEN);
}
if (QLCNIC_IS_83XX(adapter)) {
- num_stats = ARRAY_SIZE(qlc_83xx_tx_stats_strings);
+ num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
for (i = 0; i < num_stats; i++, index++)
memcpy(data + index * ETH_GSTRING_LEN,
- qlc_83xx_tx_stats_strings[i],
+ qlcnic_83xx_tx_stats_strings[i],
ETH_GSTRING_LEN);
- num_stats = ARRAY_SIZE(qlc_83xx_mac_stats_strings);
+ num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
for (i = 0; i < num_stats; i++, index++)
memcpy(data + index * ETH_GSTRING_LEN,
- qlc_83xx_mac_stats_strings[i],
+ qlcnic_83xx_mac_stats_strings[i],
ETH_GSTRING_LEN);
- num_stats = ARRAY_SIZE(qlc_83xx_rx_stats_strings);
+ num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
for (i = 0; i < num_stats; i++, index++)
memcpy(data + index * ETH_GSTRING_LEN,
- qlc_83xx_rx_stats_strings[i],
+ qlcnic_83xx_rx_stats_strings[i],
ETH_GSTRING_LEN);
return;
} else {
- num_stats = ARRAY_SIZE(qlc_83xx_mac_stats_strings);
+ num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
for (i = 0; i < num_stats; i++, index++)
memcpy(data + index * ETH_GSTRING_LEN,
- qlc_83xx_mac_stats_strings[i],
+ qlcnic_83xx_mac_stats_strings[i],
ETH_GSTRING_LEN);
}
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index ece5825..5f013fa 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -509,9 +509,6 @@ enum {
#define QLCNIC_MS_RDDATA_ULO 0x410000B8
#define QLCNIC_MS_RDDATA_UHI 0x410000BC
-static const u32 QLCNIC_MS_READ_DATA[] = {
- 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, };
-
#define QLC_TA_WRITE_ENABLE (TA_CTL_ENABLE | TA_CTL_WRITE)
#define QLC_TA_WRITE_START (TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE)
#define QLC_TA_START_ENABLE (TA_CTL_START | TA_CTL_ENABLE)
@@ -723,15 +720,14 @@ struct qlcnic_legacy_intr_set {
#define QLCNIC_MAX_PCI_FUNC 8
#define QLCNIC_MAX_VLAN_FILTERS 64
-/* FW dump defines */
#define FLASH_ROM_WINDOW 0x42110030
#define FLASH_ROM_DATA 0x42150000
-#define QLCNIC_CRB_WINDOW_2M 0x00130060
-#define QLCNIC_INDIRECT_MEM_START 0x001e0000
-#define QLCNIC_FLASH_SEM2_LK 0x0013C010
-#define QLCNIC_FLASH_SEM2_ULK 0x0013C014
-#define QLCNIC_FLASH_LOCK_ID 0x001B2100
+#define QLCNIC_CRB_WINDOW_2M 0x00130060
+#define QLCNIC_INDIRECT_MEM_START 0x001e0000
+#define QLCNIC_FLASH_SEM2_LK 0x0013C010
+#define QLCNIC_FLASH_SEM2_ULK 0x0013C014
+#define QLCNIC_FLASH_LOCK_ID 0x001B2100
/* PCI function operational mode */
enum {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
deleted file mode 100644
index 3b10acc..0000000
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ /dev/null
@@ -1,1297 +0,0 @@
-/*
- * QLogic qlcnic NIC Driver
- * Copyright (c) 2009-2010 QLogic Corporation
- *
- * See LICENSE.qlcnic for copyright and licensing details.
- */
-
-#include "qlcnic.h"
-#include "qlcnic_hw.h"
-
-struct crb_addr_pair {
- u32 addr;
- u32 data;
-};
-
-#define QLCNIC_MAX_CRB_XFORM 60
-static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
-
-#define crb_addr_transform(name) \
- (crb_addr_xform[QLCNIC_HW_PX_MAP_CRB_##name] = \
- QLCNIC_HW_CRB_HUB_AGT_ADR_##name << 20)
-
-#define QLCNIC_ADDR_ERROR (0xffffffff)
-
-static int
-qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
-
-static void crb_addr_transform_setup(void)
-{
- crb_addr_transform(XDMA);
- crb_addr_transform(TIMR);
- crb_addr_transform(SRE);
- crb_addr_transform(SQN3);
- crb_addr_transform(SQN2);
- crb_addr_transform(SQN1);
- crb_addr_transform(SQN0);
- crb_addr_transform(SQS3);
- crb_addr_transform(SQS2);
- crb_addr_transform(SQS1);
- crb_addr_transform(SQS0);
- crb_addr_transform(RPMX7);
- crb_addr_transform(RPMX6);
- crb_addr_transform(RPMX5);
- crb_addr_transform(RPMX4);
- crb_addr_transform(RPMX3);
- crb_addr_transform(RPMX2);
- crb_addr_transform(RPMX1);
- crb_addr_transform(RPMX0);
- crb_addr_transform(ROMUSB);
- crb_addr_transform(SN);
- crb_addr_transform(QMN);
- crb_addr_transform(QMS);
- crb_addr_transform(PGNI);
- crb_addr_transform(PGND);
- crb_addr_transform(PGN3);
- crb_addr_transform(PGN2);
- crb_addr_transform(PGN1);
- crb_addr_transform(PGN0);
- crb_addr_transform(PGSI);
- crb_addr_transform(PGSD);
- crb_addr_transform(PGS3);
- crb_addr_transform(PGS2);
- crb_addr_transform(PGS1);
- crb_addr_transform(PGS0);
- crb_addr_transform(PS);
- crb_addr_transform(PH);
- crb_addr_transform(NIU);
- crb_addr_transform(I2Q);
- crb_addr_transform(EG);
- crb_addr_transform(MN);
- crb_addr_transform(MS);
- crb_addr_transform(CAS2);
- crb_addr_transform(CAS1);
- crb_addr_transform(CAS0);
- crb_addr_transform(CAM);
- crb_addr_transform(C2C1);
- crb_addr_transform(C2C0);
- crb_addr_transform(SMB);
- crb_addr_transform(OCM0);
- crb_addr_transform(I2C0);
-}
-
-void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_rx_buffer *rx_buf;
- int i, ring;
-
- recv_ctx = adapter->recv_ctx;
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
- for (i = 0; i < rds_ring->num_desc; ++i) {
- rx_buf = &(rds_ring->rx_buf_arr[i]);
- if (rx_buf->skb == NULL)
- continue;
-
- pci_unmap_single(adapter->pdev,
- rx_buf->dma,
- rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
-
- dev_kfree_skb_any(rx_buf->skb);
- }
- }
-}
-
-void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_rx_buffer *rx_buf;
- int i, ring;
-
- recv_ctx = adapter->recv_ctx;
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
-
- INIT_LIST_HEAD(&rds_ring->free_list);
-
- rx_buf = rds_ring->rx_buf_arr;
- for (i = 0; i < rds_ring->num_desc; i++) {
- list_add_tail(&rx_buf->list,
- &rds_ring->free_list);
- rx_buf++;
- }
- }
-}
-
-void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_cmd_buffer *cmd_buf;
- struct qlcnic_skb_frag *buffrag;
- int i, j;
- struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
- cmd_buf = tx_ring->cmd_buf_arr;
- for (i = 0; i < tx_ring->num_desc; i++) {
- buffrag = cmd_buf->frag_array;
- if (buffrag->dma) {
- pci_unmap_single(adapter->pdev, buffrag->dma,
- buffrag->length, PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- for (j = 0; j < cmd_buf->frag_count; j++) {
- buffrag++;
- if (buffrag->dma) {
- pci_unmap_page(adapter->pdev, buffrag->dma,
- buffrag->length,
- PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- }
- if (cmd_buf->skb) {
- dev_kfree_skb_any(cmd_buf->skb);
- cmd_buf->skb = NULL;
- }
- cmd_buf++;
- }
-}
-
-void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- int ring;
-
- recv_ctx = adapter->recv_ctx;
-
- if (recv_ctx->rds_rings == NULL)
- return;
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
- vfree(rds_ring->rx_buf_arr);
- rds_ring->rx_buf_arr = NULL;
- }
- kfree(recv_ctx->rds_rings);
-}
-
-int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_rx_buffer *rx_buf;
- int ring, i, size;
-
- struct net_device *netdev = adapter->netdev;
- struct qlcnic_hardware_context *ahw = adapter->ahw;
-
- recv_ctx = adapter->recv_ctx;
-
- size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring);
- rds_ring = kzalloc(size, GFP_KERNEL);
- if (rds_ring == NULL) {
- dev_err(&netdev->dev, "failed to allocate rds ring struct\n");
- goto err_out;
- }
- recv_ctx->rds_rings = rds_ring;
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
- switch (ring) {
- case RCV_RING_NORMAL:
- rds_ring->num_desc = adapter->num_rxd;
- rds_ring->dma_size = QLCNIC_P3P_RX_BUF_MAX_LEN;
- rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
- break;
-
- case RCV_RING_JUMBO:
- rds_ring->num_desc = adapter->num_jumbo_rxd;
- rds_ring->dma_size =
- QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
-
- if (ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
- rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
-
- rds_ring->skb_size =
- rds_ring->dma_size + NET_IP_ALIGN;
- break;
- }
- rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
- vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
- if (rds_ring->rx_buf_arr == NULL) {
- dev_err(&netdev->dev,
- "Failed to allocate rx buffer ring %d\n", ring);
- goto err_out;
- }
- memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
- INIT_LIST_HEAD(&rds_ring->free_list);
- /*
- * Now go through all of them, set reference handles
- * and put them in the queues.
- */
- rx_buf = rds_ring->rx_buf_arr;
- for (i = 0; i < rds_ring->num_desc; i++) {
- list_add_tail(&rx_buf->list,
- &rds_ring->free_list);
- rx_buf->ref_handle = i;
- rx_buf++;
- }
- spin_lock_init(&rds_ring->lock);
- }
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
- sds_ring->irq = adapter->msix_entries[ring].vector;
- sds_ring->adapter = adapter;
- sds_ring->num_desc = adapter->num_rxd;
-
- for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
- INIT_LIST_HEAD(&sds_ring->free_list[i]);
- }
-
- return 0;
-
-err_out:
- qlcnic_free_sw_resources(adapter);
- return -ENOMEM;
-}
-
-/*
- * Utility to translate from internal Phantom CRB address
- * to external PCI CRB address.
- */
-static u32 qlcnic_decode_crb_addr(u32 addr)
-{
- int i;
- u32 base_addr, offset, pci_base;
-
- crb_addr_transform_setup();
-
- pci_base = QLCNIC_ADDR_ERROR;
- base_addr = addr & 0xfff00000;
- offset = addr & 0x000fffff;
-
- for (i = 0; i < QLCNIC_MAX_CRB_XFORM; i++) {
- if (crb_addr_xform[i] == base_addr) {
- pci_base = i << 20;
- break;
- }
- }
- if (pci_base == QLCNIC_ADDR_ERROR)
- return pci_base;
- else
- return pci_base + offset;
-}
-
-#define QLCNIC_MAX_ROM_WAIT_USEC 100
-
-static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter)
-{
- long timeout = 0;
- long done = 0;
- int err;
-
- cond_resched();
-
- while (done == 0) {
- done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS, &err);
- done &= 2;
- if (++timeout >= QLCNIC_MAX_ROM_WAIT_USEC) {
- dev_err(&adapter->pdev->dev,
- "Timeout reached waiting for rom done");
- return -EIO;
- }
- udelay(1);
- }
- return 0;
-}
-
-static int do_rom_fast_read(struct qlcnic_adapter *adapter,
- u32 addr, u32 *valp)
-{
- int err;
-
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr);
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 3);
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_INSTR_OPCODE, 0xb);
- if (qlcnic_wait_rom_done(adapter)) {
- dev_err(&adapter->pdev->dev, "Error waiting for rom done\n");
- return -EIO;
- }
- /* reset abyte_cnt and dummy_byte_cnt */
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 0);
- udelay(10);
- QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
-
- *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA, &err);
- return 0;
-}
-
-static int do_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
- u8 *bytes, size_t size)
-{
- int addridx;
- int ret = 0;
-
- for (addridx = addr; addridx < (addr + size); addridx += 4) {
- int v;
- ret = do_rom_fast_read(adapter, addridx, &v);
- if (ret != 0)
- break;
- *(__le32 *)bytes = cpu_to_le32(v);
- bytes += 4;
- }
-
- return ret;
-}
-
-int
-qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
- u8 *bytes, size_t size)
-{
- int ret;
-
- ret = qlcnic_rom_lock(adapter);
- if (ret < 0)
- return ret;
-
- ret = do_rom_fast_read_words(adapter, addr, bytes, size);
-
- qlcnic_rom_unlock(adapter);
- return ret;
-}
-
-int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp)
-{
- int ret;
-
- if (qlcnic_rom_lock(adapter) != 0)
- return -EIO;
-
- ret = do_rom_fast_read(adapter, addr, valp);
- qlcnic_rom_unlock(adapter);
- return ret;
-}
-
-int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
-{
- int addr, val, err;
- int i, n, init_delay;
- struct crb_addr_pair *buf;
- unsigned offset;
- u32 off;
- struct pci_dev *pdev = adapter->pdev;
-
- QLCWR(adapter, QLCNIC_CMDPEG_STATE, 0);
- QLCWR(adapter, QLCNIC_RCVPEG_STATE, 0);
-
- /* Halt all the indiviual PEGs and other blocks */
- /* disable all I2Q */
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x10, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x14, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x18, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x1c, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x20, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x24, 0x0);
-
- /* disable all niu interrupts */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0x40, 0xff);
- /* disable xge rx/tx */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0x70000, 0x00);
- /* disable xg1 rx/tx */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0x80000, 0x00);
- /* disable sideband mac */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0x90000, 0x00);
- /* disable ap0 mac */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0xa0000, 0x00);
- /* disable ap1 mac */
- QLCWR32(adapter, QLCNIC_CRB_NIU + 0xb0000, 0x00);
-
- /* halt sre */
- val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000, &err);
- QLCWR32(adapter, QLCNIC_CRB_SRE + 0x1000, val & (~(0x1)));
-
- /* halt epg */
- QLCWR32(adapter, QLCNIC_CRB_EPG + 0x1300, 0x1);
-
- /* halt timers */
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x0, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x8, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x10, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x18, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x100, 0x0);
- QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x200, 0x0);
- /* halt pegs */
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, 1);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, 1);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, 1);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, 1);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
- msleep(20);
-
- qlcnic_rom_unlock(adapter);
- /* big hammer don't reset CAM block on reset */
- QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
-
- /* Init HW CRB block */
- if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
- qlcnic_rom_fast_read(adapter, 4, &n) != 0) {
- dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n);
- return -EIO;
- }
- offset = n & 0xffffU;
- n = (n >> 16) & 0xffffU;
-
- if (n >= 1024) {
- dev_err(&pdev->dev, "QLOGIC card flash not initialized.\n");
- return -EIO;
- }
-
- buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
- if (buf == NULL) {
- dev_err(&pdev->dev, "Unable to calloc memory for rom read.\n");
- return -ENOMEM;
- }
-
- for (i = 0; i < n; i++) {
- if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
- qlcnic_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
- kfree(buf);
- return -EIO;
- }
-
- buf[i].addr = addr;
- buf[i].data = val;
- }
-
- for (i = 0; i < n; i++) {
-
- off = qlcnic_decode_crb_addr(buf[i].addr);
- if (off == QLCNIC_ADDR_ERROR) {
- dev_err(&pdev->dev, "CRB init value out of range %x\n",
- buf[i].addr);
- continue;
- }
- off += QLCNIC_PCI_CRBSPACE;
-
- if (off & 1)
- continue;
-
- /* skipping cold reboot MAGIC */
- if (off == QLCNIC_CAM_RAM(0x1fc))
- continue;
- if (off == (QLCNIC_CRB_I2C0 + 0x1c))
- continue;
- if (off == (ROMUSB_GLB + 0xbc)) /* do not reset PCI */
- continue;
- if (off == (ROMUSB_GLB + 0xa8))
- continue;
- if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
- continue;
- if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
- continue;
- if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
- continue;
- if ((off & 0x0ff00000) == QLCNIC_CRB_DDR_NET)
- continue;
- /* skip the function enable register */
- if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION))
- continue;
- if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION2))
- continue;
- if ((off & 0x0ff00000) == QLCNIC_CRB_SMB)
- continue;
-
- init_delay = 1;
- /* After writing this register, HW needs time for CRB */
- /* to quiet down (else crb_window returns 0xffffffff) */
- if (off == QLCNIC_ROMUSB_GLB_SW_RESET)
- init_delay = 1000;
-
- QLCWR32(adapter, off, buf[i].data);
-
- msleep(init_delay);
- }
- kfree(buf);
-
- /* Initialize protocol process engine */
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0xc, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x8, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
- msleep(1);
-
- QLCWR(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
- QLCWR(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
-
- return 0;
-}
-
-static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
-{
- u32 val;
- int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
-
- do {
- val = QLCRD(adapter, QLCNIC_CMDPEG_STATE);
-
- switch (val) {
- case PHAN_INITIALIZE_COMPLETE:
- case PHAN_INITIALIZE_ACK:
- return 0;
- case PHAN_INITIALIZE_FAILED:
- goto out_err;
- default:
- break;
- }
-
- msleep(QLCNIC_CMDPEG_CHECK_DELAY);
-
- } while (--retries);
-
- QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
-
-out_err:
- dev_err(&adapter->pdev->dev, "Command Peg initialization not "
- "complete, state: 0x%x.\n", val);
- return -EIO;
-}
-
-static int
-qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
-{
- u32 val;
- int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
-
- do {
- val = QLCRD(adapter, QLCNIC_RCVPEG_STATE);
-
- if (val == PHAN_PEG_RCV_INITIALIZED)
- return 0;
-
- msleep(QLCNIC_RCVPEG_CHECK_DELAY);
-
- } while (--retries);
-
- if (!retries) {
- dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
- "complete, state: 0x%x.\n", val);
- return -EIO;
- }
-
- return 0;
-}
-
-int
-qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
-{
- int err;
-
- err = qlcnic_cmd_peg_ready(adapter);
- if (err)
- return err;
-
- err = qlcnic_receive_peg_ready(adapter);
- if (err)
- return err;
-
- QLCWR(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
-
- return err;
-}
-
-int
-qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
-
- int timeo;
- u32 val;
-
- val = QLCRD(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
- val = QLC_DEV_GET_DRV(val, adapter->portnum);
- if ((val & 0x3) != QLCNIC_TYPE_NIC) {
- dev_err(&adapter->pdev->dev,
- "Not an Ethernet NIC func=%u\n", val);
- return -EIO;
- }
- adapter->ahw->physical_port = (val >> 2);
- if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
- timeo = QLCNIC_INIT_TIMEOUT_SECS;
-
- adapter->dev_init_timeo = timeo;
-
- if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo))
- timeo = QLCNIC_RESET_TIMEOUT_SECS;
-
- adapter->reset_ack_timeo = timeo;
-
- return 0;
-}
-
-static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
- struct qlcnic_flt_entry *region_entry)
-{
- struct qlcnic_flt_header flt_hdr;
- struct qlcnic_flt_entry *flt_entry;
- int i = 0, ret;
- u32 entry_size;
-
- memset(region_entry, 0, sizeof(struct qlcnic_flt_entry));
- ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION,
- (u8 *)&flt_hdr,
- sizeof(struct qlcnic_flt_header));
- if (ret) {
- dev_warn(&adapter->pdev->dev,
- "error reading flash layout header\n");
- return -EIO;
- }
-
- entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
- flt_entry = vmalloc(entry_size);
- if (flt_entry == NULL) {
- dev_err(&adapter->pdev->dev, "error allocating memory\n");
- return -EIO;
- }
- memset(flt_entry, 0, entry_size);
-
- ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
- sizeof(struct qlcnic_flt_header),
- (u8 *)flt_entry, entry_size);
- if (ret) {
- dev_warn(&adapter->pdev->dev,
- "error reading flash layout entries\n");
- goto err_out;
- }
-
- while (i < (entry_size/sizeof(struct qlcnic_flt_entry))) {
- if (flt_entry[i].region == region)
- break;
- i++;
- }
- if (i >= (entry_size/sizeof(struct qlcnic_flt_entry))) {
- dev_warn(&adapter->pdev->dev,
- "region=%x not found in %d regions\n", region, i);
- ret = -EIO;
- goto err_out;
- }
- memcpy(region_entry, &flt_entry[i], sizeof(struct qlcnic_flt_entry));
-
-err_out:
- vfree(flt_entry);
- return ret;
-}
-
-int
-qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_flt_entry fw_entry;
- u32 ver = -1, min_ver;
- int ret;
-
- if (adapter->ahw->revision_id == QLCNIC_P3P_C0)
- ret = qlcnic_get_flt_entry(adapter, QLCNIC_C0_FW_IMAGE_REGION,
- &fw_entry);
- else
- ret = qlcnic_get_flt_entry(adapter, QLCNIC_B0_FW_IMAGE_REGION,
- &fw_entry);
-
- if (!ret)
- /* 0-4:-signature, 4-8:-fw version */
- qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
- (int *)&ver);
- else
- qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET,
- (int *)&ver);
-
- ver = QLCNIC_DECODE_VERSION(ver);
- min_ver = QLCNIC_MIN_FW_VERSION;
-
- if (ver < min_ver) {
- dev_err(&adapter->pdev->dev,
- "firmware version %d.%d.%d unsupported."
- "Min supported version %d.%d.%d\n",
- _major(ver), _minor(ver), _build(ver),
- _major(min_ver), _minor(min_ver), _build(min_ver));
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-qlcnic_has_mn(struct qlcnic_adapter *adapter)
-{
- int err;
- u32 capability;
- capability = 0;
-
- capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY, &err);
- if (capability & QLCNIC_PEG_TUNE_MN_PRESENT)
- return 1;
-
- return 0;
-}
-
-static
-struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
-{
- u32 i;
- struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
- __le32 entries = cpu_to_le32(directory->num_entries);
-
- for (i = 0; i < entries; i++) {
-
- __le32 offs = cpu_to_le32(directory->findex) +
- (i * cpu_to_le32(directory->entry_size));
- __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
-
- if (tab_type == section)
- return (struct uni_table_desc *) &unirom[offs];
- }
-
- return NULL;
-}
-
-#define FILEHEADER_SIZE (14 * 4)
-
-static int
-qlcnic_validate_header(struct qlcnic_adapter *adapter)
-{
- const u8 *unirom = adapter->fw->data;
- struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
- __le32 fw_file_size = adapter->fw->size;
- __le32 entries;
- __le32 entry_size;
- __le32 tab_size;
-
- if (fw_file_size < FILEHEADER_SIZE)
- return -EINVAL;
-
- entries = cpu_to_le32(directory->num_entries);
- entry_size = cpu_to_le32(directory->entry_size);
- tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
-
- if (fw_file_size < tab_size)
- return -EINVAL;
-
- return 0;
-}
-
-static int
-qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
-{
- struct uni_table_desc *tab_desc;
- struct uni_data_desc *descr;
- const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- QLCNIC_UNI_BOOTLD_IDX_OFF));
- __le32 offs;
- __le32 tab_size;
- __le32 data_size;
-
- tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
-
- if (!tab_desc)
- return -EINVAL;
-
- tab_size = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
-
- if (adapter->fw->size < tab_size)
- return -EINVAL;
-
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx));
- descr = (struct uni_data_desc *)&unirom[offs];
-
- data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
-
- if (adapter->fw->size < data_size)
- return -EINVAL;
-
- return 0;
-}
-
-static int
-qlcnic_validate_fw(struct qlcnic_adapter *adapter)
-{
- struct uni_table_desc *tab_desc;
- struct uni_data_desc *descr;
- const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- QLCNIC_UNI_FIRMWARE_IDX_OFF));
- __le32 offs;
- __le32 tab_size;
- __le32 data_size;
-
- tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
-
- if (!tab_desc)
- return -EINVAL;
-
- tab_size = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
-
- if (adapter->fw->size < tab_size)
- return -EINVAL;
-
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * (idx));
- descr = (struct uni_data_desc *)&unirom[offs];
- data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
-
- if (adapter->fw->size < data_size)
- return -EINVAL;
-
- return 0;
-}
-
-static int
-qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
-{
- struct uni_table_desc *ptab_descr;
- const u8 *unirom = adapter->fw->data;
- int mn_present = qlcnic_has_mn(adapter);
- __le32 entries;
- __le32 entry_size;
- __le32 tab_size;
- u32 i;
-
- ptab_descr = qlcnic_get_table_desc(unirom,
- QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
- if (!ptab_descr)
- return -EINVAL;
-
- entries = cpu_to_le32(ptab_descr->num_entries);
- entry_size = cpu_to_le32(ptab_descr->entry_size);
- tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
-
- if (adapter->fw->size < tab_size)
- return -EINVAL;
-
-nomn:
- for (i = 0; i < entries; i++) {
-
- __le32 flags, file_chiprev, offs;
- u8 chiprev = adapter->ahw->revision_id;
- u32 flagbit;
-
- offs = cpu_to_le32(ptab_descr->findex) +
- (i * cpu_to_le32(ptab_descr->entry_size));
- flags = cpu_to_le32(*((int *)&unirom[offs] +
- QLCNIC_UNI_FLAGS_OFF));
- file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
- QLCNIC_UNI_CHIP_REV_OFF));
-
- flagbit = mn_present ? 1 : 2;
-
- if ((chiprev == file_chiprev) &&
- ((1ULL << flagbit) & flags)) {
- adapter->file_prd_off = offs;
- return 0;
- }
- }
- if (mn_present) {
- mn_present = 0;
- goto nomn;
- }
- return -EINVAL;
-}
-
-static int
-qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter)
-{
- if (qlcnic_validate_header(adapter)) {
- dev_err(&adapter->pdev->dev,
- "unified image: header validation failed\n");
- return -EINVAL;
- }
-
- if (qlcnic_validate_product_offs(adapter)) {
- dev_err(&adapter->pdev->dev,
- "unified image: product validation failed\n");
- return -EINVAL;
- }
-
- if (qlcnic_validate_bootld(adapter)) {
- dev_err(&adapter->pdev->dev,
- "unified image: bootld validation failed\n");
- return -EINVAL;
- }
-
- if (qlcnic_validate_fw(adapter)) {
- dev_err(&adapter->pdev->dev,
- "unified image: firmware validation failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static
-struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
- u32 section, u32 idx_offset)
-{
- const u8 *unirom = adapter->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
- idx_offset));
- struct uni_table_desc *tab_desc;
- __le32 offs;
-
- tab_desc = qlcnic_get_table_desc(unirom, section);
-
- if (tab_desc == NULL)
- return NULL;
-
- offs = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * idx);
-
- return (struct uni_data_desc *)&unirom[offs];
-}
-
-static u8 *
-qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
-{
- u32 offs = QLCNIC_BOOTLD_START;
-
- if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_BOOTLD,
- QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
-
- return (u8 *)&adapter->fw->data[offs];
-}
-
-static u8 *
-qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
-{
- u32 offs = QLCNIC_IMAGE_START;
-
- if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_FW,
- QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
-
- return (u8 *)&adapter->fw->data[offs];
-}
-
-static __le32
-qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
-{
- if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32((qlcnic_get_data_desc(adapter,
- QLCNIC_UNI_DIR_SECT_FW,
- QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
- else
- return cpu_to_le32(
- *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]);
-}
-
-static __le32
-qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
-{
- struct uni_data_desc *fw_data_desc;
- const struct firmware *fw = adapter->fw;
- __le32 major, minor, sub;
- const u8 *ver_str;
- int i, ret;
-
- if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
-
- fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
- QLCNIC_UNI_FIRMWARE_IDX_OFF);
- ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
- cpu_to_le32(fw_data_desc->size) - 17;
-
- for (i = 0; i < 12; i++) {
- if (!strncmp(&ver_str[i], "REV=", 4)) {
- ret = sscanf(&ver_str[i+4], "%u.%u.%u ",
- &major, &minor, &sub);
- if (ret != 3)
- return 0;
- else
- return major + (minor << 8) + (sub << 16);
- }
- }
-
- return 0;
-}
-
-static __le32
-qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
-{
- const struct firmware *fw = adapter->fw;
- __le32 bios_ver, prd_off = adapter->file_prd_off;
-
- if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
- return cpu_to_le32(
- *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
-
- bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
- + QLCNIC_UNI_BIOS_VERSION_OFF));
-
- return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
-}
-
-static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
-{
- if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID))
- dev_info(&adapter->pdev->dev, "Resetting rom_lock\n");
-
- qlcnic_pcie_sem_unlock(adapter, 2);
-}
-
-static int
-qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
-{
- u32 heartbeat, ret = -EIO;
- int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
-
- adapter->heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
-
- do {
- msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
- heartbeat = QLCRD(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- if (heartbeat != adapter->heartbeat) {
- ret = QLCNIC_RCODE_SUCCESS;
- break;
- }
- } while (--retries);
-
- return ret;
-}
-
-int
-qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
-{
- if ((adapter->flags & QLCNIC_FW_HANG) ||
- qlcnic_check_fw_hearbeat(adapter)) {
- qlcnic_rom_lock_recovery(adapter);
- return 1;
- }
-
- if (adapter->need_fw_reset)
- return 1;
-
- if (adapter->fw)
- return 1;
-
- return 0;
-}
-
-static const char *fw_name[] = {
- QLCNIC_UNIFIED_ROMIMAGE_NAME,
- QLCNIC_FLASH_ROMIMAGE_NAME,
-};
-
-int
-qlcnic_load_firmware(struct qlcnic_adapter *adapter)
-{
- u64 *ptr64;
- u32 i, flashaddr, size;
- const struct firmware *fw = adapter->fw;
- struct pci_dev *pdev = adapter->pdev;
-
- dev_info(&pdev->dev, "loading firmware from %s\n",
- fw_name[adapter->ahw->fw_type]);
-
- if (fw) {
- __le64 data;
-
- size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
-
- ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter);
- flashaddr = QLCNIC_BOOTLD_START;
-
- for (i = 0; i < size; i++) {
- data = cpu_to_le64(ptr64[i]);
-
- if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
- return -EIO;
-
- flashaddr += 8;
- }
-
- size = (__force u32)qlcnic_get_fw_size(adapter) / 8;
-
- ptr64 = (u64 *)qlcnic_get_fw_offs(adapter);
- flashaddr = QLCNIC_IMAGE_START;
-
- for (i = 0; i < size; i++) {
- data = cpu_to_le64(ptr64[i]);
-
- if (qlcnic_pci_mem_write_2M(adapter,
- flashaddr, data))
- return -EIO;
-
- flashaddr += 8;
- }
-
- size = (__force u32)qlcnic_get_fw_size(adapter) % 8;
- if (size) {
- data = cpu_to_le64(ptr64[i]);
-
- if (qlcnic_pci_mem_write_2M(adapter,
- flashaddr, data))
- return -EIO;
- }
-
- } else {
- u64 data;
- u32 hi, lo;
- int ret;
- struct qlcnic_flt_entry bootld_entry;
-
- ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION,
- &bootld_entry);
- if (!ret) {
- size = bootld_entry.size / 8;
- flashaddr = bootld_entry.start_addr;
- } else {
- size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
- flashaddr = QLCNIC_BOOTLD_START;
- dev_info(&pdev->dev,
- "using legacy method to get flash fw region");
- }
-
- for (i = 0; i < size; i++) {
- if (qlcnic_rom_fast_read(adapter,
- flashaddr, (int *)&lo) != 0)
- return -EIO;
- if (qlcnic_rom_fast_read(adapter,
- flashaddr + 4, (int *)&hi) != 0)
- return -EIO;
-
- data = (((u64)hi << 32) | lo);
-
- if (qlcnic_pci_mem_write_2M(adapter,
- flashaddr, data))
- return -EIO;
-
- flashaddr += 8;
- }
- }
- msleep(1);
-
- QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x18, 0x1020);
- QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0x80001e);
- return 0;
-}
-
-static int
-qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
-{
- __le32 val;
- u32 ver, bios, min_size;
- struct pci_dev *pdev = adapter->pdev;
- const struct firmware *fw = adapter->fw;
- u8 fw_type = adapter->ahw->fw_type;
-
- if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
- if (qlcnic_validate_unified_romimage(adapter))
- return -EINVAL;
-
- min_size = QLCNIC_UNI_FW_MIN_SIZE;
- } else {
- val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
- if ((__force u32)val != QLCNIC_BDINFO_MAGIC)
- return -EINVAL;
-
- min_size = QLCNIC_FW_MIN_SIZE;
- }
-
- if (fw->size < min_size)
- return -EINVAL;
-
- val = qlcnic_get_fw_version(adapter);
- ver = QLCNIC_DECODE_VERSION(val);
-
- if (ver < QLCNIC_MIN_FW_VERSION) {
- dev_err(&pdev->dev,
- "%s: firmware version %d.%d.%d unsupported\n",
- fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
- return -EINVAL;
- }
-
- val = qlcnic_get_bios_version(adapter);
- qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
- if ((__force u32)val != bios) {
- dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
- fw_name[fw_type]);
- return -EINVAL;
- }
-
- QLCWR(adapter, QLCNIC_FW_IMG_VALID, QLCNIC_BDINFO_MAGIC);
- return 0;
-}
-
-static void
-qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
-{
- u8 fw_type;
-
- switch (adapter->ahw->fw_type) {
- case QLCNIC_UNKNOWN_ROMIMAGE:
- fw_type = QLCNIC_UNIFIED_ROMIMAGE;
- break;
-
- case QLCNIC_UNIFIED_ROMIMAGE:
- default:
- fw_type = QLCNIC_FLASH_ROMIMAGE;
- break;
- }
-
- adapter->ahw->fw_type = fw_type;
-}
-
-
-
-void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
-{
- struct pci_dev *pdev = adapter->pdev;
- int rc;
-
- adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
-
-next:
- qlcnic_get_next_fwtype(adapter);
-
- if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
- adapter->fw = NULL;
- } else {
- rc = request_firmware(&adapter->fw,
- fw_name[adapter->ahw->fw_type], &pdev->dev);
- if (rc != 0)
- goto next;
-
- rc = qlcnic_validate_firmware(adapter);
- if (rc != 0) {
- release_firmware(adapter->fw);
- msleep(1);
- goto next;
- }
- }
-}
-
-
-void
-qlcnic_release_firmware(struct qlcnic_adapter *adapter)
-{
- if (adapter->fw)
- release_firmware(adapter->fw);
- adapter->fw = NULL;
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index ce8a4e0..165d596 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -1167,3 +1167,442 @@ qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
sds_ring->consumer = consumer;
writel(consumer, sds_ring->crb_sts_consumer);
}
+
+static struct qlcnic_rx_buffer *
+qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ u8 ring, u64 sts_data[])
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index >= rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ length = qlcnic_83xx_pktln(sts_data[0]);
+ cksum = qlcnic_83xx_csum_status(sts_data[1]);
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return buffer;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+
+ napi_gro_receive(&sds_ring->napi, skb);
+
+ adapter->stats.rx_pkts++;
+ adapter->stats.rxbytes += length;
+
+ return buffer;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ u8 ring, u64 sts_data[])
+{
+ struct net_device *netdev = adapter->netdev;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h;
+ struct tcphdr *th;
+ bool push;
+ int l2_hdr_offset, l4_hdr_offset;
+ int index;
+ u16 lro_length, length, data_offset;
+ u16 vid = 0xffff;
+
+ if (unlikely(ring > adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index > rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ lro_length = qlcnic_83xx_lro_pktln(sts_data[0]);
+ l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]);
+ l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]);
+ push = qlcnic_83xx_is_psh_bit(sts_data[1]);
+
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return buffer;
+ if (qlcnic_83xx_is_tstamp(sts_data[1]))
+ data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+ else
+ data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+ skb_put(skb, lro_length + data_offset);
+
+ skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ if (htons(skb->protocol) == ETH_P_IPV6) {
+ ipv6h = (struct ipv6hdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr));
+
+ length = (th->doff << 2) + lro_length;
+ ipv6h->payload_len = htons(length);
+ } else {
+ iph = (struct iphdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+
+ length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+ iph->tot_len = htons(length);
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ }
+
+
+ th->psh = push;
+
+ length = skb->len;
+
+ if (vid != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vid);
+ netif_receive_skb(skb);
+
+ adapter->stats.lro_pkts++;
+ adapter->stats.lrobytes += length;
+ return buffer;
+}
+
+static int
+qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct list_head *cur;
+ struct status_desc *desc;
+ struct qlcnic_rx_buffer *rxbuf = NULL;
+ u64 sts_data[2];
+
+ int count = 0, opcode;
+ u8 ring;
+ u32 consumer = sds_ring->consumer;
+
+ while (count < max) {
+ desc = &sds_ring->desc_head[consumer];
+ sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
+ opcode = qlcnic_83xx_opcode(sts_data[1]);
+ if (!opcode)
+ break;
+ sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
+ ring = QLCNIC_FETCH_RING_ID(sts_data[0]);
+
+ switch (opcode) {
+ case QLC_83XX_REG_DESC:
+ rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring,
+ ring, sts_data);
+ break;
+ case QLC_83XX_LRO_DESC:
+ rxbuf = qlcnic_83xx_process_lro(adapter, sds_ring,
+ ring, sts_data);
+ break;
+ default:
+ dev_info(&adapter->pdev->dev,
+ "Unkonwn opcode: 0x%x\n", opcode);
+ goto skip;
+ }
+
+ if (likely(rxbuf))
+ list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+ else
+ adapter->stats.null_rxbuf++;
+
+skip:
+ desc = &sds_ring->desc_head[consumer];
+ /* Reset the descriptor */
+ desc->status_desc_data[1] = 0;
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+ count++;
+ }
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ struct qlcnic_host_rds_ring *rds_ring =
+ &adapter->recv_ctx->rds_rings[ring];
+
+ if (!list_empty(&sds_ring->free_list[ring])) {
+ list_for_each(cur, &sds_ring->free_list[ring]) {
+ rxbuf = list_entry(cur,
+ struct qlcnic_rx_buffer, list);
+ qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+ }
+ spin_lock(&rds_ring->lock);
+ list_splice_tail_init(&sds_ring->free_list[ring],
+ &rds_ring->free_list);
+ spin_unlock(&rds_ring->lock);
+ }
+
+ qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring);
+ }
+
+ if (count) {
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+ }
+ return count;
+}
+
+static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+ /* there is only 1 tx ring in this path */
+ struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+ int tx_complete;
+ int work_done;
+
+ if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
+ qlcnic_83xx_process_aen(adapter);
+
+ tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
+
+ work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
+
+ if ((work_done < budget) && tx_complete) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ return work_done;
+}
+
+static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_tx_ring *tx_ring =
+ container_of(napi, struct qlcnic_host_tx_ring, napi);
+
+ struct qlcnic_adapter *adapter = tx_ring->adapter;
+ int work_done;
+
+ work_done = qlcnic_process_cmd_ring(adapter, tx_ring,
+ QLCNIC_TX_POLL_BUDGET);
+
+ if (work_done) {
+ napi_complete(&tx_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
+ qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ }
+
+ return work_done;
+}
+
+static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct qlcnic_host_sds_ring *sds_ring =
+ container_of(napi, struct qlcnic_host_sds_ring, napi);
+
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ int work_done;
+
+ work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
+
+ if (work_done < budget) {
+ napi_complete(&sds_ring->napi);
+ if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ return work_done;
+}
+
+void
+qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ napi_enable(&sds_ring->napi);
+ qlcnic_83xx_enable_intr(adapter, sds_ring);
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ napi_enable(&tx_ring->napi);
+ qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ }
+ }
+}
+
+void
+qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct qlcnic_host_tx_ring *tx_ring;
+
+ if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+ return;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ writel(1, sds_ring->crb_intr_mask);
+ napi_synchronize(&sds_ring->napi);
+ napi_disable(&sds_ring->napi);
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
+ napi_synchronize(&tx_ring->napi);
+ napi_disable(&tx_ring->napi);
+ }
+ }
+}
+
+int
+qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+ int ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+ return -ENOMEM;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ netif_napi_add(netdev, &sds_ring->napi,
+ qlcnic_83xx_rx_poll, QLCNIC_NETDEV_WEIGHT * 2);
+ else
+ netif_napi_add(netdev, &sds_ring->napi,
+ qlcnic_83xx_poll,
+ QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
+ }
+
+ if (qlcnic_alloc_tx_rings(adapter, netdev)) {
+ qlcnic_free_sds_rings(recv_ctx);
+ return -ENOMEM;
+ }
+
+ if (adapter->flags & QLCNIC_MSIX_ENABLED) {
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ netif_napi_add(netdev, &tx_ring->napi,
+ qlcnic_83xx_msix_tx_poll,
+ QLCNIC_NETDEV_WEIGHT);
+ }
+ }
+
+ return 0;
+}
+
+void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_sds_ring *sds_ring,
+ int ring, u64 sts_data[])
+{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ struct sk_buff *skb;
+ struct qlcnic_host_rds_ring *rds_ring;
+ int index, length, cksum;
+
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+ index = qlcnic_83xx_hndl(sts_data[0]);
+ if (unlikely(index >= rds_ring->num_desc))
+ return;
+
+ length = qlcnic_83xx_pktln(sts_data[0]);
+ cksum = qlcnic_83xx_csum_status(sts_data[0]);
+ skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return;
+
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+ adapter->ahw->diag_cnt++;
+ else
+ dump_skb(skb, adapter);
+
+ dev_kfree_skb_any(skb);
+ return;
+}
+
+void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+ struct qlcnic_adapter *adapter = sds_ring->adapter;
+ struct status_desc *desc;
+ u64 sts_data[2];
+ int ring, opcode;
+
+ u32 consumer = sds_ring->consumer;
+
+ desc = &sds_ring->desc_head[consumer];
+ sts_data[0] = le64_to_cpu(desc->status_desc_data[0]);
+ sts_data[1] = le64_to_cpu(desc->status_desc_data[1]);
+ opcode = qlcnic_83xx_opcode(sts_data[1]);
+ if (!opcode)
+ return;
+
+ ring = QLCNIC_FETCH_RING_ID(qlcnic_83xx_hndl(sts_data[0]));
+ qlcnic_83xx_process_rcv_diag(adapter, sds_ring, ring, sts_data);
+
+ desc = &sds_ring->desc_head[consumer];
+ desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+ consumer = get_next_index(consumer, sds_ring->num_desc);
+
+ sds_ring->consumer = consumer;
+ writel(consumer, sds_ring->crb_sts_consumer);
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index 1720afc..49ef8bb 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -10,6 +10,9 @@
#define QLC_83XX_OCM_INDEX 3
#define QLC_83XX_PCI_INDEX 0
+static const u32 qlcnic_ms_read_data[] = {
+ 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, };
+
static u32
qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
u32 *buffer)
@@ -318,7 +321,7 @@ qlcnic_read_memory(struct qlcnic_adapter *adapter,
goto out;
}
for (i = 0; i < 4; i++) {
- data = qlcnic_ind_rd(adapter, QLCNIC_MS_READ_DATA[i]);
+ data = qlcnic_ind_rd(adapter, qlcnic_ms_read_data[i]);
*buffer++ = cpu_to_le32(data);
}
addr += 16;
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 13/15] qlcnic: create new file for 82xx firmware commands
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Modify 82xx driver to support new adapter - Qlogic 83XX CNA
Create new file for 82xx firmware interface commands
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/Makefile | 4 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 25 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_82xx_hw.c | 2590 ++++++++++++++++++++
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 94 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 8 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 56 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 1 -
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 1179 ---------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 12 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 1431 -----------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 17 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 9 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 108 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 25 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 51 +-
16 files changed, 2837 insertions(+), 2775 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_hw.c
delete mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
delete mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index 25b73f1..fe61793 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_QLCNIC) := qlcnic.o
-qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
- qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
+qlcnic-y := qlcnic_82xx_hw.o qlcnic_main.o qlcnic_init.o \
+ qlcnic_ethtool.o qlcnic_io.o \
qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
qlcnic_83xx_init.o qlcnic_83xx_vnic.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index eaaa049..ddd8795 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -49,6 +49,8 @@
#define _minor(v) (((v) >> 16) & 0xff)
#define _build(v) ((v) & 0xffff)
+#define QLCNIC_DBG_LEVEL_MASK (NETIF_MSG_DRV | NETIF_MSG_HW | NETIF_MSG_PKTDATA)
+
/* version in image has weird encoding:
* 7:0 - major
* 15:8 - minor
@@ -142,6 +144,8 @@
#define DEFAULT_RCV_DESCRIPTORS_10G 4096
#define DEFAULT_RCV_DESCRIPTORS_VF 1024
#define MAX_RDS_RINGS 2
+#define MAX_SDS_RINGS 8
+
#define get_next_index(index, length) \
(((index) + 1) & ((length) - 1))
@@ -259,6 +263,8 @@ struct rcv_desc {
(((sts_data) >> 52) & 0x1)
#define qlcnic_get_lro_sts_seq_number(sts_data) \
((sts_data) & 0x0FFFFFFFF)
+#define qlcnic_get_lro_sts_mss(sts_data1) \
+ ((sts_data1 >> 32) & 0x0FFFF)
struct status_desc {
@@ -524,7 +530,7 @@ struct qlcnic_hardware_context {
u16 max_tx_ques;
u16 max_rx_ques;
u16 max_mtu;
- u16 msg_enable;
+ u32 msg_enable;
u16 act_pci_func;
u32 capabilities;
@@ -675,6 +681,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CAP0_JUMBO_CONTIGUOUS (1 << 7)
#define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8)
#define QLCNIC_CAP0_VALIDOFF (1 << 11)
+#define QLCNIC_CAP0_LRO_MSS (1 << 21)
/*
* Context state
@@ -881,6 +888,9 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9
#define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10
#define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27
+#define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31
+#define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2
+#define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
@@ -961,6 +971,8 @@ struct qlcnic_ipaddr {
#define QLCNIC_NEED_FLR 0x1000
#define QLCNIC_FW_RESET_OWNER 0x2000
#define QLCNIC_FW_HANG 0x4000
+#define QLCNIC_FW_LRO_MSS_CAP 0x8000
+
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -1598,8 +1610,10 @@ int qlcnic_nic_set_promisc(struct qlcnic_adapter *, u32);
void qlcnic_config_intr_coalesce(struct qlcnic_adapter *);
int qlcnic_config_rss(struct qlcnic_adapter *, int);
void qlcnic_config_ipaddr(struct qlcnic_adapter *, __be32, int);
+void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int);
int qlcnic_linkevent_request(struct qlcnic_adapter *, int);
int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *, int);
+int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *);
int qlcnic_change_mtu(struct net_device *, int);
int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
netdev_features_t qlcnic_fix_features(struct net_device *netdev,
@@ -1703,7 +1717,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_reset_npar_config(struct qlcnic_adapter *);
int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *,
struct qlcnic_adapter *, u32);
-int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
+
/*
* QLOGIC Board information
*/
@@ -1780,11 +1794,4 @@ struct qlcnic_hardware_ops {
extern struct qlcnic_nic_template qlcnic_vf_ops;
-#define QLCDB(adapter, lvl, _fmt, _args...) do { \
- if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
- printk(KERN_INFO "%s: %s: " _fmt, \
- dev_name(&adapter->pdev->dev), \
- __func__, ##_args); \
- } while (0)
-
#endif /* __QLCNIC_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_hw.c
new file mode 100644
index 0000000..93a3c18
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_82xx_hw.c
@@ -0,0 +1,2590 @@
+/*
+ * QLogic qlcnic NIC Driver
+ * Copyright (c) 2009-2010 QLogic Corporation
+ *
+ * See LICENSE.qlcnic for copyright and licensing details.
+ */
+
+#include "qlcnic.h"
+#include "qlcnic_hdr.h"
+#include "qlcnic_hw.h"
+
+#include <linux/slab.h>
+#include <net/ip.h>
+#include <linux/bitops.h>
+
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+ return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem *addr)
+{
+ writel(((u32) (val)), (addr));
+ writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+static const struct crb_128M_2M_block_map
+crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
+ {{{0, 0, 0, 0} } }, /* 0: PCI */
+ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
+ {1, 0x0110000, 0x0120000, 0x130000},
+ {1, 0x0120000, 0x0122000, 0x124000},
+ {1, 0x0130000, 0x0132000, 0x126000},
+ {1, 0x0140000, 0x0142000, 0x128000},
+ {1, 0x0150000, 0x0152000, 0x12a000},
+ {1, 0x0160000, 0x0170000, 0x110000},
+ {1, 0x0170000, 0x0172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x01e0000, 0x01e0800, 0x122000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+ {{{0, 0, 0, 0} } }, /* 3: */
+ {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+ {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
+ {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
+ {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
+ {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x08f0000, 0x08f2000, 0x172000} } },
+ {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x09f0000, 0x09f2000, 0x176000} } },
+ {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+ {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+ {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+ {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+ {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+ {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+ {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+ {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+ {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+ {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+ {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+ {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+ {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+ {{{0, 0, 0, 0} } }, /* 23: */
+ {{{0, 0, 0, 0} } }, /* 24: */
+ {{{0, 0, 0, 0} } }, /* 25: */
+ {{{0, 0, 0, 0} } }, /* 26: */
+ {{{0, 0, 0, 0} } }, /* 27: */
+ {{{0, 0, 0, 0} } }, /* 28: */
+ {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+ {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+ {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+ {{{0} } }, /* 32: PCI */
+ {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
+ {1, 0x2110000, 0x2120000, 0x130000},
+ {1, 0x2120000, 0x2122000, 0x124000},
+ {1, 0x2130000, 0x2132000, 0x126000},
+ {1, 0x2140000, 0x2142000, 0x128000},
+ {1, 0x2150000, 0x2152000, 0x12a000},
+ {1, 0x2160000, 0x2170000, 0x110000},
+ {1, 0x2170000, 0x2172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+ {{{0} } }, /* 35: */
+ {{{0} } }, /* 36: */
+ {{{0} } }, /* 37: */
+ {{{0} } }, /* 38: */
+ {{{0} } }, /* 39: */
+ {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+ {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+ {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+ {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+ {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+ {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+ {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+ {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+ {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+ {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+ {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+ {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+ {{{0} } }, /* 52: */
+ {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+ {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+ {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+ {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+ {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+ {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+ {{{0} } }, /* 59: I2C0 */
+ {{{0} } }, /* 60: I2C1 */
+ {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
+ {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+ {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
+};
+
+/*
+ * Top 12 bits of Command Regiser Block (CRB) internal address (hub, agent)
+ */
+static const unsigned crb_hub_agt[64] = {
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PS,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_MN,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_MS,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SRE,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_NIU,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_QMN,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SQN0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SQN1,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SQN2,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SQN3,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGN4,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGN0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGN1,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGN2,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGN3,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGND,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGNI,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGS0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGS1,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGS2,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGS3,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGSI,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SN,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_EG,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PS,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_CAM,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX1,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX2,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX3,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX4,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX5,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX6,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX7,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX8,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX9,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_OCM0,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_SMB,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_I2C0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_I2C1,
+ 0,
+ QLCNIC_HW_CRB_HUB_AGT_ADR_PGNC,
+ 0,
+};
+
+static const u32 msi_tgt_status[8] = {
+ ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
+};
+
+/* PCI windowing for DDR regions. */
+static void
+qlcnic_read_reg_indirect(u32 addr, void __iomem *bar0, u32 *data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_CRB_WINDOW_2M;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_INDIRECT_MEM_START + LSW(addr);
+ *data = readl(val);
+}
+
+static void
+qlcnic_write_reg_indirect(u32 addr, void __iomem *bar0, u32 data)
+{
+ u32 dest;
+ void __iomem *val;
+
+ dest = addr & 0xFFFF0000;
+ val = bar0 + QLCNIC_CRB_WINDOW_2M;
+ writel(dest, val);
+ readl(val);
+ val = bar0 + QLCNIC_INDIRECT_MEM_START + LSW(addr);
+ writel(data, val);
+ readl(val);
+}
+
+int
+qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
+{
+ int err, done = 0, timeout = 0;
+
+ while (!done) {
+ done = QLCRD32(adapter,
+ QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)), &err);
+ if (done == 1)
+ break;
+ if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to acquire sem=%d lock; held by=%d\n",
+ sem,
+ id_reg ? QLCRD32(adapter, id_reg, &err) : -1);
+ return -EIO;
+ }
+ usleep_range(1000, 2000);
+ }
+
+ if (id_reg)
+ QLCWR32(adapter, id_reg, adapter->portnum);
+
+ return 0;
+}
+
+u32 qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
+{
+ int err;
+ u32 data;
+
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_read_reg_indirect(addr, adapter->ahw->pci_base0, &data);
+ else
+ data = qlcnic_83xx_rd_reg_indirect(adapter, addr, &err);
+
+ return data;
+}
+
+void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
+{
+ if (QLCNIC_IS_82XX(adapter))
+ qlcnic_write_reg_indirect(addr, adapter->ahw->pci_base0, data);
+ else
+ qlcnic_83xx_wrt_reg_indirect(adapter, addr, data);
+}
+
+void
+qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem)
+{
+ int err;
+
+ QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)), &err);
+}
+
+static int
+qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
+ struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
+{
+ u32 i, producer, consumer;
+ struct qlcnic_cmd_buffer *pbuf;
+ struct cmd_desc_type0 *cmd_desc;
+ struct qlcnic_host_tx_ring *tx_ring;
+
+ i = 0;
+
+ if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+ return -EIO;
+
+ tx_ring = adapter->tx_ring;
+ __netif_tx_lock_bh(tx_ring->txq);
+
+ producer = tx_ring->producer;
+ consumer = tx_ring->sw_consumer;
+
+ if (nr_desc >= qlcnic_tx_avail(tx_ring)) {
+ netif_tx_stop_queue(tx_ring->txq);
+ smp_mb();
+ if (qlcnic_tx_avail(tx_ring) > nr_desc) {
+ if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
+ netif_tx_wake_queue(tx_ring->txq);
+ } else {
+ adapter->stats.xmit_off++;
+ __netif_tx_unlock_bh(tx_ring->txq);
+ return -EBUSY;
+ }
+ }
+
+ do {
+ cmd_desc = &cmd_desc_arr[i];
+
+ pbuf = &tx_ring->cmd_buf_arr[producer];
+ pbuf->skb = NULL;
+ pbuf->frag_count = 0;
+
+ memcpy(&tx_ring->desc_head[producer],
+ &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ i++;
+
+ } while (i != nr_desc);
+
+ tx_ring->producer = producer;
+
+ qlcnic_update_cmd_producer(adapter, tx_ring);
+
+ __netif_tx_unlock_bh(tx_ring->txq);
+
+ return 0;
+}
+
+int
+qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
+ __le16 vlan_id, u8 op)
+{
+ struct qlcnic_nic_req req;
+ struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
+ u64 word;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+ word = QLCNIC_MAC_EVENT | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ mac_req = (struct qlcnic_mac_req *)&req.words[0];
+ mac_req->op = op;
+ memcpy(mac_req->mac_addr, addr, 6);
+
+ vlan_req = (struct qlcnic_vlan_req *)&req.words[1];
+ vlan_req->vlan_id = vlan_id;
+
+ return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+}
+
+static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
+{
+ struct list_head *head;
+ struct qlcnic_mac_list_s *cur;
+
+ /* look up if already exists */
+ list_for_each(head, &adapter->mac_list) {
+ cur = list_entry(head, struct qlcnic_mac_list_s, list);
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+ return 0;
+ }
+
+ cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC);
+ if (cur == NULL) {
+ dev_err(&adapter->netdev->dev,
+ "failed to add mac address filter\n");
+ return -ENOMEM;
+ }
+ memcpy(cur->mac_addr, addr, ETH_ALEN);
+
+ if (adapter->ahw->hw_ops->change_macvlan(adapter,
+ cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
+ kfree(cur);
+ return -EIO;
+ }
+
+ list_add_tail(&cur->list, &adapter->mac_list);
+ return 0;
+}
+
+void qlcnic_set_multi(struct net_device *netdev)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct netdev_hw_addr *ha;
+ static const u8 bcast_addr[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ u32 mode = VPORT_MISS_MODE_DROP;
+
+ if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+ return;
+
+ qlcnic_nic_add_mac(adapter, adapter->mac_addr);
+ qlcnic_nic_add_mac(adapter, bcast_addr);
+
+ if (netdev->flags & IFF_PROMISC) {
+ if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
+ mode = VPORT_MISS_MODE_ACCEPT_ALL;
+ goto send_fw_cmd;
+ }
+
+ if ((netdev->flags & IFF_ALLMULTI) ||
+ (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
+ mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+ goto send_fw_cmd;
+ }
+
+ if (!netdev_mc_empty(netdev)) {
+ netdev_for_each_mc_addr(ha, netdev) {
+ qlcnic_nic_add_mac(adapter, ha->addr);
+ }
+ }
+
+send_fw_cmd:
+ if (mode == VPORT_MISS_MODE_ACCEPT_ALL) {
+ qlcnic_alloc_lb_filters_mem(adapter);
+ adapter->mac_learn = 1;
+ } else {
+ adapter->mac_learn = 0;
+ }
+
+ adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
+}
+
+int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE |
+ ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64(mode);
+
+ return qlcnic_send_cmd_descs(adapter,
+ (struct cmd_desc_type0 *)&req, 1);
+}
+
+void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_mac_list_s *cur;
+ struct list_head *head = &adapter->mac_list;
+
+ while (!list_empty(head)) {
+ cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
+ adapter->ahw->hw_ops->change_macvlan(adapter,
+ cur->mac_addr, 0, QLCNIC_MAC_DEL);
+ list_del(&cur->list);
+ kfree(cur);
+ }
+}
+
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
+ {
+ if (jiffies >
+ (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
+ adapter->ahw->hw_ops->change_macvlan(adapter,
+ tmp_fil->faddr, tmp_fil->vlan_id,
+ tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+ QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+ }
+}
+
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ adapter->ahw->hw_ops->change_macvlan(adapter,
+ tmp_fil->faddr, tmp_fil->vlan_id,
+ tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+ QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+}
+
+int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+{
+ struct qlcnic_nic_req req;
+ int rv;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+ req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
+ ((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
+
+ req.words[0] = cpu_to_le64(flag);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
+ flag ? "Set" : "Reset");
+ return rv;
+}
+
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ if (qlcnic_set_fw_loopback(adapter, mode))
+ return -EIO;
+
+ if (adapter->ahw->hw_ops->config_promisc_mode(adapter,
+ VPORT_MISS_MODE_ACCEPT_ALL)) {
+ qlcnic_set_fw_loopback(adapter, 0);
+ return -EIO;
+ }
+
+ msleep(1000);
+ return 0;
+}
+
+int qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ mode = VPORT_MISS_MODE_DROP;
+ qlcnic_set_fw_loopback(adapter, 0);
+
+ if (netdev->flags & IFF_PROMISC)
+ mode = VPORT_MISS_MODE_ACCEPT_ALL;
+ else if (netdev->flags & IFF_ALLMULTI)
+ mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+
+ adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
+ msleep(1000);
+ return 0;
+}
+
+void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_nic_req req;
+ int rv;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ req.req_hdr = cpu_to_le64(QLCNIC_CONFIG_INTR_COALESCE |
+ ((u64) adapter->portnum << 16));
+
+ req.words[0] = cpu_to_le64(((u64) adapter->ahw->coal.flag) << 32);
+ req.words[2] = cpu_to_le64(adapter->ahw->coal.rx_packets |
+ ((u64) adapter->ahw->coal.rx_time_us) << 16);
+ req.words[5] = cpu_to_le64(adapter->ahw->coal.timer_out |
+ ((u64) adapter->ahw->coal.type) << 32 |
+ ((u64) adapter->ahw->coal.sts_ring_mask) << 40);
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "Could not send interrupt coalescing parameters\n");
+}
+
+int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+ int rv;
+
+ if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+ return 0;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64(enable);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "Could not send configure hw lro request\n");
+
+ return rv;
+}
+
+int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+ int rv;
+
+ if (!!(adapter->flags & QLCNIC_BRIDGE_ENABLED) == enable)
+ return 0;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_CONFIG_BRIDGING |
+ ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64(enable);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "Could not send configure bridge mode request\n");
+
+ adapter->flags ^= QLCNIC_BRIDGE_ENABLED;
+
+ return rv;
+}
+
+int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+ int i, rv;
+
+ static const u64 key[] = {
+ 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
+ 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
+ 0x255b0ec26d5a56daULL
+ };
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ /*
+ * RSS request:
+ * bits 3-0: hash_method
+ * 5-4: hash_type_ipv4
+ * 7-6: hash_type_ipv6
+ * 8: enable
+ * 9: use indirection table
+ * 47-10: reserved
+ * 63-48: indirection table mask
+ */
+ word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
+ ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
+ ((u64)(enable & 0x1) << 8) |
+ ((0x7ULL) << 48);
+ req.words[0] = cpu_to_le64(word);
+ for (i = 0; i < 5; i++)
+ req.words[i+1] = cpu_to_le64(key[i]);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev, "could not configure RSS\n");
+
+ return rv;
+}
+
+void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
+{
+ struct qlcnic_nic_req req;
+ struct qlcnic_ipaddr *ipa;
+ u64 word;
+ int rv;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64(cmd);
+ ipa = (struct qlcnic_ipaddr *)&req.words[1];
+ ipa->ipv4 = ip;
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "could not notify %s IP 0x%x request\n",
+ (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
+}
+
+int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+ int rv;
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+ req.words[0] = cpu_to_le64(enable | (enable << 8));
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "could not configure link notification\n");
+
+ return rv;
+}
+
+int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_nic_req req;
+ u64 word;
+ int rv;
+
+ if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+ return 0;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_LRO_REQUEST |
+ ((u64)adapter->portnum << 16) |
+ ((u64)QLCNIC_LRO_REQUEST_CLEANUP << 56) ;
+
+ req.req_hdr = cpu_to_le64(word);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0)
+ dev_err(&adapter->netdev->dev,
+ "could not cleanup lro flows\n");
+
+ return rv;
+}
+
+int qlcnic_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ int rc = 0;
+
+ if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
+ dev_err(&adapter->netdev->dev,
+ "%d bytes < mtu < %d bytes not supported\n",
+ P3P_MAX_MTU, P3P_MIN_MTU);
+ return -EINVAL;
+ }
+
+ rc = qlcnic_fw_cmd_set_mtu(adapter, mtu);
+
+ if (!rc)
+ netdev->mtu = mtu;
+
+ return rc;
+}
+
+netdev_features_t qlcnic_fix_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+
+ if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
+ netdev_features_t changed = features ^ netdev->features;
+ features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
+ }
+
+ if (!(features & NETIF_F_RXCSUM))
+ features &= ~NETIF_F_LRO;
+
+ return features;
+}
+
+int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ netdev_features_t changed = netdev->features ^ features;
+ int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
+
+ if (!(changed & NETIF_F_LRO))
+ return 0;
+
+ netdev->features = features ^ NETIF_F_LRO;
+
+ if (qlcnic_config_hw_lro(adapter, hw_lro))
+ return -EIO;
+
+ if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter))
+ return -EIO;
+
+ return 0;
+}
+
+static int
+qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw,
+ ulong off, void __iomem **addr)
+{
+ const struct crb_128M_2M_sub_block_map *map;
+
+ if ((off >= QLCNIC_CRB_MAX) || (off < QLCNIC_PCI_CRBSPACE))
+ return -EINVAL;
+
+ off -= QLCNIC_PCI_CRBSPACE;
+
+ /* Try direct map */
+ map = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
+
+ if (map->valid && (map->start_128M <= off) && (map->end_128M > off)) {
+ *addr = ahw->pci_base0 + map->start_2M +
+ (off - map->start_128M);
+ return 0;
+ }
+
+ /* Not in direct map, use crb window */
+ *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
+ return 1;
+}
+
+static int
+qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off)
+{
+ u32 window;
+ void __iomem *addr = adapter->ahw->pci_base0 + CRB_WINDOW_2M;
+
+ off -= QLCNIC_PCI_CRBSPACE;
+
+ window = CRB_HI(off);
+ if (window == 0) {
+ dev_err(&adapter->pdev->dev, "Invalid offset 0x%lx\n", off);
+ return -EIO;
+ }
+
+ writel(window, addr);
+ if (readl(addr) != window) {
+ printk_ratelimited(KERN_WARNING
+ "failed to set CRB window to %d off 0x%lx\n",
+ window, off);
+ return -EIO;
+ }
+ return 0;
+}
+
+int
+qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
+{
+ unsigned long flags;
+ int rv;
+ void __iomem *addr = NULL;
+
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
+
+ if (rv == 0) {
+ writel(data, addr);
+ return 0;
+ }
+
+ if (rv > 0) {
+ /* indirect access */
+ write_lock_irqsave(&adapter->ahw->crb_lock, flags);
+ crb_win_lock(adapter);
+ rv = qlcnic_pci_set_crbwindow_2M(adapter, off);
+ if (!rv)
+ writel(data, addr);
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
+ return rv;
+ }
+
+ dev_err(&adapter->pdev->dev,
+ "%s: invalid offset: 0x%016lx\n", __func__, off);
+ dump_stack();
+ return -EIO;
+}
+
+u32
+qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *err)
+{
+ unsigned long flags;
+ int rv;
+ u32 data = -1;
+ void __iomem *addr = NULL;
+
+ rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
+
+ if (rv == 0)
+ return readl(addr);
+
+ if (rv > 0) {
+ /* indirect access */
+ write_lock_irqsave(&adapter->ahw->crb_lock, flags);
+ crb_win_lock(adapter);
+ if (!qlcnic_pci_set_crbwindow_2M(adapter, off))
+ data = readl(addr);
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
+ return data;
+ }
+
+ dev_err(&adapter->pdev->dev,
+ "%s: invalid offset: 0x%016lx\n", __func__, off);
+ dump_stack();
+ if (err)
+ *err = -1;
+
+ return -1;
+}
+
+
+void __iomem *
+qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, u32 offset)
+{
+ void __iomem *addr = NULL;
+
+ WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr));
+
+ return addr;
+}
+
+static int
+qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u32 window,
+ u64 off, u64 *data, int op)
+{
+ void __iomem *addr;
+ u32 start;
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ writel(window, adapter->ahw->ocm_win_crb);
+ /* read back to flush */
+ readl(adapter->ahw->ocm_win_crb);
+ start = QLCNIC_PCI_OCM0_2M + off;
+
+ addr = adapter->ahw->pci_base0 + start;
+
+ if (op == 0)
+ *data = readq(addr);
+ else
+ writeq(*data, addr);
+
+ /* Set window to 0 */
+ writel(0, adapter->ahw->ocm_win_crb);
+ readl(adapter->ahw->ocm_win_crb);
+
+ mutex_unlock(&adapter->ahw->mem_lock);
+ return 0;
+}
+
+void
+qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
+{
+ void __iomem *addr = adapter->ahw->pci_base0 +
+ QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
+
+ mutex_lock(&adapter->ahw->mem_lock);
+ *data = readq(addr);
+ mutex_unlock(&adapter->ahw->mem_lock);
+}
+
+void
+qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
+{
+ void __iomem *addr = adapter->ahw->pci_base0 +
+ QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
+
+ mutex_lock(&adapter->ahw->mem_lock);
+ writeq(data, addr);
+ mutex_unlock(&adapter->ahw->mem_lock);
+}
+
+#define MAX_CTL_CHECK 1000
+
+/* Set MS memory control data for different chip type*/
+static void
+qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off,
+ struct qlcnic_ms_reg_ctrl *ms)
+{
+ ms->control = QLCNIC_MS_CTRL;
+ ms->low = QLCNIC_MS_ADDR_LO;
+ ms->hi = QLCNIC_MS_ADDR_HI;
+ if (off & 0xf) {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_LO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_LO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_HI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_ULO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_ULO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_UHI;
+ } else {
+ ms->wd[0] = QLCNIC_MS_WRTDATA_ULO;
+ ms->rd[0] = QLCNIC_MS_RDDATA_ULO;
+ ms->wd[1] = QLCNIC_MS_WRTDATA_UHI;
+ ms->rd[1] = QLCNIC_MS_RDDATA_UHI;
+ ms->wd[2] = QLCNIC_MS_WRTDATA_LO;
+ ms->wd[3] = QLCNIC_MS_WRTDATA_HI;
+ ms->rd[2] = QLCNIC_MS_RDDATA_LO;
+ ms->rd[3] = QLCNIC_MS_RDDATA_HI;
+ }
+ if (QLCNIC_IS_83XX(adapter)) {
+ ms->ocm_window = OCM_WIN_83XX(off);
+ ms->off = GET_83XX_OCM_OFFSET(off);
+ } else {
+ ms->ocm_window = OCM_WIN_P3P(off);
+ ms->off = GET_MEM_OFFS_2M(off);
+ }
+}
+
+int
+qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
+ u64 off, u64 data)
+{
+ int j, ret = 0;
+ u32 temp, off8;
+ struct qlcnic_ms_reg_ctrl ms;
+
+ /* Only 64-bit aligned access */
+ if (off & 7)
+ return -EIO;
+
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX)) ||
+ (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX))))
+ return -EIO;
+
+ qlcnic_set_ms_controls(adapter, off, &ms);
+
+ if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, &data, 1);
+
+ off8 = off & ~0xf;
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
+
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = qlcnic_ind_rd(adapter, ms.control);
+ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ ret = -EIO;
+ goto done;
+ }
+
+ /* This is the modify part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0]));
+ qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1]));
+ /* This is the write part of read-modify-write */
+ qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff);
+ qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff);
+
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_START);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = qlcnic_ind_rd(adapter, ms.control);
+ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_WARNING
+ "failed to write through agent\n");
+ ret = -EIO;
+ } else
+ ret = 0;
+
+done:
+ mutex_unlock(&adapter->ahw->mem_lock);
+
+ return ret;
+}
+
+int
+qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
+ u64 off, u64 *data)
+{
+ int j, ret;
+ u32 temp, off8;
+ u64 val;
+ struct qlcnic_ms_reg_ctrl ms;
+
+ /* Only 64-bit aligned access */
+ if (off & 7)
+ return -EIO;
+ if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+ QLCNIC_ADDR_QDR_NET_MAX)) ||
+ (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+ QLCNIC_ADDR_DDR_NET_MAX))))
+ return -EIO ;
+
+ memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+ qlcnic_set_ms_controls(adapter, off, &ms);
+
+ if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
+ return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+ ms.off, data, 0);
+
+ mutex_lock(&adapter->ahw->mem_lock);
+
+ off8 = off & ~0xf;
+
+ qlcnic_ind_wr(adapter, ms.low, off8);
+ qlcnic_ind_wr(adapter, ms.hi, 0);
+
+ qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+ qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = qlcnic_ind_rd(adapter, ms.control);
+ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_WARNING
+ "failed to read through agent\n");
+ ret = -EIO;
+ } else {
+
+ temp = qlcnic_ind_rd(adapter, ms.rd[3]);
+ val = (u64)temp << 32;
+ val |= qlcnic_ind_rd(adapter, ms.rd[2]);
+ *data = val;
+ ret = 0;
+ }
+
+ mutex_unlock(&adapter->ahw->mem_lock);
+
+ return ret;
+}
+
+int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
+{
+ int offset, board_type, magic, err;
+ struct pci_dev *pdev = adapter->pdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ offset = QLCNIC_FW_MAGIC_OFFSET;
+ if (qlcnic_rom_fast_read(adapter, offset, &magic))
+ return -EIO;
+
+ if (magic != QLCNIC_BDINFO_MAGIC) {
+ dev_err(&pdev->dev, "invalid board config, magic=%08x\n",
+ magic);
+ return -EIO;
+ }
+
+ offset = QLCNIC_BRDTYPE_OFFSET;
+ if (qlcnic_rom_fast_read(adapter, offset, &board_type))
+ return -EIO;
+
+ ahw->board_type = board_type;
+
+ if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
+ u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I, &err);
+ if ((gpio & 0x8000) == 0)
+ board_type = QLCNIC_BRDTYPE_P3P_10G_TP;
+ }
+
+ switch (board_type) {
+ case QLCNIC_BRDTYPE_P3P_HMEZ:
+ case QLCNIC_BRDTYPE_P3P_XG_LOM:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+ case QLCNIC_BRDTYPE_P3P_IMEZ:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
+ case QLCNIC_BRDTYPE_P3P_10G_XFP:
+ case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
+ ahw->port_type = QLCNIC_XGBE;
+ break;
+ case QLCNIC_BRDTYPE_P3P_REF_QG:
+ case QLCNIC_BRDTYPE_P3P_4_GB:
+ case QLCNIC_BRDTYPE_P3P_4_GB_MM:
+ ahw->port_type = QLCNIC_GBE;
+ break;
+ case QLCNIC_BRDTYPE_P3P_10G_TP:
+ ahw->port_type = (adapter->portnum < 2) ?
+ QLCNIC_XGBE : QLCNIC_GBE;
+ break;
+ default:
+ dev_err(&pdev->dev, "unknown board type %x\n", board_type);
+ ahw->port_type = QLCNIC_XGBE;
+ break;
+ }
+
+ return 0;
+}
+
+int
+qlcnic_wol_supported(struct qlcnic_adapter *adapter)
+{
+ int err;
+ u32 wol_cfg;
+
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
+ if (wol_cfg & (1UL << adapter->portnum)) {
+ wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
+ if (wol_cfg & (1 << adapter->portnum))
+ return 1;
+ }
+
+ return 0;
+}
+
+int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
+{
+ struct qlcnic_nic_req req;
+ int rv;
+ u64 word;
+
+ memset(&req, 0, sizeof(struct qlcnic_nic_req));
+ req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+ word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64((u64)rate << 32);
+ req.words[1] = cpu_to_le64(state);
+
+ rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv)
+ dev_err(&adapter->pdev->dev, "LED configuration failed.\n");
+
+ return rv;
+}
+
+void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
+{
+ void __iomem *msix_base_addr;
+ u32 func;
+ u32 msix_base;
+
+ pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
+ msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
+ msix_base = readl(msix_base_addr);
+ func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
+ adapter->ahw->pci_func = func;
+}
+
+void qlcnic_get_ocm_win(struct qlcnic_hardware_context *ahw)
+{
+ ahw->ocm_win_crb = qlcnic_get_ioaddr(ahw, QLCNIC_PCIX_PS_REG(
+ PCIX_OCM_WINDOW_REG(ahw->pci_func)));
+}
+
+void qlcnic_read_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ int err;
+ u32 data;
+ u64 qmdata;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+ memcpy(buf, &qmdata, size);
+ } else {
+ data = QLCRD32(adapter, offset, &err);
+ memcpy(buf, &data, size);
+ }
+}
+
+void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf,
+ loff_t offset, size_t size)
+{
+ u32 data;
+ u64 qmdata;
+
+ if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+ memcpy(&qmdata, buf, size);
+ qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+ } else {
+ memcpy(&data, buf, size);
+ QLCWR32(adapter, offset, data);
+ }
+}
+
+int qlcnic_api_lock(struct qlcnic_adapter *adapter)
+{
+ return qlcnic_pcie_sem_lock(adapter, 5, 0);
+}
+
+void qlcnic_api_unlock(struct qlcnic_adapter *adapter)
+{
+ qlcnic_pcie_sem_unlock(adapter, 5);
+}
+
+void qlcnic_add_sysfs(struct qlcnic_adapter *adapter)
+{
+ qlcnic_create_diag_entries(adapter);
+}
+
+void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter)
+{
+ qlcnic_remove_diag_entries(adapter);
+}
+
+/* Array of FW control command structs with command type and required
+ * number of input and output arguments respectively.
+*/
+static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
+ { QLCNIC_CMD_CREATE_RX_CTX, 4, 1 },
+ { QLCNIC_CMD_DESTROY_RX_CTX, 2, 1 },
+ { QLCNIC_CMD_CREATE_TX_CTX, 4, 1 },
+ { QLCNIC_CMD_DESTROY_TX_CTX, 2, 1 },
+ { QLCNIC_CMD_INTRPT_TEST, 4, 1 },
+ { QLCNIC_CMD_SET_MTU, 4, 1 },
+ { QLCNIC_CMD_READ_PHY, 4, 2 },
+ { QLCNIC_CMD_WRITE_PHY, 5, 1 },
+ { QLCNIC_CMD_READ_HW_REG, 4, 1 },
+ { QLCNIC_CMD_GET_FLOW_CTL, 4, 2 },
+ { QLCNIC_CMD_SET_FLOW_CTL, 4, 1 },
+ { QLCNIC_CMD_READ_MAX_MTU, 4, 2 },
+ { QLCNIC_CMD_READ_MAX_LRO, 4, 2 },
+ { QLCNIC_CMD_MAC_ADDRESS, 4, 3 },
+ { QLCNIC_CMD_GET_PCI_INFO, 4, 1 },
+ { QLCNIC_CMD_GET_NIC_INFO, 4, 1 },
+ { QLCNIC_CMD_SET_NIC_INFO, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3 },
+ { QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3 },
+ { QLCNIC_CMD_SET_PORTMIRRORING, 4, 1 },
+ { QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1 },
+ { QLCNIC_CMD_GET_MAC_STATS, 4, 1 },
+ { QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3 },
+ { QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1 },
+ { QLCNIC_CMD_CONFIG_PORT, 4, 1 },
+ { QLCNIC_CMD_TEMP_SIZE, 4, 4 },
+ { QLCNIC_CMD_GET_TEMP_HDR, 4, 1 },
+ { QLCNIC_CMD_SET_DRV_VER, 4, 1 },
+};
+
+/* Allocate mailbox incoming and outgoing registers. It should be used with a
+ * follow up call to qlcnic_free_mbx_args
+ */
+int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
+ struct qlcnic_adapter *adapter, u32 type)
+{
+ int i, size;
+ const struct qlcnic_mailbox_metadata *mbx_tbl;
+
+ mbx_tbl = qlcnic_mbx_tbl;
+ size = ARRAY_SIZE(qlcnic_mbx_tbl);
+ for (i = 0; i < size; i++) {
+ if (type == mbx_tbl[i].cmd) {
+ mbx->req.num = mbx_tbl[i].in_args;
+ mbx->rsp.num = mbx_tbl[i].out_args;
+ mbx->req.arg = kcalloc(mbx->req.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->req.arg)
+ return -ENOMEM;
+ mbx->rsp.arg = kcalloc(mbx->rsp.num,
+ sizeof(u32), GFP_ATOMIC);
+ if (!mbx->rsp.arg) {
+ kfree(mbx->req.arg);
+ mbx->req.arg = NULL;
+ return -ENOMEM;
+ }
+ memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
+ memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
+ mbx->req.arg[0] = type;
+ break;
+ }
+ }
+ return 0;
+}
+
+void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
+{
+ kfree(cmd->req.arg);
+ cmd->req.arg = NULL;
+ kfree(cmd->rsp.arg);
+ cmd->rsp.arg = NULL;
+}
+
+
+static u32
+qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
+{
+ u32 rsp;
+ int err, timeout = 0;
+
+ do {
+ /* give atleast 1ms for firmware to respond */
+ usleep_range(1000, 2000);
+
+ if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
+ return QLCNIC_CDRP_RSP_TIMEOUT;
+
+ rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET, &err);
+ } while (!QLCNIC_CDRP_IS_RSP(rsp));
+
+ return rsp;
+}
+
+int
+qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
+{
+ int i, err;
+ u32 rsp;
+ u32 signature;
+ struct pci_dev *pdev = adapter->pdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+
+ signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw);
+
+ /* Acquire semaphore before accessing CRB */
+ if (ahw->hw_ops->api_lock(adapter)) {
+ cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
+ return cmd->rsp.arg[0];
+ }
+
+ QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
+ for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
+ QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
+ QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
+ QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
+ rsp = qlcnic_poll_rsp(adapter);
+
+ if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
+ dev_err(&pdev->dev, "card response timeout.\n");
+ cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
+ } else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
+ cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
+ dev_err(&pdev->dev, "failed card response code:0x%x\n",
+ cmd->rsp.arg[0]);
+ } else if (rsp == QLCNIC_CDRP_RSP_OK)
+ cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
+
+ for (i = 1; i < cmd->rsp.num; i++)
+ cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i), &err);
+
+ /* Release semaphore */
+ ahw->hw_ops->api_unlock(adapter);
+ return cmd->rsp.arg[0];
+}
+
+int
+qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
+{
+ int err = 0;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
+ return err;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_MTU);
+ cmd.req.arg[1] = recv_ctx->context_id;
+ cmd.req.arg[2] = mtu;
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
+ err = -EIO;
+ }
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int
+qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter)
+{
+ int err = 0;
+ struct qlcnic_cmd_args cmd;
+ char drv_string[12];
+
+ memset(drv_string, 0 , sizeof(drv_string));
+ snprintf(drv_string, sizeof(drv_string), "%d"".""%d"".""%d",
+ _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR,
+ _QLCNIC_LINUX_SUBVERSION);
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_DRV_VER);
+ memcpy(&cmd.req.arg[1], drv_string, sizeof(u32));
+ memcpy(&cmd.req.arg[2], drv_string + 4, sizeof(u32));
+ memcpy(&cmd.req.arg[3], drv_string + 8, sizeof(u32));
+
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to drv ver in fw\n");
+ err = -EIO;
+ }
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int
+qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
+{
+ void *addr;
+ struct qlcnic_hostrq_rx_ctx *prq;
+ struct qlcnic_cardrsp_rx_ctx *prsp;
+ struct qlcnic_hostrq_rds_ring *prq_rds;
+ struct qlcnic_hostrq_sds_ring *prq_sds;
+ struct qlcnic_cardrsp_rds_ring *prsp_rds;
+ struct qlcnic_cardrsp_sds_ring *prsp_sds;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_cmd_args cmd;
+
+ dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
+ u64 phys_addr;
+
+ u8 i, nrds_rings, nsds_rings;
+ size_t rq_size, rsp_size;
+ u32 cap, reg, val, reg2;
+ int err;
+
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ nrds_rings = adapter->max_rds_rings;
+ nsds_rings = adapter->max_sds_rings;
+
+ rq_size =
+ SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
+ nsds_rings);
+ rsp_size =
+ SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings,
+ nsds_rings);
+
+ addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+ &hostrq_phys_addr, GFP_KERNEL);
+ if (addr == NULL)
+ return -ENOMEM;
+ prq = addr;
+
+ addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+ &cardrsp_phys_addr, GFP_KERNEL);
+ if (addr == NULL) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ prsp = addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
+
+ cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN
+ | QLCNIC_CAP0_VALIDOFF);
+ cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
+
+ if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+ cap |= QLCNIC_CAP0_LRO_MSS;
+
+ prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
+ msix_handler);
+ prq->txrx_sds_binding = nsds_rings - 1;
+
+ prq->capabilities[0] = cpu_to_le32(cap);
+ prq->host_int_crb_mode =
+ cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
+ prq->host_rds_crb_mode =
+ cpu_to_le32(QLCNIC_HOST_RDS_CRB_MODE_UNIQUE);
+
+ prq->num_rds_rings = cpu_to_le16(nrds_rings);
+ prq->num_sds_rings = cpu_to_le16(nsds_rings);
+ prq->rds_ring_offset = 0;
+
+ val = le32_to_cpu(prq->rds_ring_offset) +
+ (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings);
+ prq->sds_ring_offset = cpu_to_le32(val);
+
+ prq_rds = (struct qlcnic_hostrq_rds_ring *)(prq->data +
+ le32_to_cpu(prq->rds_ring_offset));
+
+ for (i = 0; i < nrds_rings; i++) {
+
+ rds_ring = &recv_ctx->rds_rings[i];
+ rds_ring->producer = 0;
+
+ prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
+ prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
+ prq_rds[i].ring_kind = cpu_to_le32(i);
+ prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
+ }
+
+ prq_sds = (struct qlcnic_hostrq_sds_ring *)(prq->data +
+ le32_to_cpu(prq->sds_ring_offset));
+
+ for (i = 0; i < nsds_rings; i++) {
+
+ sds_ring = &recv_ctx->sds_rings[i];
+ sds_ring->consumer = 0;
+ memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));
+
+ prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
+ prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
+ prq_sds[i].msi_index = cpu_to_le16(i);
+ }
+
+ phys_addr = hostrq_phys_addr;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_RX_CTX);
+ cmd.req.arg[1] = MSD(phys_addr);
+ cmd.req.arg[2] = LSD(phys_addr);
+ cmd.req.arg[3] = rq_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create rx ctx in firmware%d\n", err);
+ goto out_free_rsp;
+ }
+
+ prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
+ &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
+
+ for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
+ rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg;
+ }
+
+ prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
+ &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
+
+ for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) {
+ sds_ring = &recv_ctx->sds_rings[i];
+
+ reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
+ reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);
+
+ sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg;
+ sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2;
+ }
+
+ recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
+ recv_ctx->context_id = le16_to_cpu(prsp->context_id);
+ recv_ctx->virt_port = prsp->virt_port;
+
+out_free_rsp:
+ dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
+ cardrsp_phys_addr);
+ qlcnic_free_mbx_args(&cmd);
+out_free_rq:
+ dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
+ return err;
+}
+
+static void
+qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_DESTROY_RX_CTX);
+ cmd.req.arg[1] = recv_ctx->context_id;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err)
+ dev_err(&adapter->pdev->dev,
+ "Failed to destroy rx ctx in firmware\n");
+
+ recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
+ qlcnic_free_mbx_args(&cmd);
+}
+
+int
+qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring, int ring)
+{
+ struct qlcnic_hostrq_tx_ctx *prq;
+ struct qlcnic_hostrq_cds_ring *prq_cds;
+ struct qlcnic_cardrsp_tx_ctx *prsp;
+ void *rq_addr, *rsp_addr;
+ size_t rq_size, rsp_size;
+ u32 temp;
+ struct qlcnic_cmd_args cmd;
+ int err;
+ u64 phys_addr;
+ dma_addr_t rq_phys_addr, rsp_phys_addr;
+
+ /* reset host resources */
+ tx_ring->producer = 0;
+ tx_ring->sw_consumer = 0;
+ *(tx_ring->hw_consumer) = 0;
+
+ rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
+ rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+ &rq_phys_addr, GFP_KERNEL);
+ if (!rq_addr)
+ return -ENOMEM;
+
+ rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
+ rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+ &rsp_phys_addr, GFP_KERNEL);
+ if (!rsp_addr) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+
+ memset(rq_addr, 0, rq_size);
+ prq = rq_addr;
+
+ memset(rsp_addr, 0, rsp_size);
+ prsp = rsp_addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
+
+ temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN |
+ QLCNIC_CAP0_LSO);
+ prq->capabilities[0] = cpu_to_le32(temp);
+
+ prq->host_int_crb_mode =
+ cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
+ prq->msi_index = 0;
+
+ prq->interrupt_ctl = 0;
+ prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
+
+ prq_cds = &prq->cds_ring;
+
+ prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
+ prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
+
+ phys_addr = rq_phys_addr;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CREATE_TX_CTX);
+ cmd.req.arg[1] = MSD(phys_addr);
+ cmd.req.arg[2] = LSD(phys_addr);
+ cmd.req.arg[3] = rq_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
+ tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
+ tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create tx ctx in firmware%d\n", err);
+ err = -EIO;
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
+ rsp_phys_addr);
+
+out_free_rq:
+ dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+static void
+qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring)
+{
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_DESTROY_TX_CTX);
+ cmd.req.arg[1] = tx_ring->ctx_id;
+ if (adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd))
+ dev_err(&adapter->pdev->dev,
+ "Failed to destroy tx ctx in firmware\n");
+ qlcnic_free_mbx_args(&cmd);
+}
+
+int
+qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
+{
+ int err;
+ struct qlcnic_cmd_args cmd;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIG_PORT);
+ cmd.req.arg[1] = config;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
+{
+ void *addr;
+ int err, ring;
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+
+ struct pci_dev *pdev = adapter->pdev;
+
+ recv_ctx = adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
+ sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
+ if (tx_ring->hw_consumer == NULL) {
+ dev_err(&pdev->dev, "failed to allocate tx consumer\n");
+ return -ENOMEM;
+ }
+ /* cmd desc ring */
+ addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
+ &tx_ring->phys_addr, GFP_KERNEL);
+
+ if (addr == NULL) {
+ dev_err(&pdev->dev,
+ "failed to allocate tx desc ring\n");
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+
+ tx_ring->desc_head = addr;
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ addr = dma_alloc_coherent(&adapter->pdev->dev,
+ RCV_DESC_RINGSIZE(rds_ring),
+ &rds_ring->phys_addr, GFP_KERNEL);
+ if (addr == NULL) {
+ dev_err(&pdev->dev,
+ "failed to allocate rds ring [%d]\n", ring);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ rds_ring->desc_head = addr;
+
+ }
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+
+ addr = dma_alloc_coherent(&adapter->pdev->dev,
+ STATUS_DESC_RINGSIZE(sds_ring),
+ &sds_ring->phys_addr, GFP_KERNEL);
+ if (addr == NULL) {
+ dev_err(&pdev->dev,
+ "failed to allocate sds ring [%d]\n", ring);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ sds_ring->desc_head = addr;
+ }
+
+ return 0;
+
+err_out_free:
+ qlcnic_free_hw_resources(adapter);
+ return err;
+}
+
+int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
+{
+ int i, err, ring;
+
+ if (adapter->flags & QLCNIC_NEED_FLR) {
+ pci_reset_function(adapter->pdev);
+ adapter->flags &= ~QLCNIC_NEED_FLR;
+ }
+
+ err = adapter->ahw->hw_ops->create_rx_ctx(adapter);
+ if (err)
+ return err;
+
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ err = adapter->ahw->hw_ops->create_tx_ctx(adapter,
+ &adapter->tx_ring[ring], ring);
+ if (err) {
+ qlcnic_fw_cmd_destroy_rx_ctx(adapter);
+ if (ring == 0)
+ return err;
+ for (i = 0; i < ring; i++)
+ qlcnic_fw_cmd_destroy_tx_ctx(adapter,
+ &adapter->tx_ring[i]);
+ return err;
+ }
+ }
+
+ set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
+ return 0;
+}
+
+void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
+{
+ int ring;
+
+ if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
+ qlcnic_fw_cmd_destroy_rx_ctx(adapter);
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
+ qlcnic_fw_cmd_destroy_tx_ctx(adapter,
+ &adapter->tx_ring[ring]);
+
+ /* Allow dma queues to drain after context reset */
+ msleep(20);
+ }
+}
+
+void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_recv_context *recv_ctx;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_tx_ring *tx_ring;
+ int ring;
+
+ recv_ctx = adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ if (tx_ring->hw_consumer != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ sizeof(u32),
+ tx_ring->hw_consumer,
+ tx_ring->hw_cons_phys_addr);
+ tx_ring->hw_consumer = NULL;
+ }
+
+ if (tx_ring->desc_head != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ TX_DESC_RINGSIZE(tx_ring),
+ tx_ring->desc_head, tx_ring->phys_addr);
+ tx_ring->desc_head = NULL;
+ }
+ }
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ if (rds_ring->desc_head != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ RCV_DESC_RINGSIZE(rds_ring),
+ rds_ring->desc_head,
+ rds_ring->phys_addr);
+ rds_ring->desc_head = NULL;
+ }
+ }
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+
+ if (sds_ring->desc_head != NULL) {
+ dma_free_coherent(&adapter->pdev->dev,
+ STATUS_DESC_RINGSIZE(sds_ring),
+ sds_ring->desc_head,
+ sds_ring->phys_addr);
+ sds_ring->desc_head = NULL;
+ }
+ }
+}
+
+/* Get MAC address of a NIC partition */
+int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
+{
+ int err, i;
+ struct qlcnic_cmd_args cmd;
+ u32 mac_low, mac_high;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_MAC_ADDRESS);
+ cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ mac_low = cmd.rsp.arg[1];
+ mac_high = cmd.rsp.arg[2];
+
+ for (i = 0; i < 2; i++)
+ mac[i] = (u8) (mac_high >> ((1 - i) * 8));
+ for (i = 2; i < 6; i++)
+ mac[i] = (u8) (mac_low >> ((5 - i) * 8));
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get mac address%d\n", err);
+ err = -EIO;
+ }
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
+ struct qlcnic_info *npar_info, u8 func_id)
+{
+ int err;
+ dma_addr_t nic_dma_t;
+ const struct qlcnic_info *nic_info;
+ void *nic_info_addr;
+ struct qlcnic_cmd_args cmd;
+ size_t nic_size = sizeof(struct qlcnic_info);
+
+ nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+ &nic_dma_t, GFP_KERNEL);
+ if (!nic_info_addr)
+ return -ENOMEM;
+ memset(nic_info_addr, 0, nic_size);
+
+ nic_info = nic_info_addr;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_NIC_INFO);
+ cmd.req.arg[1] = MSD(nic_dma_t);
+ cmd.req.arg[2] = LSD(nic_dma_t);
+ cmd.req.arg[3] = (func_id << 16 | nic_size);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (err == QLCNIC_RCODE_SUCCESS)
+ qlcnic_set_npar_data(adapter, nic_info, npar_info);
+ else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get nic info%d\n", err);
+ err = -EIO;
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
+ nic_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
+{
+ int err = -EIO;
+ dma_addr_t nic_dma_t;
+ void *nic_info_addr;
+ struct qlcnic_cmd_args cmd;
+ struct qlcnic_info *nic_info;
+ size_t nic_size = sizeof(struct qlcnic_info);
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return err;
+
+ nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+ &nic_dma_t, GFP_KERNEL);
+ if (!nic_info_addr)
+ return -ENOMEM;
+
+ memset(nic_info_addr, 0, nic_size);
+ nic_info = nic_info_addr;
+
+ nic_info->pci_func = cpu_to_le16(nic->pci_func);
+ nic_info->op_mode = cpu_to_le16(nic->op_mode);
+ nic_info->phys_port = cpu_to_le16(nic->phys_port);
+ nic_info->switch_mode = cpu_to_le16(nic->switch_mode);
+ nic_info->capabilities = cpu_to_le32(nic->capabilities);
+ nic_info->max_mac_filters = nic->max_mac_filters;
+ nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques);
+ nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques);
+ nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
+ nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_NIC_INFO);
+ cmd.req.arg[1] = MSD(nic_dma_t);
+ cmd.req.arg[2] = LSD(nic_dma_t);
+ cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err != QLCNIC_RCODE_SUCCESS) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to set nic info%d\n", err);
+ err = -EIO;
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
+ nic_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
+ struct qlcnic_pci_info *pci_info)
+{
+ int err = 0, i;
+ struct qlcnic_cmd_args cmd;
+ dma_addr_t pci_info_dma_t;
+ struct qlcnic_pci_info *npar;
+ void *pci_info_addr;
+ size_t npar_size = sizeof(struct qlcnic_pci_info);
+ size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
+
+ pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
+ &pci_info_dma_t, GFP_KERNEL);
+ if (!pci_info_addr)
+ return -ENOMEM;
+ memset(pci_info_addr, 0, pci_size);
+
+ npar = pci_info_addr;
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_PCI_INFO);
+ cmd.req.arg[1] = MSD(pci_info_dma_t);
+ cmd.req.arg[2] = LSD(pci_info_dma_t);
+ cmd.req.arg[3] = pci_size;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ adapter->ahw->act_pci_func = 0;
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
+ pci_info->id = le16_to_cpu(npar->id);
+ pci_info->active = le16_to_cpu(npar->active);
+ pci_info->type = le16_to_cpu(npar->type);
+ if (pci_info->type == QLCNIC_TYPE_NIC)
+ adapter->ahw->act_pci_func++;
+ pci_info->default_port =
+ le16_to_cpu(npar->default_port);
+ pci_info->tx_min_bw =
+ le16_to_cpu(npar->tx_min_bw);
+ pci_info->tx_max_bw =
+ le16_to_cpu(npar->tx_max_bw);
+ memcpy(pci_info->mac, npar->mac, ETH_ALEN);
+ }
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get PCI Info%d\n", err);
+ err = -EIO;
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
+ pci_info_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
+ u8 enable_mirroring, u8 pci_func)
+{
+ int err = -EIO;
+ u32 arg1;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
+ !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
+ return err;
+
+ arg1 = id | (enable_mirroring ? BIT_4 : 0);
+ arg1 |= pci_func << 8;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_SET_PORTMIRRORING);
+ cmd.req.arg[1] = arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (err != QLCNIC_RCODE_SUCCESS)
+ dev_err(&adapter->pdev->dev,
+ "Failed to configure port mirroring%d on eswitch:%d\n",
+ pci_func, id);
+ else
+ dev_info(&adapter->pdev->dev,
+ "Configured eSwitch %d for port mirroring:%d\n",
+ id, pci_func);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
+ struct __qlcnic_esw_statistics *stats;
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ u32 arg1;
+ struct qlcnic_cmd_args cmd;
+ int err;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC &&
+ func != adapter->ahw->pci_func) {
+ dev_err(&adapter->pdev->dev,
+ "Not privilege to query stats for func=%d", func);
+ return -EIO;
+ }
+
+ stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+ &stats_dma_t, GFP_KERNEL);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
+
+ arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
+ arg1 |= rx_tx << 15 | stats_size << 16;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_STATS);
+ cmd.req.arg[1] = arg1;
+ cmd.req.arg[2] = MSD(stats_dma_t);
+ cmd.req.arg[3] = LSD(stats_dma_t);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+
+ if (!err) {
+ stats = stats_addr;
+ esw_stats->context_id = le16_to_cpu(stats->context_id);
+ esw_stats->version = le16_to_cpu(stats->version);
+ esw_stats->size = le16_to_cpu(stats->size);
+ esw_stats->multicast_frames =
+ le64_to_cpu(stats->multicast_frames);
+ esw_stats->broadcast_frames =
+ le64_to_cpu(stats->broadcast_frames);
+ esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
+ esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
+ esw_stats->local_frames = le64_to_cpu(stats->local_frames);
+ esw_stats->errors = le64_to_cpu(stats->errors);
+ esw_stats->numbytes = le64_to_cpu(stats->numbytes);
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
+ stats_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+
+ return err;
+}
+
+int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
+ struct qlcnic_mac_statistics *mac_stats)
+{
+ struct qlcnic_mac_statistics *stats;
+ struct qlcnic_cmd_args cmd;
+ size_t stats_size = sizeof(struct qlcnic_mac_statistics);
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ int err;
+
+ if (mac_stats == NULL)
+ return -ENOMEM;
+
+ stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+ &stats_dma_t, GFP_KERNEL);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Unable to allocate memory.\n", __func__);
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_MAC_STATS);
+ cmd.req.arg[1] = stats_size << 16;
+ cmd.req.arg[2] = MSD(stats_dma_t);
+ cmd.req.arg[3] = LSD(stats_dma_t);
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ if (!err) {
+ stats = stats_addr;
+ mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
+ mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
+ mac_stats->mac_tx_mcast_pkts =
+ le64_to_cpu(stats->mac_tx_mcast_pkts);
+ mac_stats->mac_tx_bcast_pkts =
+ le64_to_cpu(stats->mac_tx_bcast_pkts);
+ mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
+ mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
+ mac_stats->mac_rx_mcast_pkts =
+ le64_to_cpu(stats->mac_rx_mcast_pkts);
+ mac_stats->mac_rx_length_error =
+ le64_to_cpu(stats->mac_rx_length_error);
+ mac_stats->mac_rx_length_small =
+ le64_to_cpu(stats->mac_rx_length_small);
+ mac_stats->mac_rx_length_large =
+ le64_to_cpu(stats->mac_rx_length_large);
+ mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
+ mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
+ mac_stats->mac_FCS_error = le64_to_cpu(stats->mac_FCS_error);
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
+ stats_dma_t);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+}
+
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ struct __qlcnic_esw_statistics port_stats;
+ u8 i;
+ int ret = -EIO;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+ if (adapter->npars == NULL)
+ return -EIO;
+
+ memset(esw_stats, 0, sizeof(u64));
+ esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->context_id = eswitch;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].phy_port != eswitch)
+ continue;
+
+ memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+ continue;
+
+ esw_stats->size = port_stats.size;
+ esw_stats->version = port_stats.version;
+ QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
+ port_stats.unicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
+ port_stats.multicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
+ port_stats.broadcast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
+ port_stats.dropped_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->errors,
+ port_stats.errors);
+ QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
+ port_stats.local_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
+ port_stats.numbytes);
+ ret = 0;
+ }
+ return ret;
+}
+
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
+ const u8 port, const u8 rx_tx)
+{
+ int err;
+ u32 arg1;
+ struct qlcnic_cmd_args cmd;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+
+ if (func_esw == QLCNIC_STATS_PORT) {
+ if (port >= QLCNIC_MAX_PCI_FUNC)
+ goto err_ret;
+ } else if (func_esw == QLCNIC_STATS_ESWITCH) {
+ if (port >= QLCNIC_NIU_MAX_XG_PORTS)
+ goto err_ret;
+ } else {
+ goto err_ret;
+ }
+
+ if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
+ goto err_ret;
+
+ arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
+ arg1 |= BIT_14 | rx_tx << 15;
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_STATS);
+ cmd.req.arg[1] = arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
+ return err;
+
+err_ret:
+ dev_err(&adapter->pdev->dev,
+ "Invalid arguments func_esw=%d port=%d rx_ctx=%d\n",
+ func_esw, port, rx_tx);
+ return -EIO;
+}
+
+static int
+__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+ u32 *arg1, u32 *arg2)
+{
+ int err = -EIO;
+ struct qlcnic_cmd_args cmd;
+ u8 pci_func;
+ pci_func = (*arg1 >> 8);
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
+ cmd.req.arg[1] = *arg1;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ *arg1 = cmd.rsp.arg[1];
+ *arg2 = cmd.rsp.arg[2];
+ qlcnic_free_mbx_args(&cmd);
+
+ if (err == QLCNIC_RCODE_SUCCESS)
+ dev_info(&adapter->pdev->dev,
+ "eSwitch port config for pci func %d\n", pci_func);
+ else
+ dev_err(&adapter->pdev->dev,
+ "Failed to get eswitch port config for pci func %d\n",
+ pci_func);
+ return err;
+}
+
+int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ int err = -EIO;
+ u32 arg1, arg2 = 0;
+ struct qlcnic_cmd_args cmd;
+ u8 pci_func;
+
+ if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+ return err;
+ pci_func = esw_cfg->pci_func;
+ arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+ arg1 |= (pci_func << 8);
+
+ if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
+ return err;
+ arg1 &= ~(0x0ff << 8);
+ arg1 |= (pci_func << 8);
+ arg1 &= ~(BIT_2 | BIT_3);
+ switch (esw_cfg->op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ arg1 |= (BIT_4 | BIT_6 | BIT_7);
+ arg2 |= (BIT_0 | BIT_1);
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ arg2 |= (BIT_2 | BIT_3);
+ if (!(esw_cfg->discard_tagged))
+ arg1 &= ~BIT_4;
+ if (!(esw_cfg->promisc_mode))
+ arg1 &= ~BIT_6;
+ if (!(esw_cfg->mac_override))
+ arg1 &= ~BIT_7;
+ if (!(esw_cfg->mac_anti_spoof))
+ arg2 &= ~BIT_0;
+ if (!(esw_cfg->offload_flags & BIT_0))
+ arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
+ if (!(esw_cfg->offload_flags & BIT_1))
+ arg2 &= ~BIT_2;
+ if (!(esw_cfg->offload_flags & BIT_2))
+ arg2 &= ~BIT_3;
+ break;
+ case QLCNIC_ADD_VLAN:
+ arg1 |= (BIT_2 | BIT_5);
+ arg1 |= (esw_cfg->vlan_id << 16);
+ break;
+ case QLCNIC_DEL_VLAN:
+ arg1 |= (BIT_3 | BIT_5);
+ arg1 &= ~(0x0ffff << 16);
+ break;
+ default:
+ return err;
+ }
+
+ adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+ QLCNIC_CMD_CONFIGURE_ESWITCH);
+ cmd.req.arg[1] = arg1;
+ cmd.req.arg[2] = arg2;
+ err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
+ qlcnic_free_mbx_args(&cmd);
+
+ if (err != QLCNIC_RCODE_SUCCESS)
+ dev_err(&adapter->pdev->dev,
+ "Failed to configure eswitch pci func %d\n", pci_func);
+ else
+ dev_info(&adapter->pdev->dev,
+ "Configured eSwitch for pci func %d\n", pci_func);
+
+ return err;
+}
+
+int
+qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ u32 arg1, arg2;
+ u8 phy_port;
+ if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
+ phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
+ else
+ phy_port = adapter->ahw->physical_port;
+ arg1 = phy_port;
+ arg1 |= (esw_cfg->pci_func << 8);
+ if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
+ return -EIO;
+
+ esw_cfg->discard_tagged = !!(arg1 & BIT_4);
+ esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
+ esw_cfg->promisc_mode = !!(arg1 & BIT_6);
+ esw_cfg->mac_override = !!(arg1 & BIT_7);
+ esw_cfg->vlan_id = LSW(arg1 >> 16);
+ esw_cfg->mac_anti_spoof = (arg2 & 0x1);
+ esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index fc50e1d..118b2b2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -52,7 +52,8 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{ QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
{ QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
};
-const u32 qlcnic_83xx_ext_reg_tbl[] = {
+
+static const u32 qlcnic_83xx_ext_reg_tbl[] = {
0x38CC, /* Global Reset */
0x38F0, /* Wildcard */
0x38FC, /* Informant */
@@ -98,18 +99,18 @@ const u32 qlcnic_83xx_ext_reg_tbl[] = {
0x34A4, /* QLC_83XX_ASIC_TEMP */
};
-const u32 qlcnic_83xx_reg_tbl[] = {
+static const u32 qlcnic_83xx_reg_tbl[] = {
0x34A8, /* PEG_HALT_STAT1 */
0x34AC, /* PEG_HALT_STAT2 */
0x34B0, /* FW_HEARTBEAT */
0x3500, /* FLASH LOCK_ID */
0x3528, /* FW_CAPABILITIES */
- 0x3538, /* drv active, DRV_REG0 */
- 0x3540, /* dev state, DRV_REG1 */
- 0x3544, /* drv state, DRV_REG2 */
- 0x3548, /* drv scratch, DRV_REG3 */
- 0x354C, /* dev part info, DRV_REG4 */
- 0x3524, /* drv IDC ver, DRV_REG5 */
+ 0x3538, /* Driver active, DRV_REG0 */
+ 0x3540, /* Device state, DRV_REG1 */
+ 0x3544, /* Driver state, DRV_REG2 */
+ 0x3548, /* Driver scratch, DRV_REG3 */
+ 0x354C, /* Device partiton info, DRV_REG4 */
+ 0x3524, /* Driver IDC ver, DRV_REG5 */
0x3550, /* FW_VER_MAJOR */
0x3554, /* FW_VER_MINOR */
0x3558, /* FW_VER_SUB */
@@ -124,7 +125,7 @@ const u32 qlcnic_83xx_reg_tbl[] = {
0x3854, /* FLASH UNLOCK */
};
-struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
+static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.read_crb = qlcnic_83xx_read_crb,
.write_crb = qlcnic_83xx_write_crb,
.rdreg = qlcnic_83xx_rd_reg_indirect,
@@ -158,7 +159,7 @@ struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.get_board_info = qlcnic_83xx_get_port_info,
};
-struct qlcnic_nic_template qlcnic_83xx_ops = {
+static struct qlcnic_nic_template qlcnic_83xx_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
.request_reset = qlcnic_83xx_idc_request_reset,
@@ -426,7 +427,8 @@ qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
handler = qlcnic_83xx_handle_aen;
val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
- sprintf(name, "%s[%s]", adapter->netdev->name, "aen");
+ snprintf(name, (IFNAMSIZ + 4),
+ "%s[%s]", adapter->netdev->name, "aen");
err = request_irq(val, handler, flags, name, adapter);
if (err) {
dev_err(&adapter->pdev->dev,
@@ -1378,18 +1380,10 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *adapter,
npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
- dev_info(&adapter->pdev->dev,
- "phy port: %d switch_mode: %d,\n"
- "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n"
- "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n",
- npar_info->phys_port, npar_info->switch_mode,
- npar_info->max_tx_ques, npar_info->max_rx_ques,
- npar_info->min_tx_bw, npar_info->max_tx_bw,
- npar_info->max_mtu, npar_info->capabilities);
}
int
-qlcnic_83xx_ms_mem_write_128b(struct qlcnic_adapter *adapter,
+qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter,
u64 addr, u32 *data, u32 count)
{
int i, j, err, ret = 0;
@@ -2468,18 +2462,6 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
npar_info->max_linkspeed_reg_offset =
(cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
- dev_info(&adapter->pdev->dev,
- "\n\top_type: %d, phy port: %d switch_mode: %d,\n"
- "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x, max_tx_bw: %d,\n"
- "\tmax_bw_offset: 0x%x max_link_speed_offset: 0x%x,\n"
- "\tmax_mtu:0x%x, capabilities: 0x%x\n",
- npar_info->op_type,
- npar_info->phys_port, npar_info->switch_mode,
- npar_info->max_tx_ques, npar_info->max_rx_ques,
- npar_info->min_tx_bw, npar_info->max_tx_bw,
- npar_info->max_bw_reg_offset,
- npar_info->max_linkspeed_reg_offset,
- npar_info->max_mtu, npar_info->capabilities);
out:
qlcnic_free_mbx_args(&cmd);
return err;
@@ -2623,11 +2605,11 @@ qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
}
int
-qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *adapter, u32 flash_addr,
- u8 *p_data, int u32_word_count)
+qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
+ u8 *p_data, int count)
{
int i, err;
- u32 u32_word;
+ u32 word;
u32 addr = flash_addr;
if (qlcnic_83xx_lock_flash(adapter) != 0)
@@ -2639,16 +2621,16 @@ qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *adapter, u32 flash_addr,
return -EIO;
}
- for (i = 0; i < u32_word_count; i++) {
+ for (i = 0; i < count; i++) {
if (qlcnic_83xx_wrt_reg_indirect(adapter,
QLC_83XX_FLASH_DIRECT_WINDOW, (addr))) {
qlcnic_83xx_unlock_flash(adapter);
return -EIO;
}
- u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ word = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
- *(__le32 *)p_data = le32_to_cpu(u32_word);
+ *(__le32 *)p_data = le32_to_cpu(word);
p_data = p_data + 4;
addr = addr + 4;
}
@@ -2659,11 +2641,11 @@ qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *adapter, u32 flash_addr,
}
int
-qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *adapter,
- u32 flash_addr, u8 *p_data, int u32_word_count)
+qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
+ u32 flash_addr, u8 *p_data, int count)
{
int err;
- u32 i, u32_word, flash_offset;
+ u32 i, word, flash_offset;
u32 addr = flash_addr;
flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
@@ -2677,15 +2659,15 @@ qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *adapter,
QLC_83XX_FLASH_DIRECT_WINDOW, (addr));
/* Check if data is spread across multiple sectors */
- if ((flash_offset + (u32_word_count * sizeof(u32))) >
+ if ((flash_offset + (count * sizeof(u32))) >
(QLCNIC_FLASH_SECTOR_SIZE - 1)) {
/* Multi sector read */
- for (i = 0; i < u32_word_count; i++) {
- u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ for (i = 0; i < count; i++) {
+ word = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
- *(__le32 *)p_data = le32_to_cpu(u32_word);
+ *(__le32 *)p_data = le32_to_cpu(word);
p_data = p_data + 4;
addr = addr + 4;
flash_offset = flash_offset + 4;
@@ -2699,10 +2681,10 @@ qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *adapter,
}
} else {
/* Single sector read */
- for (i = 0; i < u32_word_count; i++) {
- u32_word = qlcnic_83xx_rd_reg_indirect(adapter,
+ for (i = 0; i < count; i++) {
+ word = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_DIRECT_DATA(addr), &err);
- *(__le32 *)p_data = cpu_to_le32(u32_word);
+ *(__le32 *)p_data = cpu_to_le32(word);
p_data = p_data + 4;
addr = addr + 4;
}
@@ -2813,7 +2795,7 @@ qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
return -EIO;
memset(&adapter->ahw->flash_fdt, 0, fdt_size);
- ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ ret = qlcnic_83xx_lockless_flash_read32(adapter,
QLCNIC_FDT_LOCATION,
(u8 *)&adapter->ahw->flash_fdt,
count);
@@ -2891,7 +2873,7 @@ qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
}
int
-qlcnic_83xx_flash_write_u32(struct qlcnic_adapter *adapter, u32 addr,
+qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr,
u32 *p_data)
{
int ret = -EIO;
@@ -2913,13 +2895,13 @@ qlcnic_83xx_flash_write_u32(struct qlcnic_adapter *adapter, u32 addr,
int
qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
- u32 *p_data, int u32_word_count)
+ u32 *p_data, int count)
{
u32 temp;
int ret = -EIO, err;
- if ((u32_word_count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
- (u32_word_count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
+ if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) ||
+ (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) {
dev_err(&adapter->pdev->dev,
" %s: Invalid word count\n", __func__);
return -EIO;
@@ -2944,13 +2926,13 @@ qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
return -EIO;
}
- u32_word_count--;
+ count--;
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
/* Second to N-1 DWORD writes */
- while (u32_word_count != 1) {
+ while (count != 1) {
qlcnic_83xx_wrt_reg_indirect(adapter,
QLC_83XX_FLASH_WRDATA, *p_data++);
qlcnic_83xx_wrt_reg_indirect(adapter,
@@ -2962,7 +2944,7 @@ qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
" %s: failed at %d\n", __func__, __LINE__);
return -EIO;
}
- u32_word_count--;
+ count--;
}
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 6cd4877..c725b07 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -532,17 +532,17 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int);
void qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
/* 83xx MS memory access API's */
-int qlcnic_83xx_ms_mem_write_128b(struct qlcnic_adapter *, u64, u32 *, u32);
+int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *, u64, u32 *, u32);
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
u32 qlcnic_ind_rd(struct qlcnic_adapter *, u32);
/* 83xx flash operations */
-int qlcnic_83xx_flash_read_u32(struct qlcnic_adapter *, u32, u8 *, int);
-int qlcnic_83xx_lockless_flash_read_u32(struct qlcnic_adapter *,
+int qlcnic_83xx_flash_read32(struct qlcnic_adapter *, u32, u8 *, int);
+int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *,
u32, u8 *, int);
int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *, u32);
int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *, u32, u32 *, int);
-int qlcnic_83xx_flash_write_u32(struct qlcnic_adapter *, u32, u32 *);
+int qlcnic_83xx_flash_write32(struct qlcnic_adapter *, u32, u32 *);
int qlcnic_83xx_lock_flash(struct qlcnic_adapter *);
void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *);
void qlcnic_83xx_get_stats(struct qlcnic_adapter *,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 6e14662..ffd1028 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -994,7 +994,7 @@ qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
{
u32 idc_params, val;
- if (qlcnic_83xx_lockless_flash_read_u32(adapter,
+ if (qlcnic_83xx_lockless_flash_read32(adapter,
QLC_83XX_IDC_FLASH_PARAM_ADDR,
(u8 *)&idc_params, 1)) {
dev_info(&adapter->pdev->dev,
@@ -1195,7 +1195,7 @@ qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
return -ENOMEM;
}
- ret = qlcnic_83xx_lockless_flash_read_u32(adapter, src,
+ ret = qlcnic_83xx_lockless_flash_read32(adapter, src,
p_cache, size/sizeof(u32));
if (ret) {
kfree(p_cache);
@@ -1203,7 +1203,7 @@ qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
}
/* 16 byte write to MS memory */
- ret = qlcnic_83xx_ms_mem_write_128b(adapter, dest,
+ ret = qlcnic_83xx_ms_mem_write128(adapter, dest,
(u32 *)p_cache, size/16);
if (ret) {
kfree(p_cache);
@@ -1230,7 +1230,7 @@ qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
p_cache = (u32 *)adapter->ahw->fw_info.fw->data;
addr = (u64)dest;
- ret = qlcnic_83xx_ms_mem_write_128b(adapter, addr,
+ ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
(u32 *)p_cache, size/16);
if (ret) {
dev_err(&adapter->pdev->dev, "MS memory write failed\n");
@@ -1239,7 +1239,7 @@ qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
return -EIO;
}
- /* Check 128 bit alignment */
+ /* bit alignment check */
if (adapter->ahw->fw_info.fw->size & 0xF) {
addr = dest + size;
for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++)
@@ -1248,7 +1248,7 @@ qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
for (; i < 16 ; i++)
data[i] = 0;
- ret = qlcnic_83xx_ms_mem_write_128b(adapter, addr,
+ ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
(u32 *)data, 1);
if (ret) {
dev_err(&adapter->pdev->dev,
@@ -1397,7 +1397,7 @@ int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
u32_count = sizeof(struct qlcnic_83xx_reset_template_hdr) / sizeof(u32);
/* Copy template header from flash */
- if (qlcnic_83xx_flash_read_u32(p_dev, addr, p_buff, u32_count)) {
+ if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, u32_count)) {
dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
return -EIO;
}
@@ -1411,7 +1411,7 @@ int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
p_dev->ahw->reset.hdr->hdr_size)/sizeof(u32);
/* Copy rest of the template */
- if (qlcnic_83xx_flash_read_u32(p_dev, addr, p_buff, u32_count)) {
+ if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, u32_count)) {
dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);
return -EIO;
}
@@ -1762,6 +1762,27 @@ qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)
dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
}
+static int
+qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter)
+{
+ int err = -EIO;
+
+ if (request_firmware(&adapter->ahw->fw_info.fw,
+ QLC_83XX_FW_FILE_NAME, &(adapter->pdev->dev))) {
+ dev_err(&adapter->pdev->dev,
+ "No file FW image, loading flash FW image.\n");
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID,
+ QLC_83XX_BOOT_FROM_FLASH);
+ } else {
+ if (qlcnic_83xx_copy_fw_file(adapter))
+ return err;
+ QLCWR(adapter, QLCNIC_FW_IMG_VALID,
+ QLC_83XX_BOOT_FROM_FILE);
+ }
+
+ return 0;
+}
+
int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
{
u32 val;
@@ -1777,23 +1798,15 @@ int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
qlcnic_83xx_init_hw(adapter);
if (qlcnic_83xx_copy_bootloader(adapter))
return err;
+
/* Boot either flash image or firmware image from host file system */
if (adapter->ahw->fw_info.load_from_file) {
- if (request_firmware(&adapter->ahw->fw_info.fw,
- QLC_83XX_FW_FILE_NAME, &(adapter->pdev->dev))) {
- dev_err(&adapter->pdev->dev,
- "No file FW image, loading flash FW image.\n");
- QLCWR(adapter, QLCNIC_FW_IMG_VALID,
- QLC_83XX_BOOT_FROM_FLASH);
- } else {
- if (qlcnic_83xx_copy_fw_file(adapter))
- return err;
- QLCWR(adapter, QLCNIC_FW_IMG_VALID,
- QLC_83XX_BOOT_FROM_FILE);
- }
+ if (qlcnic_83xx_load_fw_image_from_host(adapter))
+ return err;
} else {
QLCWR(adapter, QLCNIC_FW_IMG_VALID, QLC_83XX_BOOT_FROM_FLASH);
}
+
qlcnic_83xx_start_hw(adapter);
if (qlcnic_83xx_check_hw_status(adapter))
return -EIO;
@@ -1835,6 +1848,7 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
int err;
struct qlcnic_hardware_context *ahw = adapter->ahw;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
err = ahw->hw_ops->get_nic_info(adapter, &nic_info, ahw->pci_func);
if (err)
return -EIO;
@@ -1987,7 +2001,7 @@ qlcnic_83xx_init(struct qlcnic_adapter *adapter)
INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
- /* register for NIC IDC AEN Events */
+ /* Register for NIC IDC AEN events */
qlcnic_83xx_register_nic_idc_func(adapter, 1);
/* Periodically monitor device status */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index 1b3b637..ab843d8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -118,7 +118,6 @@ qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
{
int err = -EIO;
- /*qlcnic_83xx_get_minidump_template(adapter);*/
if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) {
if (qlcnic_init_pci_info(adapter))
return err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
deleted file mode 100644
index 4b885c4..0000000
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ /dev/null
@@ -1,1179 +0,0 @@
-/*
- * QLogic qlcnic NIC Driver
- * Copyright (c) 2009-2010 QLogic Corporation
- *
- * See LICENSE.qlcnic for copyright and licensing details.
- */
-
-#include "qlcnic.h"
-
-/* Array of FW control command structs with command type and required
- * number of input and output arguments respectively.
-*/
-static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
- { QLCNIC_CMD_CREATE_RX_CTX, 4, 1 },
- { QLCNIC_CMD_DESTROY_RX_CTX, 2, 1 },
- { QLCNIC_CMD_CREATE_TX_CTX, 4, 1 },
- { QLCNIC_CMD_DESTROY_TX_CTX, 2, 1 },
- { QLCNIC_CMD_INTRPT_TEST, 4, 1 },
- { QLCNIC_CMD_SET_MTU, 4, 1 },
- { QLCNIC_CMD_READ_PHY, 4, 2 },
- { QLCNIC_CMD_WRITE_PHY, 5, 1 },
- { QLCNIC_CMD_READ_HW_REG, 4, 1 },
- { QLCNIC_CMD_GET_FLOW_CTL, 4, 2 },
- { QLCNIC_CMD_SET_FLOW_CTL, 4, 1 },
- { QLCNIC_CMD_READ_MAX_MTU, 4, 2 },
- { QLCNIC_CMD_READ_MAX_LRO, 4, 2 },
- { QLCNIC_CMD_MAC_ADDRESS, 4, 3 },
- { QLCNIC_CMD_GET_PCI_INFO, 4, 1 },
- { QLCNIC_CMD_GET_NIC_INFO, 4, 1 },
- { QLCNIC_CMD_SET_NIC_INFO, 4, 1 },
- { QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3 },
- { QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1 },
- { QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3 },
- { QLCNIC_CMD_SET_PORTMIRRORING, 4, 1 },
- { QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1 },
- { QLCNIC_CMD_GET_MAC_STATS, 4, 1 },
- { QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3 },
- { QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1 },
- { QLCNIC_CMD_CONFIG_PORT, 4, 1 },
- { QLCNIC_CMD_TEMP_SIZE, 4, 4 },
- { QLCNIC_CMD_GET_TEMP_HDR, 4, 1 },
-};
-
-/* Allocate mailbox incoming and outgoing registers. It should be used with a
- * follow up call to qlcnic_free_mbx_args
- */
-int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
- struct qlcnic_adapter *adapter, u32 type)
-{
- int i, size;
- const struct qlcnic_mailbox_metadata *mbx_tbl;
-
- mbx_tbl = qlcnic_mbx_tbl;
- size = ARRAY_SIZE(qlcnic_mbx_tbl);
- for (i = 0; i < size; i++) {
- if (type == mbx_tbl[i].cmd) {
- mbx->req.num = mbx_tbl[i].in_args;
- mbx->rsp.num = mbx_tbl[i].out_args;
- mbx->req.arg = kcalloc(mbx->req.num,
- sizeof(u32), GFP_ATOMIC);
- if (!mbx->req.arg)
- return -ENOMEM;
- mbx->rsp.arg = kcalloc(mbx->rsp.num,
- sizeof(u32), GFP_ATOMIC);
- if (!mbx->rsp.arg) {
- kfree(mbx->req.arg);
- mbx->req.arg = NULL;
- return -ENOMEM;
- }
- memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
- memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
- mbx->req.arg[0] = type;
- break;
- }
- }
- return 0;
-}
-
-/* Free up mailbox registers
- * */
-void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
-{
- kfree(cmd->req.arg);
- cmd->req.arg = NULL;
- kfree(cmd->rsp.arg);
- cmd->rsp.arg = NULL;
-}
-
-
-static u32
-qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
-{
- u32 rsp;
- int err, timeout = 0;
-
- do {
- /* give atleast 1ms for firmware to respond */
- msleep(1);
-
- if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
- return QLCNIC_CDRP_RSP_TIMEOUT;
-
- rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET, &err);
- } while (!QLCNIC_CDRP_IS_RSP(rsp));
-
- return rsp;
-}
-
-int
-qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
-{
- int i, err;
- u32 rsp;
- u32 signature;
- struct pci_dev *pdev = adapter->pdev;
- struct qlcnic_hardware_context *ahw = adapter->ahw;
-
- signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw);
-
- /* Acquire semaphore before accessing CRB */
- if (ahw->hw_ops->api_lock(adapter)) {
- cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
- return cmd->rsp.arg[0];
- }
-
- QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
- for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
- QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
- QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
- QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
- rsp = qlcnic_poll_rsp(adapter);
-
- if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
- dev_err(&pdev->dev, "card response timeout.\n");
- cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
- } else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
- cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
- dev_err(&pdev->dev, "failed card response code:0x%x\n",
- cmd->rsp.arg[0]);
- } else if (rsp == QLCNIC_CDRP_RSP_OK)
- cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
-
- for (i = 1; i < cmd->rsp.num; i++)
- cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i), &err);
-
- /* Release semaphore */
- ahw->hw_ops->api_unlock(adapter);
- return cmd->rsp.arg[0];
-}
-
-int
-qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
-{
- int err = 0;
- struct qlcnic_cmd_args cmd;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
- return err;
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_SET_MTU);
- cmd.req.arg[1] = recv_ctx->context_id;
- cmd.req.arg[2] = mtu;
-
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err) {
- dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
- err = -EIO;
- }
- qlcnic_free_mbx_args(&cmd);
- return err;
-}
-
-int
-qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
-{
- void *addr;
- struct qlcnic_hostrq_rx_ctx *prq;
- struct qlcnic_cardrsp_rx_ctx *prsp;
- struct qlcnic_hostrq_rds_ring *prq_rds;
- struct qlcnic_hostrq_sds_ring *prq_sds;
- struct qlcnic_cardrsp_rds_ring *prsp_rds;
- struct qlcnic_cardrsp_sds_ring *prsp_sds;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_cmd_args cmd;
-
- dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
- u64 phys_addr;
-
- u8 i, nrds_rings, nsds_rings;
- size_t rq_size, rsp_size;
- u32 cap, reg, val, reg2;
- int err;
-
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- nrds_rings = adapter->max_rds_rings;
- nsds_rings = adapter->max_sds_rings;
-
- rq_size =
- SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
- nsds_rings);
- rsp_size =
- SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings,
- nsds_rings);
-
- addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
- &hostrq_phys_addr, GFP_KERNEL);
- if (addr == NULL)
- return -ENOMEM;
- prq = addr;
-
- addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
- &cardrsp_phys_addr, GFP_KERNEL);
- if (addr == NULL) {
- err = -ENOMEM;
- goto out_free_rq;
- }
- prsp = addr;
-
- prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
-
- cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN
- | QLCNIC_CAP0_VALIDOFF);
- cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
-
- prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
- msix_handler);
- prq->txrx_sds_binding = nsds_rings - 1;
-
- prq->capabilities[0] = cpu_to_le32(cap);
- prq->host_int_crb_mode =
- cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
- prq->host_rds_crb_mode =
- cpu_to_le32(QLCNIC_HOST_RDS_CRB_MODE_UNIQUE);
-
- prq->num_rds_rings = cpu_to_le16(nrds_rings);
- prq->num_sds_rings = cpu_to_le16(nsds_rings);
- prq->rds_ring_offset = 0;
-
- val = le32_to_cpu(prq->rds_ring_offset) +
- (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings);
- prq->sds_ring_offset = cpu_to_le32(val);
-
- prq_rds = (struct qlcnic_hostrq_rds_ring *)(prq->data +
- le32_to_cpu(prq->rds_ring_offset));
-
- for (i = 0; i < nrds_rings; i++) {
-
- rds_ring = &recv_ctx->rds_rings[i];
- rds_ring->producer = 0;
-
- prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
- prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
- prq_rds[i].ring_kind = cpu_to_le32(i);
- prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
- }
-
- prq_sds = (struct qlcnic_hostrq_sds_ring *)(prq->data +
- le32_to_cpu(prq->sds_ring_offset));
-
- for (i = 0; i < nsds_rings; i++) {
-
- sds_ring = &recv_ctx->sds_rings[i];
- sds_ring->consumer = 0;
- memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));
-
- prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
- prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
- prq_sds[i].msi_index = cpu_to_le16(i);
- }
-
- phys_addr = hostrq_phys_addr;
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_CREATE_RX_CTX);
- cmd.req.arg[1] = MSD(phys_addr);
- cmd.req.arg[2] = LSD(phys_addr);
- cmd.req.arg[3] = rq_size;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Failed to create rx ctx in firmware%d\n", err);
- goto out_free_rsp;
- }
-
- prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
- &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
-
- for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
- rds_ring = &recv_ctx->rds_rings[i];
-
- reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
- rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg;
- }
-
- prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
- &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
-
- for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) {
- sds_ring = &recv_ctx->sds_rings[i];
-
- reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
- reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);
-
- sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg;
- sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2;
- }
-
- recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
- recv_ctx->context_id = le16_to_cpu(prsp->context_id);
- recv_ctx->virt_port = prsp->virt_port;
-
-out_free_rsp:
- dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
- cardrsp_phys_addr);
- qlcnic_free_mbx_args(&cmd);
-out_free_rq:
- dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
- return err;
-}
-
-static void
-qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
-{
- int err;
- struct qlcnic_cmd_args cmd;
- struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_DESTROY_RX_CTX);
- cmd.req.arg[1] = recv_ctx->context_id;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err)
- dev_err(&adapter->pdev->dev,
- "Failed to destroy rx ctx in firmware\n");
-
- recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
- qlcnic_free_mbx_args(&cmd);
-}
-
-int
-qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring, int ring)
-{
- struct qlcnic_hostrq_tx_ctx *prq;
- struct qlcnic_hostrq_cds_ring *prq_cds;
- struct qlcnic_cardrsp_tx_ctx *prsp;
- void *rq_addr, *rsp_addr;
- size_t rq_size, rsp_size;
- u32 temp;
- struct qlcnic_cmd_args cmd;
- int err;
- u64 phys_addr;
- dma_addr_t rq_phys_addr, rsp_phys_addr;
-
- /* reset host resources */
- tx_ring->producer = 0;
- tx_ring->sw_consumer = 0;
- *(tx_ring->hw_consumer) = 0;
-
- rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
- rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
- &rq_phys_addr, GFP_KERNEL);
- if (!rq_addr)
- return -ENOMEM;
-
- rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
- rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
- &rsp_phys_addr, GFP_KERNEL);
- if (!rsp_addr) {
- err = -ENOMEM;
- goto out_free_rq;
- }
-
- memset(rq_addr, 0, rq_size);
- prq = rq_addr;
-
- memset(rsp_addr, 0, rsp_size);
- prsp = rsp_addr;
-
- prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
-
- temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN |
- QLCNIC_CAP0_LSO);
- prq->capabilities[0] = cpu_to_le32(temp);
-
- prq->host_int_crb_mode =
- cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
- prq->msi_index = 0;
-
- prq->interrupt_ctl = 0;
- prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
-
- prq_cds = &prq->cds_ring;
-
- prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
- prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
-
- phys_addr = rq_phys_addr;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_CREATE_TX_CTX);
- cmd.req.arg[1] = MSD(phys_addr);
- cmd.req.arg[2] = LSD(phys_addr);
- cmd.req.arg[3] = rq_size;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- if (err == QLCNIC_RCODE_SUCCESS) {
- temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
- tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
- tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
- } else {
- dev_err(&adapter->pdev->dev,
- "Failed to create tx ctx in firmware%d\n", err);
- err = -EIO;
- }
-
- dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
- rsp_phys_addr);
-
-out_free_rq:
- dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-static void
-qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
-{
- struct qlcnic_cmd_args cmd;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_DESTROY_TX_CTX);
- cmd.req.arg[1] = tx_ring->ctx_id;
- if (adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd))
- dev_err(&adapter->pdev->dev,
- "Failed to destroy tx ctx in firmware\n");
- qlcnic_free_mbx_args(&cmd);
-}
-
-int
-qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
-{
- int err;
- struct qlcnic_cmd_args cmd;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_CONFIG_PORT);
- cmd.req.arg[1] = config;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- qlcnic_free_mbx_args(&cmd);
- return err;
-}
-
-int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
-{
- void *addr;
- int err, ring;
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
-
- struct pci_dev *pdev = adapter->pdev;
-
- recv_ctx = adapter->recv_ctx;
-
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- tx_ring = &adapter->tx_ring[ring];
- tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
- sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
- if (tx_ring->hw_consumer == NULL) {
- dev_err(&pdev->dev, "failed to allocate tx consumer\n");
- return -ENOMEM;
- }
- /* cmd desc ring */
- addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
- &tx_ring->phys_addr, GFP_KERNEL);
-
- if (addr == NULL) {
- dev_err(&pdev->dev,
- "failed to allocate tx desc ring\n");
- err = -ENOMEM;
- goto err_out_free;
- }
-
- tx_ring->desc_head = addr;
- }
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
- addr = dma_alloc_coherent(&adapter->pdev->dev,
- RCV_DESC_RINGSIZE(rds_ring),
- &rds_ring->phys_addr, GFP_KERNEL);
- if (addr == NULL) {
- dev_err(&pdev->dev,
- "failed to allocate rds ring [%d]\n", ring);
- err = -ENOMEM;
- goto err_out_free;
- }
- rds_ring->desc_head = addr;
-
- }
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
-
- addr = dma_alloc_coherent(&adapter->pdev->dev,
- STATUS_DESC_RINGSIZE(sds_ring),
- &sds_ring->phys_addr, GFP_KERNEL);
- if (addr == NULL) {
- dev_err(&pdev->dev,
- "failed to allocate sds ring [%d]\n", ring);
- err = -ENOMEM;
- goto err_out_free;
- }
- sds_ring->desc_head = addr;
- }
-
- return 0;
-
-err_out_free:
- qlcnic_free_hw_resources(adapter);
- return err;
-}
-
-int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
-{
- int i, err, ring;
-
- if (adapter->flags & QLCNIC_NEED_FLR) {
- pci_reset_function(adapter->pdev);
- adapter->flags &= ~QLCNIC_NEED_FLR;
- }
-
- err = adapter->ahw->hw_ops->create_rx_ctx(adapter);
- if (err)
- return err;
-
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- err = adapter->ahw->hw_ops->create_tx_ctx(adapter,
- &adapter->tx_ring[ring], ring);
- if (err) {
- qlcnic_fw_cmd_destroy_rx_ctx(adapter);
- if (ring == 0)
- return err;
- for (i = 0; i < ring; i++)
- qlcnic_fw_cmd_destroy_tx_ctx(adapter,
- &adapter->tx_ring[i]);
- return err;
- }
- }
-
- set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
- return 0;
-}
-
-void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
-{
- int ring;
-
- if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
- qlcnic_fw_cmd_destroy_rx_ctx(adapter);
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
- qlcnic_fw_cmd_destroy_tx_ctx(adapter,
- &adapter->tx_ring[ring]);
-
- /* Allow dma queues to drain after context reset */
- msleep(20);
- }
-}
-
-void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_recv_context *recv_ctx;
- struct qlcnic_host_rds_ring *rds_ring;
- struct qlcnic_host_sds_ring *sds_ring;
- struct qlcnic_host_tx_ring *tx_ring;
- int ring;
-
- recv_ctx = adapter->recv_ctx;
-
- for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
- tx_ring = &adapter->tx_ring[ring];
- if (tx_ring->hw_consumer != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- sizeof(u32),
- tx_ring->hw_consumer,
- tx_ring->hw_cons_phys_addr);
- tx_ring->hw_consumer = NULL;
- }
-
- if (tx_ring->desc_head != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- TX_DESC_RINGSIZE(tx_ring),
- tx_ring->desc_head, tx_ring->phys_addr);
- tx_ring->desc_head = NULL;
- }
- }
-
- for (ring = 0; ring < adapter->max_rds_rings; ring++) {
- rds_ring = &recv_ctx->rds_rings[ring];
-
- if (rds_ring->desc_head != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- RCV_DESC_RINGSIZE(rds_ring),
- rds_ring->desc_head,
- rds_ring->phys_addr);
- rds_ring->desc_head = NULL;
- }
- }
-
- for (ring = 0; ring < adapter->max_sds_rings; ring++) {
- sds_ring = &recv_ctx->sds_rings[ring];
-
- if (sds_ring->desc_head != NULL) {
- dma_free_coherent(&adapter->pdev->dev,
- STATUS_DESC_RINGSIZE(sds_ring),
- sds_ring->desc_head,
- sds_ring->phys_addr);
- sds_ring->desc_head = NULL;
- }
- }
-}
-
-/* Get MAC address of a NIC partition */
-int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
-{
- int err, i;
- struct qlcnic_cmd_args cmd;
- u32 mac_low, mac_high;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_MAC_ADDRESS);
- cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- if (err == QLCNIC_RCODE_SUCCESS) {
- mac_low = cmd.rsp.arg[1];
- mac_high = cmd.rsp.arg[2];
-
- for (i = 0; i < 2; i++)
- mac[i] = (u8) (mac_high >> ((1 - i) * 8));
- for (i = 2; i < 6; i++)
- mac[i] = (u8) (mac_low >> ((5 - i) * 8));
- } else {
- dev_err(&adapter->pdev->dev,
- "Failed to get mac address%d\n", err);
- err = -EIO;
- }
- qlcnic_free_mbx_args(&cmd);
- return err;
-}
-
-/* Get info of a NIC partition */
-int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
- struct qlcnic_info *npar_info, u8 func_id)
-{
- int err;
- dma_addr_t nic_dma_t;
- const struct qlcnic_info *nic_info;
- void *nic_info_addr;
- struct qlcnic_cmd_args cmd;
- size_t nic_size = sizeof(struct qlcnic_info);
-
- nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
- if (!nic_info_addr)
- return -ENOMEM;
- memset(nic_info_addr, 0, nic_size);
-
- nic_info = nic_info_addr;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_NIC_INFO);
- cmd.req.arg[1] = MSD(nic_dma_t);
- cmd.req.arg[2] = LSD(nic_dma_t);
- cmd.req.arg[3] = (func_id << 16 | nic_size);
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (err == QLCNIC_RCODE_SUCCESS)
- qlcnic_set_npar_data(adapter, nic_info, npar_info);
- else {
- dev_err(&adapter->pdev->dev,
- "Failed to get nic info%d\n", err);
- err = -EIO;
- }
-
- dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
- nic_dma_t);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-/* Configure a NIC partition */
-int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
-{
- int err = -EIO;
- dma_addr_t nic_dma_t;
- void *nic_info_addr;
- struct qlcnic_cmd_args cmd;
- struct qlcnic_info *nic_info;
- size_t nic_size = sizeof(struct qlcnic_info);
-
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
- return err;
-
- nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
- &nic_dma_t, GFP_KERNEL);
- if (!nic_info_addr)
- return -ENOMEM;
-
- memset(nic_info_addr, 0, nic_size);
- nic_info = nic_info_addr;
-
- nic_info->pci_func = cpu_to_le16(nic->pci_func);
- nic_info->op_mode = cpu_to_le16(nic->op_mode);
- nic_info->phys_port = cpu_to_le16(nic->phys_port);
- nic_info->switch_mode = cpu_to_le16(nic->switch_mode);
- nic_info->capabilities = cpu_to_le32(nic->capabilities);
- nic_info->max_mac_filters = nic->max_mac_filters;
- nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques);
- nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques);
- nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
- nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_SET_NIC_INFO);
- cmd.req.arg[1] = MSD(nic_dma_t);
- cmd.req.arg[2] = LSD(nic_dma_t);
- cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- if (err != QLCNIC_RCODE_SUCCESS) {
- dev_err(&adapter->pdev->dev,
- "Failed to set nic info%d\n", err);
- err = -EIO;
- }
-
- dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
- nic_dma_t);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-/* Get PCI Info of a partition */
-int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
- struct qlcnic_pci_info *pci_info)
-{
- int err = 0, i;
- struct qlcnic_cmd_args cmd;
- dma_addr_t pci_info_dma_t;
- struct qlcnic_pci_info *npar;
- void *pci_info_addr;
- size_t npar_size = sizeof(struct qlcnic_pci_info);
- size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
-
- pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
- &pci_info_dma_t, GFP_KERNEL);
- if (!pci_info_addr)
- return -ENOMEM;
- memset(pci_info_addr, 0, pci_size);
-
- npar = pci_info_addr;
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_PCI_INFO);
- cmd.req.arg[1] = MSD(pci_info_dma_t);
- cmd.req.arg[2] = LSD(pci_info_dma_t);
- cmd.req.arg[3] = pci_size;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- adapter->ahw->act_pci_func = 0;
- if (err == QLCNIC_RCODE_SUCCESS) {
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
- pci_info->id = le16_to_cpu(npar->id);
- pci_info->active = le16_to_cpu(npar->active);
- pci_info->type = le16_to_cpu(npar->type);
- if (pci_info->type == QLCNIC_TYPE_NIC)
- adapter->ahw->act_pci_func++;
- pci_info->default_port =
- le16_to_cpu(npar->default_port);
- pci_info->tx_min_bw =
- le16_to_cpu(npar->tx_min_bw);
- pci_info->tx_max_bw =
- le16_to_cpu(npar->tx_max_bw);
- memcpy(pci_info->mac, npar->mac, ETH_ALEN);
- }
- } else {
- dev_err(&adapter->pdev->dev,
- "Failed to get PCI Info%d\n", err);
- err = -EIO;
- }
-
- dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
- pci_info_dma_t);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-/* Configure eSwitch for port mirroring */
-int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
- u8 enable_mirroring, u8 pci_func)
-{
- int err = -EIO;
- u32 arg1;
- struct qlcnic_cmd_args cmd;
-
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
- !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
- return err;
-
- arg1 = id | (enable_mirroring ? BIT_4 : 0);
- arg1 |= pci_func << 8;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_SET_PORTMIRRORING);
- cmd.req.arg[1] = arg1;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- if (err != QLCNIC_RCODE_SUCCESS)
- dev_err(&adapter->pdev->dev,
- "Failed to configure port mirroring%d on eswitch:%d\n",
- pci_func, id);
- else
- dev_info(&adapter->pdev->dev,
- "Configured eSwitch %d for port mirroring:%d\n",
- id, pci_func);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
- const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
-
- size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
- struct __qlcnic_esw_statistics *stats;
- dma_addr_t stats_dma_t;
- void *stats_addr;
- u32 arg1;
- struct qlcnic_cmd_args cmd;
- int err;
-
- if (esw_stats == NULL)
- return -ENOMEM;
-
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC &&
- func != adapter->ahw->pci_func) {
- dev_err(&adapter->pdev->dev,
- "Not privilege to query stats for func=%d", func);
- return -EIO;
- }
-
- stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
- if (!stats_addr) {
- dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
- return -ENOMEM;
- }
- memset(stats_addr, 0, stats_size);
-
- arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
- arg1 |= rx_tx << 15 | stats_size << 16;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_ESWITCH_STATS);
- cmd.req.arg[1] = arg1;
- cmd.req.arg[2] = MSD(stats_dma_t);
- cmd.req.arg[3] = LSD(stats_dma_t);
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
-
- if (!err) {
- stats = stats_addr;
- esw_stats->context_id = le16_to_cpu(stats->context_id);
- esw_stats->version = le16_to_cpu(stats->version);
- esw_stats->size = le16_to_cpu(stats->size);
- esw_stats->multicast_frames =
- le64_to_cpu(stats->multicast_frames);
- esw_stats->broadcast_frames =
- le64_to_cpu(stats->broadcast_frames);
- esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
- esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
- esw_stats->local_frames = le64_to_cpu(stats->local_frames);
- esw_stats->errors = le64_to_cpu(stats->errors);
- esw_stats->numbytes = le64_to_cpu(stats->numbytes);
- }
-
- dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
- stats_dma_t);
- qlcnic_free_mbx_args(&cmd);
-
- return err;
-}
-
-/* This routine will retrieve the MAC statistics from firmware */
-int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
- struct qlcnic_mac_statistics *mac_stats)
-{
- struct qlcnic_mac_statistics *stats;
- struct qlcnic_cmd_args cmd;
- size_t stats_size = sizeof(struct qlcnic_mac_statistics);
- dma_addr_t stats_dma_t;
- void *stats_addr;
- int err;
-
- if (mac_stats == NULL)
- return -ENOMEM;
-
- stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
- &stats_dma_t, GFP_KERNEL);
- if (!stats_addr) {
- dev_err(&adapter->pdev->dev,
- "%s: Unable to allocate memory.\n", __func__);
- return -ENOMEM;
- }
- memset(stats_addr, 0, stats_size);
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_MAC_STATS);
- cmd.req.arg[1] = stats_size << 16;
- cmd.req.arg[2] = MSD(stats_dma_t);
- cmd.req.arg[3] = LSD(stats_dma_t);
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- if (!err) {
- stats = stats_addr;
- mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
- mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
- mac_stats->mac_tx_mcast_pkts =
- le64_to_cpu(stats->mac_tx_mcast_pkts);
- mac_stats->mac_tx_bcast_pkts =
- le64_to_cpu(stats->mac_tx_bcast_pkts);
- mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
- mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
- mac_stats->mac_rx_mcast_pkts =
- le64_to_cpu(stats->mac_rx_mcast_pkts);
- mac_stats->mac_rx_length_error =
- le64_to_cpu(stats->mac_rx_length_error);
- mac_stats->mac_rx_length_small =
- le64_to_cpu(stats->mac_rx_length_small);
- mac_stats->mac_rx_length_large =
- le64_to_cpu(stats->mac_rx_length_large);
- mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
- mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
- mac_stats->mac_FCS_error = le64_to_cpu(stats->mac_FCS_error);
- } else {
- dev_err(&adapter->pdev->dev,
- "%s: Get mac stats failed, err=%d.\n", __func__, err);
- }
-
- dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
- stats_dma_t);
- qlcnic_free_mbx_args(&cmd);
- return err;
-}
-
-int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
- const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
-
- struct __qlcnic_esw_statistics port_stats;
- u8 i;
- int ret = -EIO;
-
- if (esw_stats == NULL)
- return -ENOMEM;
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
- return -EIO;
- if (adapter->npars == NULL)
- return -EIO;
-
- memset(esw_stats, 0, sizeof(u64));
- esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
- esw_stats->context_id = eswitch;
-
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- if (adapter->npars[i].phy_port != eswitch)
- continue;
-
- memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
- if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
- continue;
-
- esw_stats->size = port_stats.size;
- esw_stats->version = port_stats.version;
- QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
- port_stats.unicast_frames);
- QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
- port_stats.multicast_frames);
- QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
- port_stats.broadcast_frames);
- QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
- port_stats.dropped_frames);
- QLCNIC_ADD_ESW_STATS(esw_stats->errors,
- port_stats.errors);
- QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
- port_stats.local_frames);
- QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
- port_stats.numbytes);
- ret = 0;
- }
- return ret;
-}
-
-int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
- const u8 port, const u8 rx_tx)
-{
- int err;
- u32 arg1;
- struct qlcnic_cmd_args cmd;
-
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
- return -EIO;
-
- if (func_esw == QLCNIC_STATS_PORT) {
- if (port >= QLCNIC_MAX_PCI_FUNC)
- goto err_ret;
- } else if (func_esw == QLCNIC_STATS_ESWITCH) {
- if (port >= QLCNIC_NIU_MAX_XG_PORTS)
- goto err_ret;
- } else {
- goto err_ret;
- }
-
- if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
- goto err_ret;
-
- arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
- arg1 |= BIT_14 | rx_tx << 15;
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_ESWITCH_STATS);
- cmd.req.arg[1] = arg1;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- qlcnic_free_mbx_args(&cmd);
- return err;
-
-err_ret:
- dev_err(&adapter->pdev->dev,
- "Invalid arguments func_esw=%d port=%d rx_ctx=%d\n",
- func_esw, port, rx_tx);
- return -EIO;
-}
-
-static int
-__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
- u32 *arg1, u32 *arg2)
-{
- int err = -EIO;
- struct qlcnic_cmd_args cmd;
- u8 pci_func;
- pci_func = (*arg1 >> 8);
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
- cmd.req.arg[1] = *arg1;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- *arg1 = cmd.rsp.arg[1];
- *arg2 = cmd.rsp.arg[2];
- qlcnic_free_mbx_args(&cmd);
-
- if (err == QLCNIC_RCODE_SUCCESS)
- dev_info(&adapter->pdev->dev,
- "eSwitch port config for pci func %d\n", pci_func);
- else
- dev_err(&adapter->pdev->dev,
- "Failed to get eswitch port config for pci func %d\n",
- pci_func);
- return err;
-}
-/* Configure eSwitch port
-op_mode = 0 for setting default port behavior
-op_mode = 1 for setting vlan id
-op_mode = 2 for deleting vlan id
-op_type = 0 for vlan_id
-op_type = 1 for port vlan_id
-*/
-int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg)
-{
- int err = -EIO;
- u32 arg1, arg2 = 0;
- struct qlcnic_cmd_args cmd;
- u8 pci_func;
-
- if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
- return err;
- pci_func = esw_cfg->pci_func;
- arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
- arg1 |= (pci_func << 8);
-
- if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
- return err;
- arg1 &= ~(0x0ff << 8);
- arg1 |= (pci_func << 8);
- arg1 &= ~(BIT_2 | BIT_3);
- switch (esw_cfg->op_mode) {
- case QLCNIC_PORT_DEFAULTS:
- arg1 |= (BIT_4 | BIT_6 | BIT_7);
- arg2 |= (BIT_0 | BIT_1);
- if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
- arg2 |= (BIT_2 | BIT_3);
- if (!(esw_cfg->discard_tagged))
- arg1 &= ~BIT_4;
- if (!(esw_cfg->promisc_mode))
- arg1 &= ~BIT_6;
- if (!(esw_cfg->mac_override))
- arg1 &= ~BIT_7;
- if (!(esw_cfg->mac_anti_spoof))
- arg2 &= ~BIT_0;
- if (!(esw_cfg->offload_flags & BIT_0))
- arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
- if (!(esw_cfg->offload_flags & BIT_1))
- arg2 &= ~BIT_2;
- if (!(esw_cfg->offload_flags & BIT_2))
- arg2 &= ~BIT_3;
- break;
- case QLCNIC_ADD_VLAN:
- arg1 |= (BIT_2 | BIT_5);
- arg1 |= (esw_cfg->vlan_id << 16);
- break;
- case QLCNIC_DEL_VLAN:
- arg1 |= (BIT_3 | BIT_5);
- arg1 &= ~(0x0ffff << 16);
- break;
- default:
- return err;
- }
-
- adapter->ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
- QLCNIC_CMD_CONFIGURE_ESWITCH);
- cmd.req.arg[1] = arg1;
- cmd.req.arg[2] = arg2;
- err = adapter->ahw->hw_ops->mbx_cmd(adapter, &cmd);
- qlcnic_free_mbx_args(&cmd);
-
- if (err != QLCNIC_RCODE_SUCCESS)
- dev_err(&adapter->pdev->dev,
- "Failed to configure eswitch pci func %d\n", pci_func);
- else
- dev_info(&adapter->pdev->dev,
- "Configured eSwitch for pci func %d\n", pci_func);
-
- return err;
-}
-
-int
-qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg)
-{
- u32 arg1, arg2;
- u8 phy_port;
- if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
- phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
- else
- phy_port = adapter->ahw->physical_port;
- arg1 = phy_port;
- arg1 |= (esw_cfg->pci_func << 8);
- if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
- return -EIO;
-
- esw_cfg->discard_tagged = !!(arg1 & BIT_4);
- esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
- esw_cfg->promisc_mode = !!(arg1 & BIT_6);
- esw_cfg->mac_override = !!(arg1 & BIT_7);
- esw_cfg->vlan_id = LSW(arg1 >> 16);
- esw_cfg->mac_anti_spoof = (arg2 & 0x1);
- esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
-
- return 0;
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 8264722..ece5825 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -554,10 +554,10 @@ static const u32 QLCNIC_MS_READ_DATA[] = {
#define CRB_XG_STATE_P3P (QLCNIC_REG(0x98))
#define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8))
-
-#define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0))
-
-#define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c))
+#define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0))
+#define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128))
+#define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c))
+#define CRB_MAC_BLOCK_START (QLCNIC_CAM_RAM(0x1c0))
/*
* CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address
@@ -727,8 +727,8 @@ struct qlcnic_legacy_intr_set {
#define FLASH_ROM_WINDOW 0x42110030
#define FLASH_ROM_DATA 0x42150000
-#define QLCNIC_FW_DUMP_REG1 0x00130060
-#define QLCNIC_FW_DUMP_REG2 0x001e0000
+#define QLCNIC_CRB_WINDOW_2M 0x00130060
+#define QLCNIC_INDIRECT_MEM_START 0x001e0000
#define QLCNIC_FLASH_SEM2_LK 0x0013C010
#define QLCNIC_FLASH_SEM2_ULK 0x0013C014
#define QLCNIC_FLASH_LOCK_ID 0x001B2100
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
deleted file mode 100644
index 958ad02..0000000
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ /dev/null
@@ -1,1431 +0,0 @@
-/*
- * QLogic qlcnic NIC Driver
- * Copyright (c) 2009-2010 QLogic Corporation
- *
- * See LICENSE.qlcnic for copyright and licensing details.
- */
-
-#include "qlcnic.h"
-#include "qlcnic_hdr.h"
-#include "qlcnic_hw.h"
-
-#include <linux/slab.h>
-#include <net/ip.h>
-#include <linux/bitops.h>
-
-#ifndef readq
-static inline u64 readq(void __iomem *addr)
-{
- return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(u64 val, void __iomem *addr)
-{
- writel(((u32) (val)), (addr));
- writel(((u32) (val >> 32)), (addr + 4));
-}
-#endif
-
-static const struct crb_128M_2M_block_map
-crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
- {{{0, 0, 0, 0} } }, /* 0: PCI */
- {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
- {1, 0x0110000, 0x0120000, 0x130000},
- {1, 0x0120000, 0x0122000, 0x124000},
- {1, 0x0130000, 0x0132000, 0x126000},
- {1, 0x0140000, 0x0142000, 0x128000},
- {1, 0x0150000, 0x0152000, 0x12a000},
- {1, 0x0160000, 0x0170000, 0x110000},
- {1, 0x0170000, 0x0172000, 0x12e000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {1, 0x01e0000, 0x01e0800, 0x122000},
- {0, 0x0000000, 0x0000000, 0x000000} } },
- {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
- {{{0, 0, 0, 0} } }, /* 3: */
- {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
- {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
- {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
- {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
- {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {1, 0x08f0000, 0x08f2000, 0x172000} } },
- {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {1, 0x09f0000, 0x09f2000, 0x176000} } },
- {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {1, 0x0af0000, 0x0af2000, 0x17a000} } },
- {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
- {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
- {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
- {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
- {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
- {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
- {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
- {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
- {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
- {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
- {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
- {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
- {{{0, 0, 0, 0} } }, /* 23: */
- {{{0, 0, 0, 0} } }, /* 24: */
- {{{0, 0, 0, 0} } }, /* 25: */
- {{{0, 0, 0, 0} } }, /* 26: */
- {{{0, 0, 0, 0} } }, /* 27: */
- {{{0, 0, 0, 0} } }, /* 28: */
- {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
- {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
- {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
- {{{0} } }, /* 32: PCI */
- {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
- {1, 0x2110000, 0x2120000, 0x130000},
- {1, 0x2120000, 0x2122000, 0x124000},
- {1, 0x2130000, 0x2132000, 0x126000},
- {1, 0x2140000, 0x2142000, 0x128000},
- {1, 0x2150000, 0x2152000, 0x12a000},
- {1, 0x2160000, 0x2170000, 0x110000},
- {1, 0x2170000, 0x2172000, 0x12e000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000},
- {0, 0x0000000, 0x0000000, 0x000000} } },
- {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
- {{{0} } }, /* 35: */
- {{{0} } }, /* 36: */
- {{{0} } }, /* 37: */
- {{{0} } }, /* 38: */
- {{{0} } }, /* 39: */
- {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
- {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
- {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
- {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
- {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
- {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
- {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
- {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
- {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
- {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
- {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
- {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
- {{{0} } }, /* 52: */
- {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
- {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
- {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
- {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
- {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
- {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
- {{{0} } }, /* 59: I2C0 */
- {{{0} } }, /* 60: I2C1 */
- {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
- {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
- {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
-};
-
-/*
- * top 12 bits of crb internal address (hub, agent)
- */
-static const unsigned crb_hub_agt[64] = {
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PS,
- QLCNIC_HW_CRB_HUB_AGT_ADR_MN,
- QLCNIC_HW_CRB_HUB_AGT_ADR_MS,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SRE,
- QLCNIC_HW_CRB_HUB_AGT_ADR_NIU,
- QLCNIC_HW_CRB_HUB_AGT_ADR_QMN,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SQN0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SQN1,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SQN2,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SQN3,
- QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q,
- QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR,
- QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGN4,
- QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGN0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGN1,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGN2,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGN3,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGND,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGNI,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGS0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGS1,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGS2,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGS3,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGSI,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SN,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_EG,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PS,
- QLCNIC_HW_CRB_HUB_AGT_ADR_CAM,
- 0,
- 0,
- 0,
- 0,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX1,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX2,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX3,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX4,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX5,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX6,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX7,
- QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA,
- QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q,
- QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX8,
- QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX9,
- QLCNIC_HW_CRB_HUB_AGT_ADR_OCM0,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_SMB,
- QLCNIC_HW_CRB_HUB_AGT_ADR_I2C0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_I2C1,
- 0,
- QLCNIC_HW_CRB_HUB_AGT_ADR_PGNC,
- 0,
-};
-
-static const u32 msi_tgt_status[8] = {
- ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
- ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
- ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
- ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
-};
-
-/* PCI Windowing for DDR regions. */
-
-static void
-qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data)
-{
- u32 dest;
- void __iomem *val;
-
- dest = addr & 0xFFFF0000;
- val = bar0 + QLCNIC_FW_DUMP_REG1;
- writel(dest, val);
- readl(val);
- val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
- *data = readl(val);
-}
-
-static void
-qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data)
-{
- u32 dest;
- void __iomem *val;
-
- dest = addr & 0xFFFF0000;
- val = bar0 + QLCNIC_FW_DUMP_REG1;
- writel(dest, val);
- readl(val);
- val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
- writel(data, val);
- readl(val);
-}
-
-int
-qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
-{
- int err, done = 0, timeout = 0;
-
- while (!done) {
- done = QLCRD32(adapter,
- QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)), &err);
- if (done == 1)
- break;
- if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
- dev_err(&adapter->pdev->dev,
- "Failed to acquire sem=%d lock; held by=%d\n",
- sem,
- id_reg ? QLCRD32(adapter, id_reg, &err) : -1);
- return -EIO;
- }
- msleep(1);
- }
-
- if (id_reg)
- QLCWR32(adapter, id_reg, adapter->portnum);
-
- return 0;
-}
-
-u32 qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
-{
- int err;
- u32 data;
-
- if (QLCNIC_IS_82XX(adapter))
- qlcnic_read_dump_reg(addr, adapter->ahw->pci_base0, &data);
- else
- data = qlcnic_83xx_rd_reg_indirect(adapter, addr, &err);
- return data;
-}
-
-void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
-{
- if (QLCNIC_IS_82XX(adapter))
- qlcnic_write_dump_reg(addr, adapter->ahw->pci_base0, data);
- else
- qlcnic_83xx_wrt_reg_indirect(adapter, addr, data);
-}
-
-void
-qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem)
-{
- int err;
- QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)), &err);
-}
-
-static int
-qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
- struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
-{
- u32 i, producer, consumer;
- struct qlcnic_cmd_buffer *pbuf;
- struct cmd_desc_type0 *cmd_desc;
- struct qlcnic_host_tx_ring *tx_ring;
-
- i = 0;
-
- if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
- return -EIO;
-
- tx_ring = adapter->tx_ring;
- __netif_tx_lock_bh(tx_ring->txq);
-
- producer = tx_ring->producer;
- consumer = tx_ring->sw_consumer;
-
- if (nr_desc >= qlcnic_tx_avail(tx_ring)) {
- netif_tx_stop_queue(tx_ring->txq);
- smp_mb();
- if (qlcnic_tx_avail(tx_ring) > nr_desc) {
- if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
- netif_tx_wake_queue(tx_ring->txq);
- } else {
- adapter->stats.xmit_off++;
- __netif_tx_unlock_bh(tx_ring->txq);
- return -EBUSY;
- }
- }
-
- do {
- cmd_desc = &cmd_desc_arr[i];
-
- pbuf = &tx_ring->cmd_buf_arr[producer];
- pbuf->skb = NULL;
- pbuf->frag_count = 0;
-
- memcpy(&tx_ring->desc_head[producer],
- &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
-
- producer = get_next_index(producer, tx_ring->num_desc);
- i++;
-
- } while (i != nr_desc);
-
- tx_ring->producer = producer;
-
- qlcnic_update_cmd_producer(adapter, tx_ring);
-
- __netif_tx_unlock_bh(tx_ring->txq);
-
- return 0;
-}
-
-int
-qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
- __le16 vlan_id, u8 op)
-{
- struct qlcnic_nic_req req;
- struct qlcnic_mac_req *mac_req;
- struct qlcnic_vlan_req *vlan_req;
- u64 word;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
-
- word = QLCNIC_MAC_EVENT | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- mac_req = (struct qlcnic_mac_req *)&req.words[0];
- mac_req->op = op;
- memcpy(mac_req->mac_addr, addr, 6);
-
- vlan_req = (struct qlcnic_vlan_req *)&req.words[1];
- vlan_req->vlan_id = vlan_id;
-
- return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
-}
-
-static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
-{
- struct list_head *head;
- struct qlcnic_mac_list_s *cur;
-
- /* look up if already exists */
- list_for_each(head, &adapter->mac_list) {
- cur = list_entry(head, struct qlcnic_mac_list_s, list);
- if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
- return 0;
- }
-
- cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC);
- if (cur == NULL) {
- dev_err(&adapter->netdev->dev,
- "failed to add mac address filter\n");
- return -ENOMEM;
- }
- memcpy(cur->mac_addr, addr, ETH_ALEN);
-
- if (adapter->ahw->hw_ops->change_macvlan(adapter,
- cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
- kfree(cur);
- return -EIO;
- }
-
- list_add_tail(&cur->list, &adapter->mac_list);
- return 0;
-}
-
-void qlcnic_set_multi(struct net_device *netdev)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- struct netdev_hw_addr *ha;
- static const u8 bcast_addr[ETH_ALEN] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- u32 mode = VPORT_MISS_MODE_DROP;
-
- if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
- return;
-
- qlcnic_nic_add_mac(adapter, adapter->mac_addr);
- qlcnic_nic_add_mac(adapter, bcast_addr);
-
- if (netdev->flags & IFF_PROMISC) {
- if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
- mode = VPORT_MISS_MODE_ACCEPT_ALL;
- goto send_fw_cmd;
- }
-
- if ((netdev->flags & IFF_ALLMULTI) ||
- (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
- mode = VPORT_MISS_MODE_ACCEPT_MULTI;
- goto send_fw_cmd;
- }
-
- if (!netdev_mc_empty(netdev)) {
- netdev_for_each_mc_addr(ha, netdev) {
- qlcnic_nic_add_mac(adapter, ha->addr);
- }
- }
-
-send_fw_cmd:
- if (mode == VPORT_MISS_MODE_ACCEPT_ALL) {
- qlcnic_alloc_lb_filters_mem(adapter);
- adapter->mac_learn = 1;
- } else {
- adapter->mac_learn = 0;
- }
-
- adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
-}
-
-int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
-{
- struct qlcnic_nic_req req;
- u64 word;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
-
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE |
- ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- req.words[0] = cpu_to_le64(mode);
-
- return qlcnic_send_cmd_descs(adapter,
- (struct cmd_desc_type0 *)&req, 1);
-}
-
-void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_mac_list_s *cur;
- struct list_head *head = &adapter->mac_list;
-
- while (!list_empty(head)) {
- cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
- adapter->ahw->hw_ops->change_macvlan(adapter,
- cur->mac_addr, 0, QLCNIC_MAC_DEL);
- list_del(&cur->list);
- kfree(cur);
- }
-}
-
-void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_filter *tmp_fil;
- struct hlist_node *tmp_hnode, *n;
- struct hlist_head *head;
- int i;
-
- for (i = 0; i < adapter->fhash.fmax; i++) {
- head = &(adapter->fhash.fhead[i]);
-
- hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
- {
- if (jiffies >
- (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
- adapter->ahw->hw_ops->change_macvlan(adapter,
- tmp_fil->faddr, tmp_fil->vlan_id,
- tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
- QLCNIC_MAC_DEL);
- spin_lock_bh(&adapter->mac_learn_lock);
- adapter->fhash.fnum--;
- hlist_del(&tmp_fil->fnode);
- spin_unlock_bh(&adapter->mac_learn_lock);
- kfree(tmp_fil);
- }
- }
- }
-}
-
-void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_filter *tmp_fil;
- struct hlist_node *tmp_hnode, *n;
- struct hlist_head *head;
- int i;
-
- for (i = 0; i < adapter->fhash.fmax; i++) {
- head = &(adapter->fhash.fhead[i]);
-
- hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
- adapter->ahw->hw_ops->change_macvlan(adapter,
- tmp_fil->faddr, tmp_fil->vlan_id,
- tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
- QLCNIC_MAC_DEL);
- spin_lock_bh(&adapter->mac_learn_lock);
- adapter->fhash.fnum--;
- hlist_del(&tmp_fil->fnode);
- spin_unlock_bh(&adapter->mac_learn_lock);
- kfree(tmp_fil);
- }
- }
-}
-
-int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
-{
- struct qlcnic_nic_req req;
- int rv;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
-
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
- req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
- ((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
-
- req.words[0] = cpu_to_le64(flag);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
- flag ? "Set" : "Reset");
- return rv;
-}
-
-int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
-{
- if (qlcnic_set_fw_loopback(adapter, mode))
- return -EIO;
-
- if (adapter->ahw->hw_ops->config_promisc_mode(adapter,
- VPORT_MISS_MODE_ACCEPT_ALL)) {
- qlcnic_set_fw_loopback(adapter, 0);
- return -EIO;
- }
-
- msleep(1000);
- return 0;
-}
-
-int qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
-{
- struct net_device *netdev = adapter->netdev;
-
- mode = VPORT_MISS_MODE_DROP;
- qlcnic_set_fw_loopback(adapter, 0);
-
- if (netdev->flags & IFF_PROMISC)
- mode = VPORT_MISS_MODE_ACCEPT_ALL;
- else if (netdev->flags & IFF_ALLMULTI)
- mode = VPORT_MISS_MODE_ACCEPT_MULTI;
-
- adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
- msleep(1000);
- return 0;
-}
-
-/*
- * Send the interrupt coalescing parameter set by ethtool to the card.
- */
-void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_nic_req req;
- int rv;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
-
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- req.req_hdr = cpu_to_le64(QLCNIC_CONFIG_INTR_COALESCE |
- ((u64) adapter->portnum << 16));
-
- req.words[0] = cpu_to_le64(((u64) adapter->ahw->coal.flag) << 32);
- req.words[2] = cpu_to_le64(adapter->ahw->coal.rx_packets |
- ((u64) adapter->ahw->coal.rx_time_us) << 16);
- req.words[5] = cpu_to_le64(adapter->ahw->coal.timer_out |
- ((u64) adapter->ahw->coal.type) << 32 |
- ((u64) adapter->ahw->coal.sts_ring_mask) << 40);
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "Could not send interrupt coalescing parameters\n");
-}
-
-int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
-{
- struct qlcnic_nic_req req;
- u64 word;
- int rv;
-
- if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
- return 0;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
-
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- req.words[0] = cpu_to_le64(enable);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "Could not send configure hw lro request\n");
-
- return rv;
-}
-
-int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
-{
- struct qlcnic_nic_req req;
- u64 word;
- int rv;
-
- if (!!(adapter->flags & QLCNIC_BRIDGE_ENABLED) == enable)
- return 0;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
-
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_CONFIG_BRIDGING |
- ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- req.words[0] = cpu_to_le64(enable);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "Could not send configure bridge mode request\n");
-
- adapter->flags ^= QLCNIC_BRIDGE_ENABLED;
-
- return rv;
-}
-
-int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
-{
- struct qlcnic_nic_req req;
- u64 word;
- int i, rv;
-
- static const u64 key[] = {
- 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
- 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
- 0x255b0ec26d5a56daULL
- };
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- /*
- * RSS request:
- * bits 3-0: hash_method
- * 5-4: hash_type_ipv4
- * 7-6: hash_type_ipv6
- * 8: enable
- * 9: use indirection table
- * 47-10: reserved
- * 63-48: indirection table mask
- */
- word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
- ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
- ((u64)(enable & 0x1) << 8) |
- ((0x7ULL) << 48);
- req.words[0] = cpu_to_le64(word);
- for (i = 0; i < 5; i++)
- req.words[i+1] = cpu_to_le64(key[i]);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev, "could not configure RSS\n");
-
- return rv;
-}
-
-void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
-{
- struct qlcnic_nic_req req;
- struct qlcnic_ipaddr *ipa;
- u64 word;
- int rv;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- req.words[0] = cpu_to_le64(cmd);
- ipa = (struct qlcnic_ipaddr *)&req.words[1];
- ipa->ipv4 = ip;
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "could not notify %s IP 0x%x request\n",
- (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
-}
-
-int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable)
-{
- struct qlcnic_nic_req req;
- u64 word;
- int rv;
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
- req.words[0] = cpu_to_le64(enable | (enable << 8));
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "could not configure link notification\n");
-
- return rv;
-}
-
-int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_nic_req req;
- u64 word;
- int rv;
-
- if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
- return 0;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_LRO_REQUEST |
- ((u64)adapter->portnum << 16) |
- ((u64)QLCNIC_LRO_REQUEST_CLEANUP << 56) ;
-
- req.req_hdr = cpu_to_le64(word);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0)
- dev_err(&adapter->netdev->dev,
- "could not cleanup lro flows\n");
-
- return rv;
-}
-
-/*
- * qlcnic_change_mtu - Change the Maximum Transfer Unit
- * @returns 0 on success, negative on failure
- */
-
-int qlcnic_change_mtu(struct net_device *netdev, int mtu)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- int rc = 0;
-
- if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
- dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
- " not supported\n", P3P_MAX_MTU, P3P_MIN_MTU);
- return -EINVAL;
- }
-
- rc = qlcnic_fw_cmd_set_mtu(adapter, mtu);
-
- if (!rc)
- netdev->mtu = mtu;
-
- return rc;
-}
-
-
-netdev_features_t qlcnic_fix_features(struct net_device *netdev,
- netdev_features_t features)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
-
- if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
- netdev_features_t changed = features ^ netdev->features;
- features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
- }
-
- if (!(features & NETIF_F_RXCSUM))
- features &= ~NETIF_F_LRO;
-
- return features;
-}
-
-
-int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
-{
- struct qlcnic_adapter *adapter = netdev_priv(netdev);
- netdev_features_t changed = netdev->features ^ features;
- int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
-
- if (!(changed & NETIF_F_LRO))
- return 0;
-
- netdev->features = features ^ NETIF_F_LRO;
-
- if (qlcnic_config_hw_lro(adapter, hw_lro))
- return -EIO;
-
- if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter))
- return -EIO;
-
- return 0;
-}
-
-/*
- * Changes the CRB window to the specified window.
- */
- /* Returns < 0 if off is not valid,
- * 1 if window access is needed. 'off' is set to offset from
- * CRB space in 128M pci map
- * 0 if no window access is needed. 'off' is set to 2M addr
- * In: 'off' is offset from base in 128M pci map
- */
-static int
-qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw,
- ulong off, void __iomem **addr)
-{
- const struct crb_128M_2M_sub_block_map *m;
-
- if ((off >= QLCNIC_CRB_MAX) || (off < QLCNIC_PCI_CRBSPACE))
- return -EINVAL;
-
- off -= QLCNIC_PCI_CRBSPACE;
-
- /*
- * Try direct map
- */
- m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
-
- if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
- *addr = ahw->pci_base0 + m->start_2M +
- (off - m->start_128M);
- return 0;
- }
-
- /*
- * Not in direct map, use crb window
- */
- *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
- return 1;
-}
-
-/*
- * In: 'off' is offset from CRB space in 128M pci map
- * Out: 'off' is 2M pci map addr
- * side effect: lock crb window
- */
-static int
-qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off)
-{
- u32 window;
- void __iomem *addr = adapter->ahw->pci_base0 + CRB_WINDOW_2M;
-
- off -= QLCNIC_PCI_CRBSPACE;
-
- window = CRB_HI(off);
- if (window == 0) {
- dev_err(&adapter->pdev->dev, "Invalid offset 0x%lx\n", off);
- return -EIO;
- }
-
- writel(window, addr);
- if (readl(addr) != window) {
- printk_ratelimited(KERN_WARNING
- "failed to set CRB window to %d off 0x%lx\n",
- window, off);
- return -EIO;
- }
- return 0;
-}
-
-int
-qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
-{
- unsigned long flags;
- int rv;
- void __iomem *addr = NULL;
-
- rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
-
- if (rv == 0) {
- writel(data, addr);
- return 0;
- }
-
- if (rv > 0) {
- /* indirect access */
- write_lock_irqsave(&adapter->ahw->crb_lock, flags);
- crb_win_lock(adapter);
- rv = qlcnic_pci_set_crbwindow_2M(adapter, off);
- if (!rv)
- writel(data, addr);
- crb_win_unlock(adapter);
- write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
- return rv;
- }
-
- dev_err(&adapter->pdev->dev,
- "%s: invalid offset: 0x%016lx\n", __func__, off);
- dump_stack();
- return -EIO;
-}
-
-u32
-qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off, int *err)
-{
- unsigned long flags;
- int rv;
- u32 data = -1;
- void __iomem *addr = NULL;
-
- rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
-
- if (rv == 0)
- return readl(addr);
-
- if (rv > 0) {
- /* indirect access */
- write_lock_irqsave(&adapter->ahw->crb_lock, flags);
- crb_win_lock(adapter);
- if (!qlcnic_pci_set_crbwindow_2M(adapter, off))
- data = readl(addr);
- crb_win_unlock(adapter);
- write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
- return data;
- }
-
- dev_err(&adapter->pdev->dev,
- "%s: invalid offset: 0x%016lx\n", __func__, off);
- dump_stack();
- if (err)
- *err = -1;
-
- return -1;
-}
-
-
-void __iomem *
-qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, u32 offset)
-{
- void __iomem *addr = NULL;
-
- WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr));
-
- return addr;
-}
-
-static int
-qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u32 window,
- u64 off, u64 *data, int op)
-{
- void __iomem *addr;
- u32 start;
-
- mutex_lock(&adapter->ahw->mem_lock);
-
- writel(window, adapter->ahw->ocm_win_crb);
- /* read back to flush */
- readl(adapter->ahw->ocm_win_crb);
- start = QLCNIC_PCI_OCM0_2M + off;
-
- addr = adapter->ahw->pci_base0 + start;
-
- if (op == 0) /* read */
- *data = readq(addr);
- else /* write */
- writeq(*data, addr);
-
- /* Set window to 0 */
- writel(0, adapter->ahw->ocm_win_crb);
- readl(adapter->ahw->ocm_win_crb);
-
- mutex_unlock(&adapter->ahw->mem_lock);
- return 0;
-}
-
-void
-qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
-{
- void __iomem *addr = adapter->ahw->pci_base0 +
- QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
-
- mutex_lock(&adapter->ahw->mem_lock);
- *data = readq(addr);
- mutex_unlock(&adapter->ahw->mem_lock);
-}
-
-void
-qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
-{
- void __iomem *addr = adapter->ahw->pci_base0 +
- QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
-
- mutex_lock(&adapter->ahw->mem_lock);
- writeq(data, addr);
- mutex_unlock(&adapter->ahw->mem_lock);
-}
-
-#define MAX_CTL_CHECK 1000
-
-/* Set MS memory control data for different chip type*/
-static void
-qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off,
- struct qlcnic_ms_reg_ctrl *ms)
-{
- ms->control = QLCNIC_MS_CTRL;
- ms->low = QLCNIC_MS_ADDR_LO;
- ms->hi = QLCNIC_MS_ADDR_HI;
- if (off & 0xf) {
- ms->wd[0] = QLCNIC_MS_WRTDATA_LO;
- ms->rd[0] = QLCNIC_MS_RDDATA_LO;
- ms->wd[1] = QLCNIC_MS_WRTDATA_HI;
- ms->rd[1] = QLCNIC_MS_RDDATA_HI;
- ms->wd[2] = QLCNIC_MS_WRTDATA_ULO;
- ms->wd[3] = QLCNIC_MS_WRTDATA_UHI;
- ms->rd[2] = QLCNIC_MS_RDDATA_ULO;
- ms->rd[3] = QLCNIC_MS_RDDATA_UHI;
- } else {
- ms->wd[0] = QLCNIC_MS_WRTDATA_ULO;
- ms->rd[0] = QLCNIC_MS_RDDATA_ULO;
- ms->wd[1] = QLCNIC_MS_WRTDATA_UHI;
- ms->rd[1] = QLCNIC_MS_RDDATA_UHI;
- ms->wd[2] = QLCNIC_MS_WRTDATA_LO;
- ms->wd[3] = QLCNIC_MS_WRTDATA_HI;
- ms->rd[2] = QLCNIC_MS_RDDATA_LO;
- ms->rd[3] = QLCNIC_MS_RDDATA_HI;
- }
- if (QLCNIC_IS_83XX(adapter)) {
- ms->ocm_window = OCM_WIN_83XX(off);
- ms->off = GET_83XX_OCM_OFFSET(off);
- } else {
- ms->ocm_window = OCM_WIN_P3P(off);
- ms->off = GET_MEM_OFFS_2M(off);
- }
-}
-
-int
-qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
- u64 off, u64 data)
-{
- int j, ret = 0;
- u32 temp, off8;
- struct qlcnic_ms_reg_ctrl ms;
-
- /* Only 64-bit aligned access */
- if (off & 7)
- return -EIO;
-
- memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
- if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) ||
- (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
- QLCNIC_ADDR_DDR_NET_MAX))))
- return -EIO;
-
- qlcnic_set_ms_controls(adapter, off, &ms);
-
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
- return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
- ms.off, &data, 1);
-
- off8 = off & ~0xf;
-
- mutex_lock(&adapter->ahw->mem_lock);
-
- qlcnic_ind_wr(adapter, ms.low, off8);
- qlcnic_ind_wr(adapter, ms.hi, 0);
-
- qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
- qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
-
- for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = qlcnic_ind_rd(adapter, ms.control);
- if ((temp & TA_CTL_BUSY) == 0)
- break;
- }
-
- if (j >= MAX_CTL_CHECK) {
- ret = -EIO;
- goto done;
- }
-
- /* This is the modify part of read-modify-write */
- qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0]));
- qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1]));
- /* This is the write part of read-modify-write */
- qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff);
- qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff);
-
- qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_ENABLE);
- qlcnic_ind_wr(adapter, ms.control, QLC_TA_WRITE_START);
-
- for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = qlcnic_ind_rd(adapter, ms.control);
- if ((temp & TA_CTL_BUSY) == 0)
- break;
- }
-
- if (j >= MAX_CTL_CHECK) {
- printk_ratelimited(KERN_WARNING
- "failed to write through agent\n");
- ret = -EIO;
- } else {
- ret = 0;
- }
-
-done:
- mutex_unlock(&adapter->ahw->mem_lock);
-
- return ret;
-}
-
-int
-qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
- u64 off, u64 *data)
-{
- int j, ret;
- u32 temp, off8;
- u64 val;
- struct qlcnic_ms_reg_ctrl ms;
-
- /* Only 64-bit aligned access */
- if (off & 7)
- return -EIO;
- if (!((ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
- QLCNIC_ADDR_QDR_NET_MAX)) ||
- (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
- QLCNIC_ADDR_DDR_NET_MAX))))
- return -EIO ;
-
- memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
- qlcnic_set_ms_controls(adapter, off, &ms);
-
- if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
- return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
- ms.off, data, 0);
-
- mutex_lock(&adapter->ahw->mem_lock);
-
- off8 = off & ~0xf;
-
- qlcnic_ind_wr(adapter, ms.low, off8);
- qlcnic_ind_wr(adapter, ms.hi, 0);
-
- qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
- qlcnic_ind_wr(adapter, ms.control, QLC_TA_START_ENABLE);
-
- for (j = 0; j < MAX_CTL_CHECK; j++) {
- temp = qlcnic_ind_rd(adapter, ms.control);
- if ((temp & TA_CTL_BUSY) == 0)
- break;
- }
-
- if (j >= MAX_CTL_CHECK) {
- printk_ratelimited(KERN_WARNING
- "failed to read through agent\n");
- ret = -EIO;
- } else {
-
- temp = qlcnic_ind_rd(adapter, ms.rd[3]);
- val = (u64)temp << 32;
- val |= qlcnic_ind_rd(adapter, ms.rd[2]);
- *data = val;
- ret = 0;
- }
-
- mutex_unlock(&adapter->ahw->mem_lock);
-
- return ret;
-}
-
-int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
-{
- int offset, board_type, magic, err;
- struct pci_dev *pdev = adapter->pdev;
- struct qlcnic_hardware_context *ahw = adapter->ahw;
-
- offset = QLCNIC_FW_MAGIC_OFFSET;
- if (qlcnic_rom_fast_read(adapter, offset, &magic))
- return -EIO;
-
- if (magic != QLCNIC_BDINFO_MAGIC) {
- dev_err(&pdev->dev, "invalid board config, magic=%08x\n",
- magic);
- return -EIO;
- }
-
- offset = QLCNIC_BRDTYPE_OFFSET;
- if (qlcnic_rom_fast_read(adapter, offset, &board_type))
- return -EIO;
-
- ahw->board_type = board_type;
-
- if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
- u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I, &err);
- if ((gpio & 0x8000) == 0)
- board_type = QLCNIC_BRDTYPE_P3P_10G_TP;
- }
-
- switch (board_type) {
- case QLCNIC_BRDTYPE_P3P_HMEZ:
- case QLCNIC_BRDTYPE_P3P_XG_LOM:
- case QLCNIC_BRDTYPE_P3P_10G_CX4:
- case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
- case QLCNIC_BRDTYPE_P3P_IMEZ:
- case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
- case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
- case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
- case QLCNIC_BRDTYPE_P3P_10G_XFP:
- case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
- ahw->port_type = QLCNIC_XGBE;
- break;
- case QLCNIC_BRDTYPE_P3P_REF_QG:
- case QLCNIC_BRDTYPE_P3P_4_GB:
- case QLCNIC_BRDTYPE_P3P_4_GB_MM:
- ahw->port_type = QLCNIC_GBE;
- break;
- case QLCNIC_BRDTYPE_P3P_10G_TP:
- ahw->port_type = (adapter->portnum < 2) ?
- QLCNIC_XGBE : QLCNIC_GBE;
- break;
- default:
- dev_err(&pdev->dev, "unknown board type %x\n", board_type);
- ahw->port_type = QLCNIC_XGBE;
- break;
- }
-
- return 0;
-}
-
-int
-qlcnic_wol_supported(struct qlcnic_adapter *adapter)
-{
- int err;
- u32 wol_cfg;
-
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
- if (wol_cfg & (1UL << adapter->portnum)) {
- wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
- if (wol_cfg & (1 << adapter->portnum))
- return 1;
- }
-
- return 0;
-}
-
-int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
-{
- struct qlcnic_nic_req req;
- int rv;
- u64 word;
-
- memset(&req, 0, sizeof(struct qlcnic_nic_req));
- req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
-
- word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16);
- req.req_hdr = cpu_to_le64(word);
-
- req.words[0] = cpu_to_le64((u64)rate << 32);
- req.words[1] = cpu_to_le64(state);
-
- rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv)
- dev_err(&adapter->pdev->dev, "LED configuration failed.\n");
-
- return rv;
-}
-
-void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
-{
- void __iomem *msix_base_addr;
- u32 func;
- u32 msix_base;
-
- pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
- msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
- msix_base = readl(msix_base_addr);
- func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
- adapter->ahw->pci_func = func;
-}
-
-void qlcnic_get_ocm_win(struct qlcnic_hardware_context *ahw)
-{
- ahw->ocm_win_crb = qlcnic_get_ioaddr(ahw, QLCNIC_PCIX_PS_REG(
- PCIX_OCM_WINDOW_REG(ahw->pci_func)));
-}
-
-void qlcnic_read_crb(struct qlcnic_adapter *adapter, char *buf,
- loff_t offset, size_t size)
-{
- int err;
- u32 data;
- u64 qmdata;
-
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
- memcpy(buf, &qmdata, size);
- } else {
- data = QLCRD32(adapter, offset, &err);
- memcpy(buf, &data, size);
- }
-}
-
-void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf,
- loff_t offset, size_t size)
-{
- u32 data;
- u64 qmdata;
-
- if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
- memcpy(&qmdata, buf, size);
- qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
- } else {
- memcpy(&data, buf, size);
- QLCWR32(adapter, offset, data);
- }
-}
-
-int qlcnic_api_lock(struct qlcnic_adapter *adapter)
-{
- return qlcnic_pcie_sem_lock(adapter, 5, 0);
-}
-
-void qlcnic_api_unlock(struct qlcnic_adapter *adapter)
-{
- qlcnic_pcie_sem_unlock(adapter, 5);
-}
-
-void qlcnic_add_sysfs(struct qlcnic_adapter *adapter)
-{
- qlcnic_create_diag_entries(adapter);
-}
-
-void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter)
-{
- qlcnic_remove_diag_entries(adapter);
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 2f3966e..d9551a3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -1,8 +1,6 @@
#ifndef __QLCNIC_HW_H
#define __QLCNIC_HW_H
-#include "qlcnic.h"
-
#define MASK(n) ((1ULL<<(n))-1)
#define OCM_WIN_P3P(addr) (addr & 0xffc0000)
#define OCM_WIN_83XX(addr) (addr & 0xFFE0000)
@@ -22,7 +20,7 @@
#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
#define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030
#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
-#define QLCNIC_83XX_BAR0_LENGTH 0x4000
+#define QLC_83XX_BAR0_LENGTH 0x4000
#define QLCNIC_IS_83XX(adapter) \
(((adapter)->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? 1 : 0)
@@ -82,7 +80,11 @@ struct qlcnic_ms_reg_ctrl {
writel(value, (((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr])))
#define QLCNIC_READ_LINK_SPEED(adapter, pcifn, err)\
- QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn), err)
+ (QLCNIC_IS_83XX(adapter) ?\
+ (((readl(adapter->ahw->pci_base0 + QLC_83XX_LINK_SPEED(pcifn)) >> \
+ ((pcifn % 4) << 4)) & 0xFFFF) * QLC_83XX_LINK_SPEED_FACTOR) :\
+ (P3P_LINK_SPEED_MHZ * P3P_LINK_SPEED_VAL(pcifn, \
+ QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn), err))))
/* Mailbox ownership */
#define QLCNIC_GET_OWNER(val) \
@@ -124,6 +126,7 @@ struct qlcnic_ms_reg_ctrl {
#define QLCNIC_CMD_TEMP_SIZE 0x2f
#define QLCNIC_CMD_GET_TEMP_HDR 0x30
#define QLCNIC_CMD_GET_MAC_STATS 0x37
+#define QLCNIC_CMD_SET_DRV_VER 0x38
#define QLCNIC_CMD_CONFIGURE_RSS 0x41
#define QLCNIC_CMD_CONFIG_INTR_COAL 0x43
#define QLCNIC_CMD_CONFIGURE_LED 0x44
@@ -175,7 +178,7 @@ do { \
*bar = QLCNIC_82XX_BAR0_LENGTH; \
break; \
case PCI_DEVICE_ID_QLOGIC_QLE834X: \
- *bar = QLCNIC_83XX_BAR0_LENGTH; \
+ *bar = QLC_83XX_BAR0_LENGTH; \
break; \
default: \
*bar = 0; \
@@ -219,7 +222,9 @@ do { \
((ahw)->pci_base0 + 0x800 + ((i) * 4))
#define QLCNIC_IS_TSO_CAPABLE(adapter)\
- ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ ((QLCNIC_IS_82XX(adapter)) ?\
+ ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) :\
+ ((adapter)->ahw->capabilities & QLCNIC_FW_83XX_CAPABILITY_TSO))
#define QLCNIC_IS_VLAN_TX_CAPABLE(adapter) \
((QLCNIC_IS_82XX(adapter)) ?\
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 737adea..3b10acc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -662,7 +662,7 @@ static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
flt_entry = vmalloc(entry_size);
if (flt_entry == NULL) {
- dev_warn(&adapter->pdev->dev, "error allocating memory\n");
+ dev_err(&adapter->pdev->dev, "error allocating memory\n");
return -EIO;
}
memset(flt_entry, 0, entry_size);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 1c384f1..ce8a4e0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -115,6 +115,7 @@ qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
vh = (struct vlan_ethhdr *)skb->data;
flags = FLAGS_VLAN_TAGGED;
vlan_tci = vh->h_vlan_TCI;
+ protocol = ntohs(vh->h_vlan_encapsulated_proto);
} else if (vlan_tx_tag_present(skb)) {
flags = FLAGS_VLAN_OOB;
vlan_tci = vlan_tx_tag_get(skb);
@@ -724,8 +725,6 @@ struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
skb_checksum_none_assert(skb);
}
- skb->dev = adapter->netdev;
-
buffer->skb = NULL;
return skb;
@@ -885,6 +884,9 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
length = skb->len;
+ if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+ skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
+
if (vid != 0xffff)
__vlan_hwaccel_put_tag(skb, vid);
netif_receive_skb(skb);
@@ -1075,7 +1077,8 @@ void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
pr_info("\n");
for (i = 0; i < skb->len; i++) {
- QLCDB(adapter, DRV, "%02x ", data[i]);
+ netif_info(adapter->ahw, pktdata, adapter->netdev,
+ "%02x ", data[i]);
if ((i & 0x0f) == 8)
pr_info("\n");
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 9d1962f..5d423c1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -35,6 +35,10 @@ char qlcnic_driver_name[] = "qlcnic";
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
+static int qlcnic_debug_level = -1;
+module_param(qlcnic_debug_level, int, 0664);
+MODULE_PARM_DESC(qlcnic_debug_level, "Debug level (0=none,...,16=all)");
+
static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0444);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
@@ -252,7 +256,7 @@ qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, struct net_device *netdev)
return 0;
}
-int
+static int
qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
int ring;
@@ -653,7 +657,7 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
pfn = pci_info[i].id;
- if (pfn > QLCNIC_MAX_PCI_FUNC) {
+ if (pfn >= QLCNIC_MAX_PCI_FUNC) {
ret = QL_STATUS_INVALID_PARAM;
goto err_eswitch;
}
@@ -727,7 +731,7 @@ err_lock:
return ret;
}
-void
+static void
qlcnic_check_vf(struct qlcnic_adapter *adapter, const struct pci_device_id *ent)
{
void __iomem *priv_op;
@@ -803,17 +807,18 @@ static void qlcnic_get_brd_name(struct qlcnic_adapter *adapter, char *name)
qlcnic_boards[i].device == pdev->device &&
qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor &&
qlcnic_boards[i].sub_device == pdev->subsystem_device) {
- sprintf(name, "%pM: %s" ,
- adapter->mac_addr,
- qlcnic_boards[i].short_name);
- found = 1;
- break;
+ snprintf(name, QLCNIC_MAX_BOARD_NAME_LEN, "%pM: %s",
+ adapter->mac_addr,
+ qlcnic_boards[i].short_name);
+ found = 1;
+ break;
}
}
if (!found)
- sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
+ snprintf(name, ETH_ALEN, "%pM Gigabit Ethernet",
+ adapter->mac_addr);
}
void
@@ -849,8 +854,8 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
}
}
- dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
- fw_major, fw_minor, fw_build);
+ dev_info(&pdev->dev, "Driver v%s, firmware v%d.%d.%d\n",
+ QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
if (ahw->port_type == QLCNIC_XGBE) {
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
@@ -884,6 +889,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
struct qlcnic_info nic_info;
struct qlcnic_hardware_context *ahw = adapter->ahw;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
err = ahw->hw_ops->get_nic_info(adapter, &nic_info, ahw->pci_func);
if (err)
return err;
@@ -1118,6 +1124,7 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
npar = &adapter->npars[i];
pci_func = npar->pci_func;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
err = ahw->hw_ops->get_nic_info(adapter, &nic_info, pci_func);
if (err)
return err;
@@ -1287,8 +1294,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
- sprintf(sds_ring->name, "%s[%d]",
- netdev->name, ring);
+ snprintf(sds_ring->name, sizeof(int) + IFNAMSIZ,
+ "%s[%d]", netdev->name, ring);
err = request_irq(sds_ring->irq, handler, flags,
sds_ring->name, sds_ring);
if (err)
@@ -1300,7 +1307,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->max_drv_tx_rings;
ring++) {
tx_ring = &adapter->tx_ring[ring];
- sprintf(tx_ring->name, "%s[%d]", netdev->name,
+ snprintf(tx_ring->name, sizeof(int) + IFNAMSIZ,
+ "%s[%d]", netdev->name,
adapter->max_sds_rings + ring);
err = request_irq(tx_ring->irq, handler, flags,
tx_ring->name, tx_ring);
@@ -1341,7 +1349,10 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
static int
__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
+ int err;
u8 ring;
+ u32 capab2;
+
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -1354,6 +1365,12 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (qlcnic_set_eswitch_port_config(adapter))
return -EIO;
+ if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
+ capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2, &err);
+ if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
+ adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
+ }
+
if (qlcnic_fw_create_ctx(adapter))
return -EIO;
@@ -1424,6 +1441,7 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
adapter->ahw->hw_ops->napi_disable(adapter);
qlcnic_fw_destroy_ctx(adapter);
+ adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP;
qlcnic_reset_rx_buffers_list(adapter);
qlcnic_release_tx_buffers(adapter);
@@ -1632,7 +1650,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
}
/* Reset context in hardware only */
-int
+static int
qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -1766,14 +1784,16 @@ int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ u32 capab2;
struct net_device *netdev = NULL;
struct qlcnic_adapter *adapter = NULL;
struct qlcnic_hardware_context *ahw;
int err;
- uint8_t pci_using_dac;
+ uint8_t pci_using_dac = 0;
char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
err = pci_enable_device(pdev);
+
if (err)
return err;
@@ -1823,6 +1843,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->pdev = pdev;
adapter->ahw = ahw;
+ adapter->ahw->msg_enable =
+ netif_msg_init(qlcnic_debug_level, QLCNIC_DBG_LEVEL_MASK);
+
adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic");
if (adapter->qlcnic_wq == NULL) {
dev_err(&pdev->dev, "Failed to create workqueue\n");
@@ -1883,6 +1906,14 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
module_name(THIS_MODULE),
brd_name, adapter->ahw->revision_id);
}
+
+ if ((QLCNIC_IS_82XX(adapter)) && (adapter->ahw->capabilities &
+ QLCNIC_FW_CAPABILITY_MORE_CAPS)) {
+ capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2, &err);
+ if (capab2 & QLCNIC_FW_CAPABILITY_2_OCBB)
+ qlcnic_fw_cmd_set_drv_version(adapter);
+ }
+
err = ahw->hw_ops->setup_intr(adapter, 0);
if (err)
goto err_out_disable_msi;
@@ -2178,6 +2209,9 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter)
temp = 0;
+ if (QLCNIC_IS_83XX(adapter))
+ temp = QLCRDX(adapter->ahw, QLC_83XX_ASIC_TEMP);
+
if (QLCNIC_IS_82XX(adapter))
temp = QLCRD(adapter, QLCNIC_ASIC_TEMP);
@@ -2482,7 +2516,8 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
}
prev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
- QLCDB(adapter, HW, "Device state = %u\n", prev_state);
+ netif_info(adapter->ahw, hw, adapter->netdev,
+ "Device state = %u\n", prev_state);
switch (prev_state) {
case QLCNIC_DEV_COLD:
@@ -2595,7 +2630,8 @@ skip_ack_check:
QLCWR(adapter, QLCNIC_CRB_DEV_STATE,
QLCNIC_DEV_INITIALIZING);
set_bit(__QLCNIC_START_FW, &adapter->state);
- QLCDB(adapter, DRV, "Restarting fw\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "Restarting fw\n");
qlcnic_idc_debug_info(adapter, 0);
val = QLCRD(adapter, QLCNIC_CRB_DRV_STATE);
QLC_DEV_SET_RST_RDY(val, adapter->portnum);
@@ -2623,7 +2659,8 @@ skip_ack_check:
wait_npar:
dev_state = QLCRD(adapter, QLCNIC_CRB_DEV_STATE);
- QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
+ netif_info(adapter->ahw, hw, adapter->netdev,
+ "Func waiting: Device state=%u\n", dev_state);
switch (dev_state) {
case QLCNIC_DEV_READY:
@@ -2751,7 +2788,8 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
if (state == QLCNIC_DEV_READY) {
QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
adapter->flags |= QLCNIC_FW_RESET_OWNER;
- QLCDB(adapter, DRV, "NEED_RESET state set\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "NEED_RESET state set\n");
qlcnic_idc_debug_info(adapter, 0);
}
@@ -2768,7 +2806,8 @@ qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
return;
QLCWR(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
- QLCDB(adapter, DRV, "NPAR operational state set\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "NPAR operational state set\n");
adapter->ahw->hw_ops->api_unlock(adapter);
}
@@ -2802,7 +2841,8 @@ qlcnic_attach_work(struct work_struct *work)
FW_POLL_DELAY);
else
goto attach;
- QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n");
+ netif_info(adapter->ahw, drv, netdev,
+ "Waiting for NPAR state to operational\n");
return;
}
attach:
@@ -2895,7 +2935,8 @@ detach:
!test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
- QLCDB(adapter, DRV, "fw recovery scheduled.\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "fw recovery scheduled.\n");
}
return 1;
@@ -2981,7 +3022,8 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
- QLCDB(adapter, DRV, "Restarting fw\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "Restarting fw\n");
}
ahw->hw_ops->api_unlock(adapter);
@@ -3122,8 +3164,15 @@ qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
int qlcnic_validate_max_rss(u8 max_hw, u8 val)
{
- u32 max_allowed = rounddown_pow_of_two(
- min_t(int, max_hw, num_online_cpus()));
+ u32 max_allowed;
+
+ if (max_hw > MAX_SDS_RINGS) {
+ max_hw = MAX_SDS_RINGS;
+ pr_info("max rss reset to %d\n", MAX_SDS_RINGS);
+ }
+
+ max_allowed = rounddown_pow_of_two(
+ min_t(int, max_hw, num_online_cpus()));
if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) {
pr_info("rss_ring valid range [2 - %x] in powers of 2\n",
@@ -3139,7 +3188,9 @@ qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
int err;
struct net_device *netdev = adapter->netdev;
- rtnl_lock();
+ if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+ return -EBUSY;
+
netif_device_detach(netdev);
if (netif_running(netdev))
__qlcnic_down(adapter, netdev);
@@ -3179,7 +3230,6 @@ qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
err = len;
done:
netif_device_attach(netdev);
- rtnl_unlock();
return err;
}
@@ -3188,7 +3238,7 @@ qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
-void
+static void
qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
struct net_device *dev, unsigned long event)
{
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index c1d5a6a..1720afc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -75,7 +75,7 @@ qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
timeout++;
}
if (timeout > ctr->timeout) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Timed out, aborting poll CRB\n");
return 0;
}
@@ -106,7 +106,7 @@ qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
t_hdr->saved_state[ctr->index_v] = data;
break;
default:
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Unknown opcode\n");
break;
}
@@ -293,7 +293,7 @@ qlcnic_read_memory(struct qlcnic_adapter *adapter,
addr = mem->addr;
/* check for data size of multiple of 16 and 16 byte alignment */
if ((addr & 0xf) || (reg_read%16)) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Unaligned memory addr:0x%x size:0x%x\n",
addr, reg_read);
return 0;
@@ -344,7 +344,7 @@ qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
{
int ret = 1;
if (size != entry->hdr.cap_size) {
- dev_info(dev,
+ dev_err(dev,
"Invalid entry, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
ret = 0;
@@ -475,7 +475,7 @@ qlcnic_83xx_dump_rom(struct qlcnic_adapter *adapter,
fl_addr = rom->addr;
size = rom->size/4;
- if (!qlcnic_83xx_lockless_flash_read_u32(adapter,
+ if (!qlcnic_83xx_lockless_flash_read32(adapter,
fl_addr, (u8 *)buffer, size))
return rom->size;
@@ -554,7 +554,7 @@ qlcnic_fw_flash_get_minidump_temp(struct qlcnic_adapter *adapter,
if (qlcnic_83xx_lock_flash(adapter))
return -EIO;
- ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ ret = qlcnic_83xx_lockless_flash_read32(adapter,
QLC_83XX_MINIDUMP_FLASH, buffer, size/sizeof(u32));
qlcnic_83xx_unlock_flash(adapter);
@@ -576,7 +576,7 @@ qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter,
if (qlcnic_83xx_lock_flash(adapter))
return -EIO;
- ret = qlcnic_83xx_lockless_flash_read_u32(adapter,
+ ret = qlcnic_83xx_lockless_flash_read32(adapter,
QLC_83XX_MINIDUMP_FLASH, (u8 *)&tmp_hdr, size);
qlcnic_83xx_unlock_flash(adapter);
@@ -678,7 +678,7 @@ qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
&temp_size, &use_flash_temp);
if (err) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Can't get template size %d\n", err);
return -EIO;
}
@@ -752,7 +752,8 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
return -EIO;
}
- QLCDB(adapter, DRV, "Take FW dump\n");
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "Take FW dump\n");
/* Calculate the size for dump data area only */
for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
if (i & tmpl_hdr->drv_cap_mask)
@@ -762,7 +763,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
fw_dump->data = vmalloc(dump_size);
if (!fw_dump->data) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Unable to allocate (%d KB) for fw dump\n",
dump_size/1024);
return -ENOMEM;
@@ -804,7 +805,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
}
if (ops_index == ops_cnt) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Invalid entry type %d, exiting dump\n",
entry->hdr.type);
goto error;
@@ -819,7 +820,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
buffer = fw_dump->data + buf_offset;
}
if (dump_size != buf_offset) {
- dev_info(&adapter->pdev->dev,
+ dev_err(&adapter->pdev->dev,
"Captured(%d) and expected size(%d) do not match\n",
buf_offset, dump_size);
goto error;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 9f743bf..e8f021b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -35,7 +35,7 @@ qlcnic_show_bridged_mode(struct device *dev,
if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
- return sprintf(buf, "%d\n", bridged_mode);
+ return snprintf(buf, sizeof(int), "%d\n", bridged_mode);
}
static struct device_attribute dev_attr_bridged_mode = {
@@ -66,7 +66,7 @@ qlcnic_show_diag_mode(struct device *dev,
{
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n",
+ return snprintf(buf, sizeof(u32), "%d\n",
!!(adapter->flags & QLCNIC_DIAG_ENABLED));
}
@@ -83,7 +83,8 @@ qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
*rate = LSB(beacon);
*state = MSB(beacon);
- QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
+ netif_info(adapter->ahw, drv, adapter->netdev,
+ "rate %x state %x\n", *rate, *state);
if (!*state) {
*rate = __QLCNIC_MAX_LED_RATE;
@@ -159,7 +160,7 @@ qlcnic_show_beacon(struct device *dev,
{
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
+ return snprintf(buf, sizeof(u8), "%d\n", adapter->ahw->beacon_state);
}
static struct device_attribute dev_attr_beacon = {
@@ -380,6 +381,9 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
if (size != sizeof(pm_cfg))
return QL_STATUS_INVALID_PARAM;
+ memset(&pm_cfg, 0,
+ sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC);
+
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
pci_func = adapter->npars[i].pci_func;
pm_cfg[pci_func].action = adapter->npars[i].enable_pm;
@@ -401,6 +405,8 @@ validate_esw_config(struct qlcnic_adapter *adapter,
if (QLCNIC_IS_82XX(adapter))
op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+ else
+ op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
@@ -415,6 +421,10 @@ validate_esw_config(struct qlcnic_adapter *adapter,
case QLCNIC_PORT_DEFAULTS:
if (QLCNIC_IS_82XX(adapter)) {
ret = QLC_DEV_GET_DRV(op_mode, pci_func);
+ } else {
+ ret = QLC_83XX_GET_FUNC_PRIVILEGE_LEVEL(
+ op_mode, pci_func);
+ esw_cfg[i].offload_flags = 0;
}
if (ret != QLCNIC_NON_PRIV_FUNC) {
@@ -531,6 +541,9 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
if (size != sizeof(esw_cfg))
return QL_STATUS_INVALID_PARAM;
+ memset(&esw_cfg, 0,
+ sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC);
+
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
pci_func = adapter->npars[i].pci_func;
esw_cfg[pci_func].pci_func = pci_func;
@@ -583,6 +596,7 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count ; i++) {
pci_func = np_cfg[i].pci_func;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
ret = adapter->ahw->hw_ops->get_nic_info(adapter,
&nic_info, pci_func);
if (ret)
@@ -615,6 +629,10 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
if (size != sizeof(np_cfg))
return QL_STATUS_INVALID_PARAM;
+ memset(&nic_info, 0, sizeof(struct qlcnic_info));
+ memset(&np_cfg, 0, sizeof(struct qlcnic_npar_func_cfg) *
+ QLCNIC_MAX_PCI_FUNC);
+
for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
if (qlcnic_is_valid_nic_func(adapter, i) < 0)
continue;
@@ -771,6 +789,9 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
if (size != sizeof(pci_cfg))
return QL_STATUS_INVALID_PARAM;
+ memset(&pci_cfg, 0,
+ sizeof(struct qlcnic_pci_func_cfg) * QLCNIC_MAX_PCI_FUNC);
+
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info)
return -ENOMEM;
@@ -862,32 +883,32 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
struct device *dev = &adapter->pdev->dev;
if (device_create_bin_file(dev, &bin_attr_port_stats))
- dev_info(dev, "failed to create port stats sysfs entry");
+ dev_err(dev, "failed to create port stats sysfs entry");
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
- dev_info(dev, "failed to create diag_mode sysfs entry\n");
+ dev_err(dev, "failed to create diag_mode sysfs entry\n");
if (device_create_file(dev, &dev_attr_beacon))
- dev_info(dev, "failed to create beacon sysfs entry");
+ dev_err(dev, "failed to create beacon sysfs entry");
if (device_create_bin_file(dev, &bin_attr_crb))
- dev_info(dev, "failed to create crb sysfs entry\n");
+ dev_err(dev, "failed to create crb sysfs entry\n");
if (device_create_bin_file(dev, &bin_attr_mem))
- dev_info(dev, "failed to create mem sysfs entry\n");
+ dev_err(dev, "failed to create mem sysfs entry\n");
if (device_create_bin_file(dev, &bin_attr_pci_config))
- dev_info(dev, "failed to create pci config sysfs entry");
+ dev_err(dev, "failed to create pci config sysfs entry");
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
if (device_create_bin_file(dev, &bin_attr_esw_config))
- dev_info(dev, "failed to create esw config sysfs entry");
+ dev_err(dev, "failed to create esw config sysfs entry");
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
return;
if (device_create_bin_file(dev, &bin_attr_npar_config))
- dev_info(dev, "failed to create npar config sysfs entry");
+ dev_err(dev, "failed to create npar config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_pm_config))
- dev_info(dev, "failed to create pm config sysfs entry");
+ dev_err(dev, "failed to create pm config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_esw_stats))
- dev_info(dev, "failed to create eswitch stats sysfs entry");
+ dev_err(dev, "failed to create eswitch stats sysfs entry");
}
void
@@ -923,7 +944,7 @@ qlcnic_sysfs_validate_bar(struct qlcnic_adapter *adapter, loff_t offset,
if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
return -EIO;
- if (offset >= QLCNIC_83XX_BAR0_LENGTH || (offset & (bar - 1)) ||
+ if (offset >= QLC_83XX_BAR0_LENGTH || (offset & (bar - 1)) ||
(size != bar))
return -EINVAL;
return 0;
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 15/15] qlcnic: update driver version - 5.1.30
From: Sony Chacko @ 2012-08-24 1:07 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko
In-Reply-To: <1345770439-30517-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index ddd8795..bd01819 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 1
-#define _QLCNIC_LINUX_SUBVERSION 29
-#define QLCNIC_LINUX_VERSIONID "5.1.29"
+#define _QLCNIC_LINUX_SUBVERSION 30
+#define QLCNIC_LINUX_VERSIONID "5.1.30"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
--
1.7.1
^ permalink raw reply related
* [PATCH net-next v2] net: dev: fix the incorrect hold of net namespace's lo device
From: Gao feng @ 2012-08-24 1:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Gao feng, Eric Dumazet, Eric W. Biederman
When moving a net device from one net namespace to another
net namespace,dev_change_net_namespace calls NETDEV_DOWN
event,so the original net namespace's dst entries which
beloned to this net device will be put into dst_garbage
list.
then dev_change_net_namespace will set this net device's
net to the new net namespace.
If we unregister this net device's driver, this will trigger
the NETDEV_UNREGISTER_FINAL event, dst_ifdown will be called,
and get this net device's dst entries from dst_garbage list,
put these entries' dev to the new net namespace's lo device.
It's not what we want,actually we need these dst entries hold
the original net namespace's lo device,this incorrect device
holding will trigger emg message like below.
unregister_netdevice: waiting for lo to become free. Usage count = 1
so we should call NETDEV_UNREGISTER_FINAL event in
dev_change_net_namespace too,in order to make sure dst entries
already in the dst_garbage list, we need rcu_barrier before we
call NETDEV_UNREGISTER_FINAL event.
With help form Eric Dumazet.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
---
net/core/dev.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index bc857fe..6956d4c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6256,6 +6256,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
the device is just moving and can keep their slaves up.
*/
call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+ rcu_barrier();
+ call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
/*
--
1.7.7.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox