[PATCH net-next v3 6/6] qede: Register l2 queues with doorbell overflow recovery mechanism

2018-11-28 Thread Ariel Elior
All L2 queues funnel through this flow, so this would cover the
regular RSS queues, as well queues created for VFs, mqos queues,
xdp queues, etc.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c 
b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 46d0f2e..1c4cea8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1774,6 +1774,10 @@ static int qede_drain_txq(struct qede_dev *edev,
 static int qede_stop_txq(struct qede_dev *edev,
 struct qede_tx_queue *txq, int rss_id)
 {
+   /* delete doorbell from doorbell recovery mechanism */
+   edev->ops->common->db_recovery_del(edev->cdev, txq->doorbell_addr,
+  >tx_db);
+
return edev->ops->q_tx_stop(edev->cdev, rss_id, txq->handle);
 }
 
@@ -1910,6 +1914,11 @@ static int qede_start_txq(struct qede_dev *edev,
  DQ_XCM_ETH_TX_BD_PROD_CMD);
txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
 
+   /* register doorbell with doorbell recovery mechanism */
+   rc = edev->ops->common->db_recovery_add(edev->cdev, txq->doorbell_addr,
+   >tx_db, DB_REC_WIDTH_32B,
+   DB_REC_KERNEL);
+
return rc;
 }
 
-- 
1.8.3.1



[PATCH net-next v3 5/6] qed: Expose the doorbell overflow recovery mechanism to the protocol drivers

2018-11-28 Thread Ariel Elior
Most of the doorbelling entities are outside of the core module.
L2 queues, Roce queues, iscsi and fcoe all need to register.
Make the APIs available for these drivers.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_main.c |  2 ++
 include/linux/qed/qed_if.h | 27 +++
 2 files changed, 29 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f2c50ef..a0b761d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -2238,6 +2238,8 @@ static int qed_read_module_eeprom(struct qed_dev *cdev, 
char *buf,
.update_mac = _update_mac,
.update_mtu = _update_mtu,
.update_wol = _update_wol,
+   .db_recovery_add = _db_recovery_add,
+   .db_recovery_del = _db_recovery_del,
.read_module_eeprom = _read_module_eeprom,
 };
 
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 41382e7..8b2b005 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -1009,6 +1009,33 @@ struct qed_common_ops {
  */
int (*set_led)(struct qed_dev *cdev,
   enum qed_led_mode mode);
+/**
+ * @brief db_recovery_add - add doorbell information to the doorbell
+ * recovery mechanism.
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address of where db_data is stored
+ * @param db_is_32b - doorbell is 32b pr 64b
+ * @param db_is_user - doorbell recovery addresses are user or kernel space
+ */
+   int (*db_recovery_add)(struct qed_dev *cdev,
+  void __iomem *db_addr,
+  void *db_data,
+  enum qed_db_rec_width db_width,
+  enum qed_db_rec_space db_space);
+
+/**
+ * @brief db_recovery_del - remove doorbell information from the doorbell
+ * recovery mechanism. db_data serves as key (db_addr is not unique).
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address where db_data is stored. Serves as key for the
+ * entry to delete.
+ */
+   int (*db_recovery_del)(struct qed_dev *cdev,
+  void __iomem *db_addr, void *db_data);
 
 /**
  * @brief update_drv_state - API to inform the change in the driver state.
-- 
1.8.3.1



[PATCH net-next v3 4/6] qed: Register light L2 queues with doorbell overflow recovery mechanism

2018-11-28 Thread Ariel Elior
Light L2 queues are doorbelling entities. Modify the implementation
to keep the doorbell data necessary for doorbelling in well known
location instead of recomputing every time. Register the LL2 queue
with doorbell recovery mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_ll2.c | 30 --
 drivers/net/ethernet/qlogic/qed/qed_ll2.h |  1 +
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index aa63338..504c8f7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1085,7 +1085,14 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn 
*p_hwfn,
 
p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
 
-   return qed_spq_post(p_hwfn, p_ent, NULL);
+   rc = qed_spq_post(p_hwfn, p_ent, NULL);
+   if (rc)
+   return rc;
+
+   rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr,
+_tx->db_msg, DB_REC_WIDTH_32B,
+DB_REC_KERNEL);
+   return rc;
 }
 
 static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn,
@@ -1119,9 +1126,11 @@ static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn 
*p_hwfn,
 static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
 {
+   struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
int rc = -EINVAL;
+   qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, _tx->db_msg);
 
/* Get SPQ entry */
memset(_data, 0, sizeof(init_data));
@@ -1542,6 +1551,13 @@ int qed_ll2_establish_connection(void *cxt, u8 
connection_handle)
p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells +
qed_db_addr(p_ll2_conn->cid,
DQ_DEMS_LEGACY);
+   /* prepare db data */
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_TX_BD_PROD_CMD);
+   p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
 
rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn);
if (rc)
@@ -1780,7 +1796,6 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw;
struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_ll2_tx_packet *p_pkt = NULL;
-   struct core_db_data db_msg = { 0, 0, 0 };
u16 bd_prod;
 
/* If there are missing BDs, don't do anything now */
@@ -1809,24 +1824,19 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
list_move_tail(_pkt->list_entry, _tx->active_descq);
}
 
-   SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_TX_BD_PROD_CMD);
-   db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db_msg.spq_prod = cpu_to_le16(bd_prod);
+   p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod);
 
/* Make sure the BDs data is updated before ringing the doorbell */
wmb();
 
-   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_msg));
+   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_tx->db_msg));
 
DP_VERBOSE(p_hwfn,
   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 
0x%04x]\n",
   p_ll2_conn->queue_id,
   p_ll2_conn->cid,
-  p_ll2_conn->input.conn_type, db_msg.spq_prod);
+  p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod);
 }
 
 int qed_ll2_prepare_tx_packet(void *cxt,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index 1a5c1ae..5f01fbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -103,6 +103,7 @@ struct qed_ll2_tx_queue {
struct qed_ll2_tx_packet cur_completing_packet;
u16 cur_completing_bd_idx;
void __iomem *doorbell_addr;
+   struct core_db_data db_msg;
u16 bds_idx;
u16 cur_send_frag_num;
u16 cur_completing_frag_num;
-- 
1.8.3.1



[PATCH net-next v3 3/6] qed: Register slowpath queue doorbell with doorbell overflow recovery mechanism

2018-11-28 Thread Ariel Elior
Slow path queue is a doorbelling entity. Register it with the overflow 
mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_sp.h  |  4 ++-
 drivers/net/ethernet/qlogic/qed/qed_spq.c | 47 +++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h 
b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index e95431f..17aa25f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -224,7 +224,9 @@ struct qed_spq {
u32 comp_count;
 
u32 cid;
-   qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
+   u32 db_addr_offset;
+   struct core_db_data db_data;
+   qed_spq_async_comp_cb   async_comp_cb[MAX_PROTOCOL_TYPE];
 };
 
 /**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c 
b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index c4a6274..29039bb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -254,9 +254,9 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
   struct qed_spq *p_spq, struct qed_spq_entry *p_ent)
 {
struct qed_chain *p_chain = _hwfn->p_spq->chain;
+   struct core_db_data *p_db_data = _spq->db_data;
u16 echo = qed_chain_get_prod_idx(p_chain);
struct slow_path_element*elem;
-   struct core_db_data db;
 
p_ent->elem.hdr.echo= cpu_to_le16(echo);
elem = qed_chain_produce(p_chain);
@@ -268,27 +268,22 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
*elem = p_ent->elem; /* struct assignment */
 
/* send a doorbell on the slow hwfn session */
-   memset(, 0, sizeof(db));
-   SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_SPQ_PROD_CMD);
-   db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+   p_db_data->spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
 
/* make sure the SPQE is updated before the doorbell */
wmb();
 
-   DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *));
+   DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *)p_db_data);
 
/* make sure doorbell is rang */
wmb();
 
DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
   "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x 
agg_params: %02x, prod: %04x\n",
-  qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
-  p_spq->cid, db.params, db.agg_flags,
-  qed_chain_get_prod_idx(p_chain));
+  p_spq->db_addr_offset,
+  p_spq->cid,
+  p_db_data->params,
+  p_db_data->agg_flags, qed_chain_get_prod_idx(p_chain));
 
return 0;
 }
@@ -492,8 +487,11 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwfn->p_spq;
struct qed_spq_entry *p_virt = NULL;
+   struct core_db_data *p_db_data;
+   void __iomem *db_addr;
dma_addr_t p_phys = 0;
u32 i, capacity;
+   int rc;
 
INIT_LIST_HEAD(_spq->pending);
INIT_LIST_HEAD(_spq->completion_pending);
@@ -530,6 +528,25 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 
/* reset the chain itself */
qed_chain_reset(_spq->chain);
+
+   /* Initialize the address/data of the SPQ doorbell */
+   p_spq->db_addr_offset = qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY);
+   p_db_data = _spq->db_data;
+   memset(p_db_data, 0, sizeof(*p_db_data));
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_SPQ_PROD_CMD);
+   p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+   /* Register the SPQ doorbell with the doorbell recovery mechanism */
+   db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+  p_spq->db_addr_offset);
+   rc = qed_db_recovery_add(p_hwfn->cdev, db_addr, _spq->db_data,
+DB_REC_WIDTH_32B, DB_REC_KERNEL);
+   if (rc)
+   DP_INFO(p_hwfn,
+   "Failed to register the SPQ doorbell with the doorbell 
recovery mechanism\n");
 }
 
 int qed_spq_alloc(struct qed_hwfn *p_hwfn)
@@ -577,11 +594,17 @@ int qed_spq_alloc(struct qed_hwfn *p_hwfn)
 void qed_spq_free(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwf

[PATCH net-next 0/6 v3] qed*: Doorbell overflow recovery

2018-11-28 Thread Ariel Elior
Doorbell Overflow
If sufficient CPU cores will send doorbells at a sufficiently high rate, they
can cause an overflow in the doorbell queue block message fifo. When fill level
reaches maximum, the device stops accepting all doorbells from that PF until a
recovery procedure has taken place.

Doorbell Overflow Recovery
The recovery procedure basically means resending the last doorbell for every
doorbelling entity. A doorbelling entity is anything which may send doorbells:
L2 tx ring, rdma sq/rq/cq, light l2, vf l2 tx ring, spq, etc. This relies on
the design assumption that all doorbells are aggregative, so last doorbell
carries the information of all previous doorbells.

APIs
All doorbelling entities need to register with the mechanism before sending
doorbells. The registration entails providing the doorbell address the entity
would be using, and a virtual address where last doorbell data can be found.
Typically fastpath structures already have this construct.

Executing the recovery procedure
Handling the attentions, iterating over all the registered entities and
resending their doorbells, is all handled within qed core module.

Relevance
All doorbelling entities in all protocols need to register with the mechanism,
via the new APIs. Technically this is quite simple (just call the API). Some
protocol fastpath implementation may not have the doorbell data stored anywhere
(compute it from scratch every time) and will have to add such a place.
This is rare and is also better practice (save some cycles on the fastpath).

Performance Penalty
No performance penalty should incur as a result of this feature. If anything
performance can improve by avoiding recalcualtion of doorbell data everytime
doorbell is sent (in some flows).

Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Please consider applying to net-next.
Thanks,
Ariel

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 

v1->v2:
---
Add support for ARCH=i386 (definition of writeq)

v2->v3:
---
Use generic writeq implementation in 
io-64-nonatomic-lo-hi.h instead of reimplementing.

Ariel Elior (6):
  qed: Add doorbell overflow recovery mechanism
  qed: Use the doorbell overflow recovery mechanism in case of doorbell
overflow
  qed: Register slowpath queue doorbell with doorbell overflow recovery
mechanism
  qed: Register light L2 queues with doorbell overflow recovery
mechanism
  qed: Expose the doorbell overflow recovery mechanism to the protocol
drivers
  qede: Register l2 queues with doorbell overflow recovery mechanism

 drivers/net/ethernet/qlogic/qed/qed.h  |  31 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 334 -
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h  |  28 +++
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 +--
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 +
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |  30 ++-
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |   1 +
 drivers/net/ethernet/qlogic/qed/qed_main.c |  66 -
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 drivers/net/ethernet/qlogic/qed/qed_sp.h   |   4 +-
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |  22 ++
 drivers/net/ethernet/qlogic/qede/qede_main.c   |   9 +
 include/linux/qed/qed_if.h |  42 
 13 files changed, 744 insertions(+), 35 deletions(-)

-- 
1.8.3.1



[PATCH net-next v3 1/6] qed: Add doorbell overflow recovery mechanism

2018-11-28 Thread Ariel Elior
Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h |  17 ++
 drivers/net/ethernet/qlogic/qed/qed_dev.c | 320 ++
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h |  28 +++
 include/linux/qed/qed_if.h|  14 ++
 4 files changed, 379 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 5f0962d..882279e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -296,6 +296,12 @@ enum qed_wol_support {
QED_WOL_SUPPORT_PME,
 };
 
+enum qed_db_rec_exec {
+   DB_REC_DRY_RUN,
+   DB_REC_REAL_DEAL,
+   DB_REC_ONCE,
+};
+
 struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
@@ -425,6 +431,14 @@ struct qed_qm_info {
u8 num_pf_rls;
 };
 
+struct qed_db_recovery_info {
+   struct list_head list;
+
+   /* Lock to protect the doorbell recovery mechanism list */
+   spinlock_t lock;
+   u32 db_recovery_counter;
+};
+
 struct storm_stats {
u32 address;
u32 len;
@@ -640,6 +654,9 @@ struct qed_hwfn {
/* L2-related */
struct qed_l2_info *p_l2_info;
 
+   /* Mechanism for recovering from doorbell drop */
+   struct qed_db_recovery_info db_recovery_info;
+
/* Nvm images number and attributes */
struct qed_nvm_image_info nvm_info;
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 7ceb2b9..a63f87f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -66,6 +66,318 @@
 
 static DEFINE_SPINLOCK(qm_lock);
 
+/ Doorbell Recovery ***/
+/* The doorbell recovery mechanism consists of a list of entries which 
represent
+ * doorbelling entities (l2 queues, roce sq/rq/cqs, the slowpath spq, etc). 
Each
+ * entity needs to register with the mechanism and provide the parameters
+ * describing it's doorbell, including a location where last used doorbell data
+ * can be found. The doorbell execute function will traverse the list and
+ * doorbell all of the registered entries.
+ */
+struct qed_db_recovery_entry {
+   struct list_head list_entry;
+   void __iomem *db_addr;
+   void *db_data;
+   enum qed_db_rec_width db_width;
+   enum qed_db_rec_space db_space;
+   u8 hwfn_idx;
+};
+
+/* Display a single doorbell recovery entry */
+static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
+struct qed_db_recovery_entry *db_entry,
+char *action)
+{
+   DP_VERBOSE(p_hwfn,
+  QED_MSG_SPQ,
+  "(%s: db_entry %p, addr %p, data %p, width %s, %s space, 
hwfn %d)\n",
+  action,
+  db_entry,
+  db_entry->db_addr,
+  db_entry->db_data,
+  db_entry->db_width == DB_REC_WIDTH_32B ? "32b" : "64b",
+  db_entry->db_space == DB_REC_USER ? "user" : "kernel",
+  db_entry->hwfn_idx);
+}
+
+/* Doorbell address sanity (address within doorbell bar range) */
+static bool qed_db_rec_sanity(struct qed_dev *cdev,
+ void __iomem *db_addr, void *db_data)
+{
+   /* Make sure doorbell address is within the doorbell bar */
+   if (db_addr < cdev->doorbells ||
+   (u8 __iomem *)db_addr >
+   (u8 __iomem *)cdev->doorbells + cdev->db_size) {
+   WARN(true,
+"Illegal doorbell address: %p. Legal range for doorbell 
addresses is [%p..%p]\n",
+db_addr,
+cdev->doorbells,
+(u8 __iomem *)cdev->doorbells + cdev->db_size);
+   return false;
+   }
+
+   /* ake sure doorbell data pointer is not null */
+   if (!db_data) {
+   WARN(true, "Illegal doorbell data pointer: %p", db_data);
+   return false;
+   }
+
+   return true;
+}
+
+/* Find hwfn according to the doorbell address */
+static struct qed_hwfn *qed_db_rec_find_hwfn(struct qed_dev *cdev,
+void __iomem *db_addr)
+{
+   struct qed_hwfn *p_hwfn;
+
+   /* In CMT doorbell bar is split down the middle between engine 0 and 
enigne 1 */
+   if (cdev->num_hwfns > 1)
+   p_hwfn = db_addr < cdev->hwfns[1].doorbells ?
+   >hwfns[0] : >hwfns[1];
+   else
+   p_hwfn = QED_LEADI

[PATCH net-next v3 2/6] qed: Use the doorbell overflow recovery mechanism in case of doorbell overflow

2018-11-28 Thread Ariel Elior
In case of an attention from the doorbell queue block, analyze the HW
indications. In case of a doorbell overflow, execute a doorbell recovery.
Since there can be spurious indications (race conditions between multiple PFs),
schedule a periodic task for checking whether a doorbell overflow may have been
missed. After a set time with no indications, terminate the periodic task.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 ++---
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 ++
 drivers/net/ethernet/qlogic/qed/qed_main.c |  64 ++-
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 6 files changed, 280 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 882279e..a053062 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -536,6 +536,7 @@ struct qed_simd_fp_handler {
 
 enum qed_slowpath_wq_flag {
QED_SLOWPATH_MFW_TLV_REQ,
+   QED_SLOWPATH_PERIODIC_DB_REC,
 };
 
 struct qed_hwfn {
@@ -669,11 +670,12 @@ struct qed_hwfn {
struct delayed_work iov_task;
unsigned long iov_task_flags;
 #endif
-
-   struct z_stream_s   *stream;
+   struct z_stream_s *stream;
+   bool slowpath_wq_active;
struct workqueue_struct *slowpath_wq;
struct delayed_work slowpath_task;
unsigned long slowpath_task_flags;
+   u32 periodic_db_rec_count;
 };
 
 struct pci_params {
@@ -914,6 +916,12 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
 
 #define QED_LEADING_HWFN(dev)   (>hwfns[0])
 
+/* doorbell recovery mechanism */
+void qed_db_recovery_dp(struct qed_hwfn *p_hwfn);
+void qed_db_recovery_execute(struct qed_hwfn *p_hwfn,
+enum qed_db_rec_exec db_exec);
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn);
+
 /* Other Linux specific common definitions */
 #define DP_NAME(cdev) ((cdev)->name)
 
@@ -948,4 +956,6 @@ int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn,
  union qed_mfw_tlv_data *tlv_data);
 
 void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc);
+
+void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn);
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index a63f87f..0172d90 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1759,6 +1759,14 @@ enum QED_ROCE_EDPM_MODE {
QED_ROCE_EDPM_MODE_DISABLE = 2,
 };
 
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn)
+{
+   if (p_hwfn->dcbx_no_edpm || p_hwfn->db_bar_no_edpm)
+   return false;
+
+   return true;
+}
+
 static int
 qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
@@ -1828,13 +1836,13 @@ enum QED_ROCE_EDPM_MODE {
p_hwfn->wid_count = (u16) n_cpus;
 
DP_INFO(p_hwfn,
-   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
+   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s, page_size=%lu\n",
norm_regsize,
pwm_regsize,
p_hwfn->dpi_size,
p_hwfn->dpi_count,
-   ((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
-   "disabled" : "enabled");
+   (!qed_edpm_enabled(p_hwfn)) ?
+   "disabled" : "enabled", PAGE_SIZE);
 
if (rc) {
DP_ERR(p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c 
b/drivers/net/ethernet/qlogic/qed/qed_int.c
index af3a28e..0fe44a6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -361,29 +361,147 @@ static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn)
return 0;
 }
 
-#define QED_DORQ_ATTENTION_REASON_MASK (0xf)
-#define QED_DORQ_ATTENTION_OPAQUE_MASK (0x)
-#define QED_DORQ_ATTENTION_SIZE_MASK   (0x7f)
-#define QED_DORQ_ATTENTION_SIZE_SHIFT  (16)
+#define QED_DORQ_ATTENTION_REASON_MASK  (0xf)
+#define QED_DORQ_ATTENTION_OPAQUE_MASK  (0x)
+#define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
+#define QED_DORQ_ATTENTION_SIZE_MASK(0x7f)
+#define QED_DORQ_ATTENTION_SIZE_SHIFT   (16)
+
+#define QED_DB_REC_COUNT1000
+#define QED_DB_REC_INTERVAL 100
+
+static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+   u32 count = QED_DB_REC_COUNT;
+   u32 usage = 1;
+
+   /* wait for usage to 

[PATCH net-next v3 5/6] qed: Expose the doorbell overflow recovery mechanism to the protocol drivers

2018-10-22 Thread Ariel Elior
Most of the doorbelling entities are outside of the core module.
L2 queues, Roce queues, iscsi and fcoe all need to register.
Make the APIs available for these drivers.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_main.c |  2 ++
 include/linux/qed/qed_if.h | 27 +++
 2 files changed, 29 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f2c50ef..a0b761d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -2238,6 +2238,8 @@ static int qed_read_module_eeprom(struct qed_dev *cdev, 
char *buf,
.update_mac = _update_mac,
.update_mtu = _update_mtu,
.update_wol = _update_wol,
+   .db_recovery_add = _db_recovery_add,
+   .db_recovery_del = _db_recovery_del,
.read_module_eeprom = _read_module_eeprom,
 };
 
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 41382e7..8b2b005 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -1009,6 +1009,33 @@ struct qed_common_ops {
  */
int (*set_led)(struct qed_dev *cdev,
   enum qed_led_mode mode);
+/**
+ * @brief db_recovery_add - add doorbell information to the doorbell
+ * recovery mechanism.
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address of where db_data is stored
+ * @param db_is_32b - doorbell is 32b pr 64b
+ * @param db_is_user - doorbell recovery addresses are user or kernel space
+ */
+   int (*db_recovery_add)(struct qed_dev *cdev,
+  void __iomem *db_addr,
+  void *db_data,
+  enum qed_db_rec_width db_width,
+  enum qed_db_rec_space db_space);
+
+/**
+ * @brief db_recovery_del - remove doorbell information from the doorbell
+ * recovery mechanism. db_data serves as key (db_addr is not unique).
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address where db_data is stored. Serves as key for the
+ * entry to delete.
+ */
+   int (*db_recovery_del)(struct qed_dev *cdev,
+  void __iomem *db_addr, void *db_data);
 
 /**
  * @brief update_drv_state - API to inform the change in the driver state.
-- 
1.8.3.1



[PATCH net-next v3 1/6] qed: Add doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h |  17 ++
 drivers/net/ethernet/qlogic/qed/qed_dev.c | 320 ++
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h |  28 +++
 include/linux/qed/qed_if.h|  14 ++
 4 files changed, 379 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 5f0962d..882279e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -296,6 +296,12 @@ enum qed_wol_support {
QED_WOL_SUPPORT_PME,
 };
 
+enum qed_db_rec_exec {
+   DB_REC_DRY_RUN,
+   DB_REC_REAL_DEAL,
+   DB_REC_ONCE,
+};
+
 struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
@@ -425,6 +431,14 @@ struct qed_qm_info {
u8 num_pf_rls;
 };
 
+struct qed_db_recovery_info {
+   struct list_head list;
+
+   /* Lock to protect the doorbell recovery mechanism list */
+   spinlock_t lock;
+   u32 db_recovery_counter;
+};
+
 struct storm_stats {
u32 address;
u32 len;
@@ -640,6 +654,9 @@ struct qed_hwfn {
/* L2-related */
struct qed_l2_info *p_l2_info;
 
+   /* Mechanism for recovering from doorbell drop */
+   struct qed_db_recovery_info db_recovery_info;
+
/* Nvm images number and attributes */
struct qed_nvm_image_info nvm_info;
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 7ceb2b9..a63f87f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -66,6 +66,318 @@
 
 static DEFINE_SPINLOCK(qm_lock);
 
+/ Doorbell Recovery ***/
+/* The doorbell recovery mechanism consists of a list of entries which 
represent
+ * doorbelling entities (l2 queues, roce sq/rq/cqs, the slowpath spq, etc). 
Each
+ * entity needs to register with the mechanism and provide the parameters
+ * describing it's doorbell, including a location where last used doorbell data
+ * can be found. The doorbell execute function will traverse the list and
+ * doorbell all of the registered entries.
+ */
+struct qed_db_recovery_entry {
+   struct list_head list_entry;
+   void __iomem *db_addr;
+   void *db_data;
+   enum qed_db_rec_width db_width;
+   enum qed_db_rec_space db_space;
+   u8 hwfn_idx;
+};
+
+/* Display a single doorbell recovery entry */
+static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
+struct qed_db_recovery_entry *db_entry,
+char *action)
+{
+   DP_VERBOSE(p_hwfn,
+  QED_MSG_SPQ,
+  "(%s: db_entry %p, addr %p, data %p, width %s, %s space, 
hwfn %d)\n",
+  action,
+  db_entry,
+  db_entry->db_addr,
+  db_entry->db_data,
+  db_entry->db_width == DB_REC_WIDTH_32B ? "32b" : "64b",
+  db_entry->db_space == DB_REC_USER ? "user" : "kernel",
+  db_entry->hwfn_idx);
+}
+
+/* Doorbell address sanity (address within doorbell bar range) */
+static bool qed_db_rec_sanity(struct qed_dev *cdev,
+ void __iomem *db_addr, void *db_data)
+{
+   /* Make sure doorbell address is within the doorbell bar */
+   if (db_addr < cdev->doorbells ||
+   (u8 __iomem *)db_addr >
+   (u8 __iomem *)cdev->doorbells + cdev->db_size) {
+   WARN(true,
+"Illegal doorbell address: %p. Legal range for doorbell 
addresses is [%p..%p]\n",
+db_addr,
+cdev->doorbells,
+(u8 __iomem *)cdev->doorbells + cdev->db_size);
+   return false;
+   }
+
+   /* ake sure doorbell data pointer is not null */
+   if (!db_data) {
+   WARN(true, "Illegal doorbell data pointer: %p", db_data);
+   return false;
+   }
+
+   return true;
+}
+
+/* Find hwfn according to the doorbell address */
+static struct qed_hwfn *qed_db_rec_find_hwfn(struct qed_dev *cdev,
+void __iomem *db_addr)
+{
+   struct qed_hwfn *p_hwfn;
+
+   /* In CMT doorbell bar is split down the middle between engine 0 and 
enigne 1 */
+   if (cdev->num_hwfns > 1)
+   p_hwfn = db_addr < cdev->hwfns[1].doorbells ?
+   >hwfns[0] : >hwfns[1];
+   else
+   p_hwfn = QED_LEADI

[PATCH net-next v3 6/6] qede: Register l2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
All L2 queues funnel through this flow, so this would cover the
regular RSS queues, as well queues created for VFs, mqos queues,
xdp queues, etc.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c 
b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 46d0f2e..1c4cea8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1774,6 +1774,10 @@ static int qede_drain_txq(struct qede_dev *edev,
 static int qede_stop_txq(struct qede_dev *edev,
 struct qede_tx_queue *txq, int rss_id)
 {
+   /* delete doorbell from doorbell recovery mechanism */
+   edev->ops->common->db_recovery_del(edev->cdev, txq->doorbell_addr,
+  >tx_db);
+
return edev->ops->q_tx_stop(edev->cdev, rss_id, txq->handle);
 }
 
@@ -1910,6 +1914,11 @@ static int qede_start_txq(struct qede_dev *edev,
  DQ_XCM_ETH_TX_BD_PROD_CMD);
txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
 
+   /* register doorbell with doorbell recovery mechanism */
+   rc = edev->ops->common->db_recovery_add(edev->cdev, txq->doorbell_addr,
+   >tx_db, DB_REC_WIDTH_32B,
+   DB_REC_KERNEL);
+
return rc;
 }
 
-- 
1.8.3.1



[PATCH net-next v3 3/6] qed: Register slowpath queue doorbell with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Slow path queue is a doorbelling entity. Register it with the overflow 
mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_sp.h  |  4 ++-
 drivers/net/ethernet/qlogic/qed/qed_spq.c | 47 +++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h 
b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index e95431f..17aa25f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -224,7 +224,9 @@ struct qed_spq {
u32 comp_count;
 
u32 cid;
-   qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
+   u32 db_addr_offset;
+   struct core_db_data db_data;
+   qed_spq_async_comp_cb   async_comp_cb[MAX_PROTOCOL_TYPE];
 };
 
 /**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c 
b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index c4a6274..29039bb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -254,9 +254,9 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
   struct qed_spq *p_spq, struct qed_spq_entry *p_ent)
 {
struct qed_chain *p_chain = _hwfn->p_spq->chain;
+   struct core_db_data *p_db_data = _spq->db_data;
u16 echo = qed_chain_get_prod_idx(p_chain);
struct slow_path_element*elem;
-   struct core_db_data db;
 
p_ent->elem.hdr.echo= cpu_to_le16(echo);
elem = qed_chain_produce(p_chain);
@@ -268,27 +268,22 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
*elem = p_ent->elem; /* struct assignment */
 
/* send a doorbell on the slow hwfn session */
-   memset(, 0, sizeof(db));
-   SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_SPQ_PROD_CMD);
-   db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+   p_db_data->spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
 
/* make sure the SPQE is updated before the doorbell */
wmb();
 
-   DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *));
+   DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *)p_db_data);
 
/* make sure doorbell is rang */
wmb();
 
DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
   "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x 
agg_params: %02x, prod: %04x\n",
-  qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
-  p_spq->cid, db.params, db.agg_flags,
-  qed_chain_get_prod_idx(p_chain));
+  p_spq->db_addr_offset,
+  p_spq->cid,
+  p_db_data->params,
+  p_db_data->agg_flags, qed_chain_get_prod_idx(p_chain));
 
return 0;
 }
@@ -492,8 +487,11 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwfn->p_spq;
struct qed_spq_entry *p_virt = NULL;
+   struct core_db_data *p_db_data;
+   void __iomem *db_addr;
dma_addr_t p_phys = 0;
u32 i, capacity;
+   int rc;
 
INIT_LIST_HEAD(_spq->pending);
INIT_LIST_HEAD(_spq->completion_pending);
@@ -530,6 +528,25 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 
/* reset the chain itself */
qed_chain_reset(_spq->chain);
+
+   /* Initialize the address/data of the SPQ doorbell */
+   p_spq->db_addr_offset = qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY);
+   p_db_data = _spq->db_data;
+   memset(p_db_data, 0, sizeof(*p_db_data));
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_SPQ_PROD_CMD);
+   p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+   /* Register the SPQ doorbell with the doorbell recovery mechanism */
+   db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+  p_spq->db_addr_offset);
+   rc = qed_db_recovery_add(p_hwfn->cdev, db_addr, _spq->db_data,
+DB_REC_WIDTH_32B, DB_REC_KERNEL);
+   if (rc)
+   DP_INFO(p_hwfn,
+   "Failed to register the SPQ doorbell with the doorbell 
recovery mechanism\n");
 }
 
 int qed_spq_alloc(struct qed_hwfn *p_hwfn)
@@ -577,11 +594,17 @@ int qed_spq_alloc(struct qed_hwfn *p_hwfn)
 void qed_spq_free(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwf

[PATCH net-next v3 4/6] qed: Register light L2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Light L2 queues are doorbelling entities. Modify the implementation
to keep the doorbell data necessary for doorbelling in well known
location instead of recomputing every time. Register the LL2 queue
with doorbell recovery mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_ll2.c | 30 --
 drivers/net/ethernet/qlogic/qed/qed_ll2.h |  1 +
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index aa63338..504c8f7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1085,7 +1085,14 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn 
*p_hwfn,
 
p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
 
-   return qed_spq_post(p_hwfn, p_ent, NULL);
+   rc = qed_spq_post(p_hwfn, p_ent, NULL);
+   if (rc)
+   return rc;
+
+   rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr,
+_tx->db_msg, DB_REC_WIDTH_32B,
+DB_REC_KERNEL);
+   return rc;
 }
 
 static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn,
@@ -1119,9 +1126,11 @@ static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn 
*p_hwfn,
 static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
 {
+   struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
int rc = -EINVAL;
+   qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, _tx->db_msg);
 
/* Get SPQ entry */
memset(_data, 0, sizeof(init_data));
@@ -1542,6 +1551,13 @@ int qed_ll2_establish_connection(void *cxt, u8 
connection_handle)
p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells +
qed_db_addr(p_ll2_conn->cid,
DQ_DEMS_LEGACY);
+   /* prepare db data */
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_TX_BD_PROD_CMD);
+   p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
 
rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn);
if (rc)
@@ -1780,7 +1796,6 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw;
struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_ll2_tx_packet *p_pkt = NULL;
-   struct core_db_data db_msg = { 0, 0, 0 };
u16 bd_prod;
 
/* If there are missing BDs, don't do anything now */
@@ -1809,24 +1824,19 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
list_move_tail(_pkt->list_entry, _tx->active_descq);
}
 
-   SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_TX_BD_PROD_CMD);
-   db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db_msg.spq_prod = cpu_to_le16(bd_prod);
+   p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod);
 
/* Make sure the BDs data is updated before ringing the doorbell */
wmb();
 
-   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_msg));
+   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_tx->db_msg));
 
DP_VERBOSE(p_hwfn,
   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 
0x%04x]\n",
   p_ll2_conn->queue_id,
   p_ll2_conn->cid,
-  p_ll2_conn->input.conn_type, db_msg.spq_prod);
+  p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod);
 }
 
 int qed_ll2_prepare_tx_packet(void *cxt,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index 1a5c1ae..5f01fbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -103,6 +103,7 @@ struct qed_ll2_tx_queue {
struct qed_ll2_tx_packet cur_completing_packet;
u16 cur_completing_bd_idx;
void __iomem *doorbell_addr;
+   struct core_db_data db_msg;
u16 bds_idx;
u16 cur_send_frag_num;
u16 cur_completing_frag_num;
-- 
1.8.3.1



[PATCH net-next v3 2/6] qed: Use the doorbell overflow recovery mechanism in case of doorbell overflow

2018-10-22 Thread Ariel Elior
In case of an attention from the doorbell queue block, analyze the HW
indications. In case of a doorbell overflow, execute a doorbell recovery.
Since there can be spurious indications (race conditions between multiple PFs),
schedule a periodic task for checking whether a doorbell overflow may have been
missed. After a set time with no indications, terminate the periodic task.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 ++---
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 ++
 drivers/net/ethernet/qlogic/qed/qed_main.c |  64 ++-
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 6 files changed, 280 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 882279e..a053062 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -536,6 +536,7 @@ struct qed_simd_fp_handler {
 
 enum qed_slowpath_wq_flag {
QED_SLOWPATH_MFW_TLV_REQ,
+   QED_SLOWPATH_PERIODIC_DB_REC,
 };
 
 struct qed_hwfn {
@@ -669,11 +670,12 @@ struct qed_hwfn {
struct delayed_work iov_task;
unsigned long iov_task_flags;
 #endif
-
-   struct z_stream_s   *stream;
+   struct z_stream_s *stream;
+   bool slowpath_wq_active;
struct workqueue_struct *slowpath_wq;
struct delayed_work slowpath_task;
unsigned long slowpath_task_flags;
+   u32 periodic_db_rec_count;
 };
 
 struct pci_params {
@@ -914,6 +916,12 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
 
 #define QED_LEADING_HWFN(dev)   (>hwfns[0])
 
+/* doorbell recovery mechanism */
+void qed_db_recovery_dp(struct qed_hwfn *p_hwfn);
+void qed_db_recovery_execute(struct qed_hwfn *p_hwfn,
+enum qed_db_rec_exec db_exec);
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn);
+
 /* Other Linux specific common definitions */
 #define DP_NAME(cdev) ((cdev)->name)
 
@@ -948,4 +956,6 @@ int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn,
  union qed_mfw_tlv_data *tlv_data);
 
 void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc);
+
+void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn);
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index a63f87f..0172d90 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1759,6 +1759,14 @@ enum QED_ROCE_EDPM_MODE {
QED_ROCE_EDPM_MODE_DISABLE = 2,
 };
 
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn)
+{
+   if (p_hwfn->dcbx_no_edpm || p_hwfn->db_bar_no_edpm)
+   return false;
+
+   return true;
+}
+
 static int
 qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
@@ -1828,13 +1836,13 @@ enum QED_ROCE_EDPM_MODE {
p_hwfn->wid_count = (u16) n_cpus;
 
DP_INFO(p_hwfn,
-   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
+   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s, page_size=%lu\n",
norm_regsize,
pwm_regsize,
p_hwfn->dpi_size,
p_hwfn->dpi_count,
-   ((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
-   "disabled" : "enabled");
+   (!qed_edpm_enabled(p_hwfn)) ?
+   "disabled" : "enabled", PAGE_SIZE);
 
if (rc) {
DP_ERR(p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c 
b/drivers/net/ethernet/qlogic/qed/qed_int.c
index af3a28e..0fe44a6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -361,29 +361,147 @@ static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn)
return 0;
 }
 
-#define QED_DORQ_ATTENTION_REASON_MASK (0xf)
-#define QED_DORQ_ATTENTION_OPAQUE_MASK (0x)
-#define QED_DORQ_ATTENTION_SIZE_MASK   (0x7f)
-#define QED_DORQ_ATTENTION_SIZE_SHIFT  (16)
+#define QED_DORQ_ATTENTION_REASON_MASK  (0xf)
+#define QED_DORQ_ATTENTION_OPAQUE_MASK  (0x)
+#define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
+#define QED_DORQ_ATTENTION_SIZE_MASK(0x7f)
+#define QED_DORQ_ATTENTION_SIZE_SHIFT   (16)
+
+#define QED_DB_REC_COUNT1000
+#define QED_DB_REC_INTERVAL 100
+
+static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+   u32 count = QED_DB_REC_COUNT;
+   u32 usage = 1;
+
+   /* wait for usage to 

[PATCH net-next 0/6 v2] qed*: Doorbell overflow recovery

2018-10-22 Thread Ariel Elior
Doorbell Overflow
If sufficient CPU cores will send doorbells at a sufficiently high rate, they
can cause an overflow in the doorbell queue block message fifo. When fill level
reaches maximum, the device stops accepting all doorbells from that PF until a
recovery procedure has taken place.

Doorbell Overflow Recovery
The recovery procedure basically means resending the last doorbell for every
doorbelling entity. A doorbelling entity is anything which may send doorbells:
L2 tx ring, rdma sq/rq/cq, light l2, vf l2 tx ring, spq, etc. This relies on
the design assumption that all doorbells are aggregative, so last doorbell
carries the information of all previous doorbells.

APIs
All doorbelling entities need to register with the mechanism before sending
doorbells. The registration entails providing the doorbell address the entity
would be using, and a virtual address where last doorbell data can be found.
Typically fastpath structures already have this construct.

Executing the recovery procedure
Handling the attentions, iterating over all the registered entities and
resending their doorbells, is all handled within qed core module.

Relevance
All doorbelling entities in all protocols need to register with the mechanism,
via the new APIs. Technically this is quite simple (just call the API). Some
protocol fastpath implementation may not have the doorbell data stored anywhere
(compute it from scratch every time) and will have to add such a place.
This is rare and is also better practice (save some cycles on the fastpath).

Performance Penalty
No performance penalty should incur as a result of this feature. If anything
performance can improve by avoiding recalcualtion of doorbell data everytime
doorbell is sent (in some flows).

Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Please consider applying to net-next.
Thanks,
Ariel

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 

v1->v2:
---
Add support for ARCH=i386 (definition of writeq)

v2->v3:
---
Use generic writeq implementation in 
io-64-nonatomic-lo-hi.h instead of reimplementing.

Ariel Elior (6):
  qed: Add doorbell overflow recovery mechanism
  qed: Use the doorbell overflow recovery mechanism in case of doorbell
overflow
  qed: Register slowpath queue doorbell with doorbell overflow recovery
mechanism
  qed: Register light L2 queues with doorbell overflow recovery
mechanism
  qed: Expose the doorbell overflow recovery mechanism to the protocol
drivers
  qede: Register l2 queues with doorbell overflow recovery mechanism

 drivers/net/ethernet/qlogic/qed/qed.h  |  31 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 334 -
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h  |  28 +++
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 +--
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 +
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |  30 ++-
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |   1 +
 drivers/net/ethernet/qlogic/qed/qed_main.c |  66 -
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 drivers/net/ethernet/qlogic/qed/qed_sp.h   |   4 +-
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |  22 ++
 drivers/net/ethernet/qlogic/qede/qede_main.c   |   9 +
 include/linux/qed/qed_if.h |  42 
 13 files changed, 744 insertions(+), 35 deletions(-)

-- 
1.8.3.1



[PATCH net-next 0/6 v2] qed*: Doorbell overflow recovery

2018-10-22 Thread Ariel Elior
Doorbell Overflow
If sufficient CPU cores will send doorbells at a sufficiently high rate, they
can cause an overflow in the doorbell queue block message fifo. When fill level
reaches maximum, the device stops accepting all doorbells from that PF until a
recovery procedure has taken place.

Doorbell Overflow Recovery
The recovery procedure basically means resending the last doorbell for every
doorbelling entity. A doorbelling entity is anything which may send doorbells:
L2 tx ring, rdma sq/rq/cq, light l2, vf l2 tx ring, spq, etc. This relies on
the design assumption that all doorbells are aggregative, so last doorbell
carries the information of all previous doorbells.

APIs
All doorbelling entities need to register with the mechanism before sending
doorbells. The registration entails providing the doorbell address the entity
would be using, and a virtual address where last doorbell data can be found.
Typically fastpath structures already have this construct.

Executing the recovery procedure
Handling the attentions, iterating over all the registered entities and
resending their doorbells, is all handled within qed core module.

Relevance
All doorbelling entities in all protocols need to register with the mechanism,
via the new APIs. Technically this is quite simple (just call the API). Some
protocol fastpath implementation may not have the doorbell data stored anywhere
(compute it from scratch every time) and will have to add such a place.
This is rare and is also better practice (save some cycles on the fastpath).

Performance Penalty
No performance penalty should incur as a result of this feature. If anything
performance can improve by avoiding recalcualtion of doorbell data everytime
doorbell is sent (in some flows).

Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Please consider applying to net-next.
Thanks,
Ariel

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 

v1->v2:
---
Add support for ARCH=i386 (definition of writeq)

Ariel Elior (6):
  qed: Add doorbell overflow recovery mechanism
  qed: Use the doorbell overflow recovery mechanism in case of doorbell
overflow
  qed: Register slowpath queue doorbell with doorbell overflow recovery
mechanism
  qed: Register light L2 queues with doorbell overflow recovery
mechanism
  qed: Expose the doorbell overflow recovery mechanism to the protocol
drivers
  qede: Register l2 queues with doorbell overflow recovery mechanism

 drivers/net/ethernet/qlogic/qed/qed.h  |  31 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 334 -
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h  |  28 +++
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 +--
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 +
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |  30 ++-
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |   1 +
 drivers/net/ethernet/qlogic/qed/qed_main.c |  66 -
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 drivers/net/ethernet/qlogic/qed/qed_sp.h   |   4 +-
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |  22 ++
 drivers/net/ethernet/qlogic/qede/qede_main.c   |   9 +
 include/linux/qed/qed_if.h |  42 
 13 files changed, 744 insertions(+), 35 deletions(-)

-- 
1.8.3.1



[PATCH net-next v2 5/6] qed: Expose the doorbell overflow recovery mechanism to the protocol drivers

2018-10-22 Thread Ariel Elior
Most of the doorbelling entities are outside of the core module.
L2 queues, Roce queues, iscsi and fcoe all need to register.
Make the APIs available for these drivers.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_main.c |  2 ++
 include/linux/qed/qed_if.h | 27 +++
 2 files changed, 29 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f2c50ef..a0b761d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -2238,6 +2238,8 @@ static int qed_read_module_eeprom(struct qed_dev *cdev, 
char *buf,
.update_mac = _update_mac,
.update_mtu = _update_mtu,
.update_wol = _update_wol,
+   .db_recovery_add = _db_recovery_add,
+   .db_recovery_del = _db_recovery_del,
.read_module_eeprom = _read_module_eeprom,
 };
 
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index afb2e4c..cb0f344 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -1017,6 +1017,33 @@ struct qed_common_ops {
  */
int (*set_led)(struct qed_dev *cdev,
   enum qed_led_mode mode);
+/**
+ * @brief db_recovery_add - add doorbell information to the doorbell
+ * recovery mechanism.
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address of where db_data is stored
+ * @param db_is_32b - doorbell is 32b pr 64b
+ * @param db_is_user - doorbell recovery addresses are user or kernel space
+ */
+   int (*db_recovery_add)(struct qed_dev *cdev,
+  void __iomem *db_addr,
+  void *db_data,
+  enum qed_db_rec_width db_width,
+  enum qed_db_rec_space db_space);
+
+/**
+ * @brief db_recovery_del - remove doorbell information from the doorbell
+ * recovery mechanism. db_data serves as key (db_addr is not unique).
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address where db_data is stored. Serves as key for the
+ * entry to delete.
+ */
+   int (*db_recovery_del)(struct qed_dev *cdev,
+  void __iomem *db_addr, void *db_data);
 
 /**
  * @brief update_drv_state - API to inform the change in the driver state.
-- 
1.8.3.1



[PATCH net-next v2 3/6] qed: Register slowpath queue doorbell with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Slow path queue is a doorbelling entity. Register it with the overflow 
mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_sp.h  |  4 ++-
 drivers/net/ethernet/qlogic/qed/qed_spq.c | 47 +++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h 
b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index e95431f..17aa25f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -224,7 +224,9 @@ struct qed_spq {
u32 comp_count;
 
u32 cid;
-   qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
+   u32 db_addr_offset;
+   struct core_db_data db_data;
+   qed_spq_async_comp_cb   async_comp_cb[MAX_PROTOCOL_TYPE];
 };
 
 /**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c 
b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index c4a6274..29039bb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -254,9 +254,9 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
   struct qed_spq *p_spq, struct qed_spq_entry *p_ent)
 {
struct qed_chain *p_chain = _hwfn->p_spq->chain;
+   struct core_db_data *p_db_data = _spq->db_data;
u16 echo = qed_chain_get_prod_idx(p_chain);
struct slow_path_element*elem;
-   struct core_db_data db;
 
p_ent->elem.hdr.echo= cpu_to_le16(echo);
elem = qed_chain_produce(p_chain);
@@ -268,27 +268,22 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
*elem = p_ent->elem; /* struct assignment */
 
/* send a doorbell on the slow hwfn session */
-   memset(, 0, sizeof(db));
-   SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_SPQ_PROD_CMD);
-   db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+   p_db_data->spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
 
/* make sure the SPQE is updated before the doorbell */
wmb();
 
-   DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *));
+   DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *) p_db_data);
 
/* make sure doorbell is rang */
wmb();
 
DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
   "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x 
agg_params: %02x, prod: %04x\n",
-  qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
-  p_spq->cid, db.params, db.agg_flags,
-  qed_chain_get_prod_idx(p_chain));
+  p_spq->db_addr_offset,
+  p_spq->cid,
+  p_db_data->params,
+  p_db_data->agg_flags, qed_chain_get_prod_idx(p_chain));
 
return 0;
 }
@@ -492,8 +487,11 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwfn->p_spq;
struct qed_spq_entry *p_virt = NULL;
+   struct core_db_data *p_db_data;
+   void __iomem *db_addr;
dma_addr_t p_phys = 0;
u32 i, capacity;
+   int rc;
 
INIT_LIST_HEAD(_spq->pending);
INIT_LIST_HEAD(_spq->completion_pending);
@@ -530,6 +528,25 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 
/* reset the chain itself */
qed_chain_reset(_spq->chain);
+
+   /* Initialize the address/data of the SPQ doorbell */
+   p_spq->db_addr_offset = qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY);
+   p_db_data = _spq->db_data;
+   memset(p_db_data, 0, sizeof(*p_db_data));
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_SPQ_PROD_CMD);
+   p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+   /* Register the SPQ doorbell with the doorbell recovery mechanism */
+   db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+  p_spq->db_addr_offset);
+   rc = qed_db_recovery_add(p_hwfn->cdev, db_addr, _spq->db_data,
+DB_REC_WIDTH_32B, DB_REC_KERNEL);
+   if (rc)
+   DP_INFO(p_hwfn,
+   "Failed to register the SPQ doorbell with the doorbell 
recovery mechanism\n");
 }
 
 int qed_spq_alloc(struct qed_hwfn *p_hwfn)
@@ -577,11 +594,17 @@ int qed_spq_alloc(struct qed_hwfn *p_hwfn)
 void qed_spq_free(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwf

[PATCH net-next v2 4/6] qed: Register light L2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Light L2 queues are doorbelling entities. Modify the implementation
to keep the doorbell data necessary for doorbelling in well known
location instead of recomputing every time. Register the LL2 queue
with doorbell recovery mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_ll2.c | 30 --
 drivers/net/ethernet/qlogic/qed/qed_ll2.h |  1 +
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index aa63338..504c8f7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1085,7 +1085,14 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn 
*p_hwfn,
 
p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
 
-   return qed_spq_post(p_hwfn, p_ent, NULL);
+   rc = qed_spq_post(p_hwfn, p_ent, NULL);
+   if (rc)
+   return rc;
+
+   rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr,
+_tx->db_msg, DB_REC_WIDTH_32B,
+DB_REC_KERNEL);
+   return rc;
 }
 
 static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn,
@@ -1119,9 +1126,11 @@ static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn 
*p_hwfn,
 static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
 {
+   struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
int rc = -EINVAL;
+   qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, _tx->db_msg);
 
/* Get SPQ entry */
memset(_data, 0, sizeof(init_data));
@@ -1542,6 +1551,13 @@ int qed_ll2_establish_connection(void *cxt, u8 
connection_handle)
p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells +
qed_db_addr(p_ll2_conn->cid,
DQ_DEMS_LEGACY);
+   /* prepare db data */
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_TX_BD_PROD_CMD);
+   p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
 
rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn);
if (rc)
@@ -1780,7 +1796,6 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw;
struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_ll2_tx_packet *p_pkt = NULL;
-   struct core_db_data db_msg = { 0, 0, 0 };
u16 bd_prod;
 
/* If there are missing BDs, don't do anything now */
@@ -1809,24 +1824,19 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
list_move_tail(_pkt->list_entry, _tx->active_descq);
}
 
-   SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_TX_BD_PROD_CMD);
-   db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db_msg.spq_prod = cpu_to_le16(bd_prod);
+   p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod);
 
/* Make sure the BDs data is updated before ringing the doorbell */
wmb();
 
-   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_msg));
+   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_tx->db_msg));
 
DP_VERBOSE(p_hwfn,
   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 
0x%04x]\n",
   p_ll2_conn->queue_id,
   p_ll2_conn->cid,
-  p_ll2_conn->input.conn_type, db_msg.spq_prod);
+  p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod);
 }
 
 int qed_ll2_prepare_tx_packet(void *cxt,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index 1a5c1ae..5f01fbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -103,6 +103,7 @@ struct qed_ll2_tx_queue {
struct qed_ll2_tx_packet cur_completing_packet;
u16 cur_completing_bd_idx;
void __iomem *doorbell_addr;
+   struct core_db_data db_msg;
u16 bds_idx;
u16 cur_send_frag_num;
u16 cur_completing_frag_num;
-- 
1.8.3.1



[PATCH net-next v2 1/6] qed: Add doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h |  17 ++
 drivers/net/ethernet/qlogic/qed/qed_dev.c | 320 ++
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h |  28 +++
 include/linux/qed/qed_if.h|  22 ++
 4 files changed, 387 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 5f0962d..882279e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -296,6 +296,12 @@ enum qed_wol_support {
QED_WOL_SUPPORT_PME,
 };
 
+enum qed_db_rec_exec {
+   DB_REC_DRY_RUN,
+   DB_REC_REAL_DEAL,
+   DB_REC_ONCE,
+};
+
 struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
@@ -425,6 +431,14 @@ struct qed_qm_info {
u8 num_pf_rls;
 };
 
+struct qed_db_recovery_info {
+   struct list_head list;
+
+   /* Lock to protect the doorbell recovery mechanism list */
+   spinlock_t lock;
+   u32 db_recovery_counter;
+};
+
 struct storm_stats {
u32 address;
u32 len;
@@ -640,6 +654,9 @@ struct qed_hwfn {
/* L2-related */
struct qed_l2_info *p_l2_info;
 
+   /* Mechanism for recovering from doorbell drop */
+   struct qed_db_recovery_info db_recovery_info;
+
/* Nvm images number and attributes */
struct qed_nvm_image_info nvm_info;
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 7ceb2b9..a63f87f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -66,6 +66,318 @@
 
 static DEFINE_SPINLOCK(qm_lock);
 
+/ Doorbell Recovery ***/
+/* The doorbell recovery mechanism consists of a list of entries which 
represent
+ * doorbelling entities (l2 queues, roce sq/rq/cqs, the slowpath spq, etc). 
Each
+ * entity needs to register with the mechanism and provide the parameters
+ * describing it's doorbell, including a location where last used doorbell data
+ * can be found. The doorbell execute function will traverse the list and
+ * doorbell all of the registered entries.
+ */
+struct qed_db_recovery_entry {
+   struct list_head list_entry;
+   void __iomem *db_addr;
+   void *db_data;
+   enum qed_db_rec_width db_width;
+   enum qed_db_rec_space db_space;
+   u8 hwfn_idx;
+};
+
+/* Display a single doorbell recovery entry */
+static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
+struct qed_db_recovery_entry *db_entry,
+char *action)
+{
+   DP_VERBOSE(p_hwfn,
+  QED_MSG_SPQ,
+  "(%s: db_entry %p, addr %p, data %p, width %s, %s space, 
hwfn %d)\n",
+  action,
+  db_entry,
+  db_entry->db_addr,
+  db_entry->db_data,
+  db_entry->db_width == DB_REC_WIDTH_32B ? "32b" : "64b",
+  db_entry->db_space == DB_REC_USER ? "user" : "kernel",
+  db_entry->hwfn_idx);
+}
+
+/* Doorbell address sanity (address within doorbell bar range) */
+static bool qed_db_rec_sanity(struct qed_dev *cdev,
+ void __iomem *db_addr, void *db_data)
+{
+   /* Make sure doorbell address is within the doorbell bar */
+   if (db_addr < cdev->doorbells ||
+   (u8 __iomem *)db_addr >
+   (u8 __iomem *)cdev->doorbells + cdev->db_size) {
+   WARN(true,
+"Illegal doorbell address: %p. Legal range for doorbell 
addresses is [%p..%p]\n",
+db_addr,
+cdev->doorbells,
+(u8 __iomem *)cdev->doorbells + cdev->db_size);
+   return false;
+   }
+
+   /* ake sure doorbell data pointer is not null */
+   if (!db_data) {
+   WARN(true, "Illegal doorbell data pointer: %p", db_data);
+   return false;
+   }
+
+   return true;
+}
+
+/* Find hwfn according to the doorbell address */
+static struct qed_hwfn *qed_db_rec_find_hwfn(struct qed_dev *cdev,
+void __iomem *db_addr)
+{
+   struct qed_hwfn *p_hwfn;
+
+   /* In CMT doorbell bar is split down the middle between engine 0 and 
enigne 1 */
+   if (cdev->num_hwfns > 1)
+   p_hwfn = db_addr < cdev->hwfns[1].doorbells ?
+   >hwfns[0] : >hwfns[1];
+   else
+   p_hwfn = QED_LEADI

[PATCH net-next v2 2/6] qed: Use the doorbell overflow recovery mechanism in case of doorbell overflow

2018-10-22 Thread Ariel Elior
In case of an attention from the doorbell queue block, analyze the HW
indications. In case of a doorbell overflow, execute a doorbell recovery.
Since there can be spurious indications (race conditions between multiple PFs),
schedule a periodic task for checking whether a doorbell overflow may have been
missed. After a set time with no indications, terminate the periodic task.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 ++---
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 ++
 drivers/net/ethernet/qlogic/qed/qed_main.c |  64 ++-
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 6 files changed, 280 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 882279e..a053062 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -536,6 +536,7 @@ struct qed_simd_fp_handler {
 
 enum qed_slowpath_wq_flag {
QED_SLOWPATH_MFW_TLV_REQ,
+   QED_SLOWPATH_PERIODIC_DB_REC,
 };
 
 struct qed_hwfn {
@@ -669,11 +670,12 @@ struct qed_hwfn {
struct delayed_work iov_task;
unsigned long iov_task_flags;
 #endif
-
-   struct z_stream_s   *stream;
+   struct z_stream_s *stream;
+   bool slowpath_wq_active;
struct workqueue_struct *slowpath_wq;
struct delayed_work slowpath_task;
unsigned long slowpath_task_flags;
+   u32 periodic_db_rec_count;
 };
 
 struct pci_params {
@@ -914,6 +916,12 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
 
 #define QED_LEADING_HWFN(dev)   (>hwfns[0])
 
+/* doorbell recovery mechanism */
+void qed_db_recovery_dp(struct qed_hwfn *p_hwfn);
+void qed_db_recovery_execute(struct qed_hwfn *p_hwfn,
+enum qed_db_rec_exec db_exec);
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn);
+
 /* Other Linux specific common definitions */
 #define DP_NAME(cdev) ((cdev)->name)
 
@@ -948,4 +956,6 @@ int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn,
  union qed_mfw_tlv_data *tlv_data);
 
 void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc);
+
+void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn);
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index a63f87f..0172d90 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1759,6 +1759,14 @@ enum QED_ROCE_EDPM_MODE {
QED_ROCE_EDPM_MODE_DISABLE = 2,
 };
 
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn)
+{
+   if (p_hwfn->dcbx_no_edpm || p_hwfn->db_bar_no_edpm)
+   return false;
+
+   return true;
+}
+
 static int
 qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
@@ -1828,13 +1836,13 @@ enum QED_ROCE_EDPM_MODE {
p_hwfn->wid_count = (u16) n_cpus;
 
DP_INFO(p_hwfn,
-   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
+   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s, page_size=%lu\n",
norm_regsize,
pwm_regsize,
p_hwfn->dpi_size,
p_hwfn->dpi_count,
-   ((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
-   "disabled" : "enabled");
+   (!qed_edpm_enabled(p_hwfn)) ?
+   "disabled" : "enabled", PAGE_SIZE);
 
if (rc) {
DP_ERR(p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c 
b/drivers/net/ethernet/qlogic/qed/qed_int.c
index af3a28e..0fe44a6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -361,29 +361,147 @@ static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn)
return 0;
 }
 
-#define QED_DORQ_ATTENTION_REASON_MASK (0xf)
-#define QED_DORQ_ATTENTION_OPAQUE_MASK (0x)
-#define QED_DORQ_ATTENTION_SIZE_MASK   (0x7f)
-#define QED_DORQ_ATTENTION_SIZE_SHIFT  (16)
+#define QED_DORQ_ATTENTION_REASON_MASK  (0xf)
+#define QED_DORQ_ATTENTION_OPAQUE_MASK  (0x)
+#define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
+#define QED_DORQ_ATTENTION_SIZE_MASK(0x7f)
+#define QED_DORQ_ATTENTION_SIZE_SHIFT   (16)
+
+#define QED_DB_REC_COUNT1000
+#define QED_DB_REC_INTERVAL 100
+
+static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+   u32 count = QED_DB_REC_COUNT;
+   u32 usage = 1;
+
+   /* wait for usage to 

[PATCH net-next v2 6/6] qede: Register l2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
All L2 queues funnel through this flow, so this would cover the
regular RSS queues, as well queues created for VFs, mqos queues,
xdp queues, etc.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c 
b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 46d0f2e..1c4cea8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1774,6 +1774,10 @@ static int qede_drain_txq(struct qede_dev *edev,
 static int qede_stop_txq(struct qede_dev *edev,
 struct qede_tx_queue *txq, int rss_id)
 {
+   /* delete doorbell from doorbell recovery mechanism */
+   edev->ops->common->db_recovery_del(edev->cdev, txq->doorbell_addr,
+  >tx_db);
+
return edev->ops->q_tx_stop(edev->cdev, rss_id, txq->handle);
 }
 
@@ -1910,6 +1914,11 @@ static int qede_start_txq(struct qede_dev *edev,
  DQ_XCM_ETH_TX_BD_PROD_CMD);
txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
 
+   /* register doorbell with doorbell recovery mechanism */
+   rc = edev->ops->common->db_recovery_add(edev->cdev, txq->doorbell_addr,
+   >tx_db, DB_REC_WIDTH_32B,
+   DB_REC_KERNEL);
+
return rc;
 }
 
-- 
1.8.3.1



[PATCH net-next 3/6] qed: Register slowpath queue doorbell with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Slow path queue is a doorbelling entity. Register it with the overflow 
mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_sp.h  |  4 ++-
 drivers/net/ethernet/qlogic/qed/qed_spq.c | 47 +++
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h 
b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index e95431f..17aa25f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -224,7 +224,9 @@ struct qed_spq {
u32 comp_count;
 
u32 cid;
-   qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
+   u32 db_addr_offset;
+   struct core_db_data db_data;
+   qed_spq_async_comp_cb   async_comp_cb[MAX_PROTOCOL_TYPE];
 };
 
 /**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c 
b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index c4a6274..29039bb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -254,9 +254,9 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
   struct qed_spq *p_spq, struct qed_spq_entry *p_ent)
 {
struct qed_chain *p_chain = _hwfn->p_spq->chain;
+   struct core_db_data *p_db_data = _spq->db_data;
u16 echo = qed_chain_get_prod_idx(p_chain);
struct slow_path_element*elem;
-   struct core_db_data db;
 
p_ent->elem.hdr.echo= cpu_to_le16(echo);
elem = qed_chain_produce(p_chain);
@@ -268,27 +268,22 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
*elem = p_ent->elem; /* struct assignment */
 
/* send a doorbell on the slow hwfn session */
-   memset(, 0, sizeof(db));
-   SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_SPQ_PROD_CMD);
-   db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+   p_db_data->spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
 
/* make sure the SPQE is updated before the doorbell */
wmb();
 
-   DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *));
+   DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *) p_db_data);
 
/* make sure doorbell is rang */
wmb();
 
DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
   "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x 
agg_params: %02x, prod: %04x\n",
-  qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
-  p_spq->cid, db.params, db.agg_flags,
-  qed_chain_get_prod_idx(p_chain));
+  p_spq->db_addr_offset,
+  p_spq->cid,
+  p_db_data->params,
+  p_db_data->agg_flags, qed_chain_get_prod_idx(p_chain));
 
return 0;
 }
@@ -492,8 +487,11 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwfn->p_spq;
struct qed_spq_entry *p_virt = NULL;
+   struct core_db_data *p_db_data;
+   void __iomem *db_addr;
dma_addr_t p_phys = 0;
u32 i, capacity;
+   int rc;
 
INIT_LIST_HEAD(_spq->pending);
INIT_LIST_HEAD(_spq->completion_pending);
@@ -530,6 +528,25 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 
/* reset the chain itself */
qed_chain_reset(_spq->chain);
+
+   /* Initialize the address/data of the SPQ doorbell */
+   p_spq->db_addr_offset = qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY);
+   p_db_data = _spq->db_data;
+   memset(p_db_data, 0, sizeof(*p_db_data));
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
+   SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_SPQ_PROD_CMD);
+   p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+   /* Register the SPQ doorbell with the doorbell recovery mechanism */
+   db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+  p_spq->db_addr_offset);
+   rc = qed_db_recovery_add(p_hwfn->cdev, db_addr, _spq->db_data,
+DB_REC_WIDTH_32B, DB_REC_KERNEL);
+   if (rc)
+   DP_INFO(p_hwfn,
+   "Failed to register the SPQ doorbell with the doorbell 
recovery mechanism\n");
 }
 
 int qed_spq_alloc(struct qed_hwfn *p_hwfn)
@@ -577,11 +594,17 @@ int qed_spq_alloc(struct qed_hwfn *p_hwfn)
 void qed_spq_free(struct qed_hwfn *p_hwfn)
 {
struct qed_spq *p_spq = p_hwf

[PATCH net-next 4/6] qed: Register light L2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Light L2 queues are doorbelling entities. Modify the implementation
to keep the doorbell data necessary for doorbelling in well known
location instead of recomputing every time. Register the LL2 queue
with doorbell recovery mechanism.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_ll2.c | 30 --
 drivers/net/ethernet/qlogic/qed/qed_ll2.h |  1 +
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index aa63338..504c8f7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1085,7 +1085,14 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn 
*p_hwfn,
 
p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
 
-   return qed_spq_post(p_hwfn, p_ent, NULL);
+   rc = qed_spq_post(p_hwfn, p_ent, NULL);
+   if (rc)
+   return rc;
+
+   rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr,
+_tx->db_msg, DB_REC_WIDTH_32B,
+DB_REC_KERNEL);
+   return rc;
 }
 
 static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn,
@@ -1119,9 +1126,11 @@ static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn 
*p_hwfn,
 static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,
struct qed_ll2_info *p_ll2_conn)
 {
+   struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
int rc = -EINVAL;
+   qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, _tx->db_msg);
 
/* Get SPQ entry */
memset(_data, 0, sizeof(init_data));
@@ -1542,6 +1551,13 @@ int qed_ll2_establish_connection(void *cxt, u8 
connection_handle)
p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells +
qed_db_addr(p_ll2_conn->cid,
DQ_DEMS_LEGACY);
+   /* prepare db data */
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
+   SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_CORE_TX_BD_PROD_CMD);
+   p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
 
rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn);
if (rc)
@@ -1780,7 +1796,6 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw;
struct qed_ll2_tx_queue *p_tx = _ll2_conn->tx_queue;
struct qed_ll2_tx_packet *p_pkt = NULL;
-   struct core_db_data db_msg = { 0, 0, 0 };
u16 bd_prod;
 
/* If there are missing BDs, don't do anything now */
@@ -1809,24 +1824,19 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn 
*p_hwfn,
list_move_tail(_pkt->list_entry, _tx->active_descq);
}
 
-   SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-   SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,
- DQ_XCM_CORE_TX_BD_PROD_CMD);
-   db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-   db_msg.spq_prod = cpu_to_le16(bd_prod);
+   p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod);
 
/* Make sure the BDs data is updated before ringing the doorbell */
wmb();
 
-   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_msg));
+   DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)_tx->db_msg));
 
DP_VERBOSE(p_hwfn,
   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 
0x%04x]\n",
   p_ll2_conn->queue_id,
   p_ll2_conn->cid,
-  p_ll2_conn->input.conn_type, db_msg.spq_prod);
+  p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod);
 }
 
 int qed_ll2_prepare_tx_packet(void *cxt,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
index 1a5c1ae..5f01fbd 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -103,6 +103,7 @@ struct qed_ll2_tx_queue {
struct qed_ll2_tx_packet cur_completing_packet;
u16 cur_completing_bd_idx;
void __iomem *doorbell_addr;
+   struct core_db_data db_msg;
u16 bds_idx;
u16 cur_send_frag_num;
u16 cur_completing_frag_num;
-- 
1.8.3.1



[PATCH net-next 0/6] qed*: Doorbell overflow recovery

2018-10-22 Thread Ariel Elior
Doorbell Overflow
If sufficient CPU cores will send doorbells at a sufficiently high rate, they
can cause an overflow in the doorbell queue block message fifo. When fill level
reaches maximum, the device stops accepting all doorbells from that PF until a
recovery procedure has taken place.

Doorbell Overflow Recovery
The recovery procedure basically means resending the last doorbell for every
doorbelling entity. A doorbelling entity is anything which may send doorbells:
L2 tx ring, rdma sq/rq/cq, light l2, vf l2 tx ring, spq, etc. This relies on
the design assumption that all doorbells are aggregative, so last doorbell
carries the information of all previous doorbells.

APIs
All doorbelling entities need to register with the mechanism before sending
doorbells. The registration entails providing the doorbell address the entity
would be using, and a virtual address where last doorbell data can be found.
Typically fastpath structures already have this construct.

Executing the recovery procedure
Handling the attentions, iterating over all the registered entities and
resending their doorbells, is all handled within qed core module.

Relevance
All doorbelling entities in all protocols need to register with the mechanism,
via the new APIs. Technically this is quite simple (just call the API). Some
protocol fastpath implementation may not have the doorbell data stored anywhere
(compute it from scratch every time) and will have to add such a place.
This is rare and is also better practice (save some cycles on the fastpath).

Performance Penalty
No performance penalty should incur as a result of this feature. If anything
performance can improve by avoiding recalcualtion of doorbell data everytime
doorbell is sent (in some flows).

Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Please consider applying to net-next.
Thanks,
Ariel

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 

Ariel Elior (6):
  qed: Add doorbell overflow recovery mechanism
  qed: Use the doorbell overflow recovery mechanism in case of doorbell
overflow
  qed: Register slowpath queue doorbell with doorbell overflow recovery
mechanism
  qed: Register light L2 queues with doorbell overflow recovery
mechanism
  qed: Expose the doorbell overflow recovery mechanism to the protocol
drivers
  qede: Register l2 queues with doorbell overflow recovery mechanism

 drivers/net/ethernet/qlogic/qed/qed.h  |  31 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  | 334 -
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h  |  28 +++
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 +--
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 +
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |  30 ++-
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |   1 +
 drivers/net/ethernet/qlogic/qed/qed_main.c |  66 -
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 drivers/net/ethernet/qlogic/qed/qed_sp.h   |   4 +-
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |  22 ++
 drivers/net/ethernet/qlogic/qede/qede_main.c   |   9 +
 include/linux/qed/qed_if.h |  42 
 13 files changed, 744 insertions(+), 35 deletions(-)

-- 
1.8.3.1



[PATCH net-next 6/6] qede: Register l2 queues with doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
All L2 queues funnel through this flow, so this would cover the
regular RSS queues, as well queues created for VFs, mqos queues,
xdp queues, etc.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qede/qede_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c 
b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 46d0f2e..1c4cea8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1774,6 +1774,10 @@ static int qede_drain_txq(struct qede_dev *edev,
 static int qede_stop_txq(struct qede_dev *edev,
 struct qede_tx_queue *txq, int rss_id)
 {
+   /* delete doorbell from doorbell recovery mechanism */
+   edev->ops->common->db_recovery_del(edev->cdev, txq->doorbell_addr,
+  >tx_db);
+
return edev->ops->q_tx_stop(edev->cdev, rss_id, txq->handle);
 }
 
@@ -1910,6 +1914,11 @@ static int qede_start_txq(struct qede_dev *edev,
  DQ_XCM_ETH_TX_BD_PROD_CMD);
txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
 
+   /* register doorbell with doorbell recovery mechanism */
+   rc = edev->ops->common->db_recovery_add(edev->cdev, txq->doorbell_addr,
+   >tx_db, DB_REC_WIDTH_32B,
+   DB_REC_KERNEL);
+
return rc;
 }
 
-- 
1.8.3.1



[PATCH net-next 2/6] qed: Use the doorbell overflow recovery mechanism in case of doorbell overflow

2018-10-22 Thread Ariel Elior
In case of an attention from the doorbell queue block, analyze the HW
indications. In case of a doorbell overflow, execute a doorbell recovery.
Since there can be spurious indications (race conditions between multiple PFs),
schedule a periodic task for checking whether a doorbell overflow may have been
missed. After a set time with no indications, terminate the periodic task.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |  14 ++-
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 152 ++---
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  10 ++
 drivers/net/ethernet/qlogic/qed/qed_main.c |  64 ++-
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |  50 
 6 files changed, 280 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 882279e..a053062 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -536,6 +536,7 @@ struct qed_simd_fp_handler {
 
 enum qed_slowpath_wq_flag {
QED_SLOWPATH_MFW_TLV_REQ,
+   QED_SLOWPATH_PERIODIC_DB_REC,
 };
 
 struct qed_hwfn {
@@ -669,11 +670,12 @@ struct qed_hwfn {
struct delayed_work iov_task;
unsigned long iov_task_flags;
 #endif
-
-   struct z_stream_s   *stream;
+   struct z_stream_s *stream;
+   bool slowpath_wq_active;
struct workqueue_struct *slowpath_wq;
struct delayed_work slowpath_task;
unsigned long slowpath_task_flags;
+   u32 periodic_db_rec_count;
 };
 
 struct pci_params {
@@ -914,6 +916,12 @@ void qed_set_fw_mac_addr(__le16 *fw_msb,
 
 #define QED_LEADING_HWFN(dev)   (>hwfns[0])
 
+/* doorbell recovery mechanism */
+void qed_db_recovery_dp(struct qed_hwfn *p_hwfn);
+void qed_db_recovery_execute(struct qed_hwfn *p_hwfn,
+enum qed_db_rec_exec db_exec);
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn);
+
 /* Other Linux specific common definitions */
 #define DP_NAME(cdev) ((cdev)->name)
 
@@ -948,4 +956,6 @@ int qed_mfw_fill_tlv_data(struct qed_hwfn *hwfn,
  union qed_mfw_tlv_data *tlv_data);
 
 void qed_hw_info_set_offload_tc(struct qed_hw_info *p_info, u8 tc);
+
+void qed_periodic_db_rec_start(struct qed_hwfn *p_hwfn);
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 9cdc267..aae5114 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1759,6 +1759,14 @@ enum QED_ROCE_EDPM_MODE {
QED_ROCE_EDPM_MODE_DISABLE = 2,
 };
 
+bool qed_edpm_enabled(struct qed_hwfn *p_hwfn)
+{
+   if (p_hwfn->dcbx_no_edpm || p_hwfn->db_bar_no_edpm)
+   return false;
+
+   return true;
+}
+
 static int
 qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
@@ -1828,13 +1836,13 @@ enum QED_ROCE_EDPM_MODE {
p_hwfn->wid_count = (u16) n_cpus;
 
DP_INFO(p_hwfn,
-   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s\n",
+   "doorbell bar: normal_region_size=%d, pwm_region_size=%d, 
dpi_size=%d, dpi_count=%d, roce_edpm=%s, page_size=%lu\n",
norm_regsize,
pwm_regsize,
p_hwfn->dpi_size,
p_hwfn->dpi_count,
-   ((p_hwfn->dcbx_no_edpm) || (p_hwfn->db_bar_no_edpm)) ?
-   "disabled" : "enabled");
+   (!qed_edpm_enabled(p_hwfn)) ?
+   "disabled" : "enabled", PAGE_SIZE);
 
if (rc) {
DP_ERR(p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c 
b/drivers/net/ethernet/qlogic/qed/qed_int.c
index af3a28e..0fe44a6 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -361,29 +361,147 @@ static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn)
return 0;
 }
 
-#define QED_DORQ_ATTENTION_REASON_MASK (0xf)
-#define QED_DORQ_ATTENTION_OPAQUE_MASK (0x)
-#define QED_DORQ_ATTENTION_SIZE_MASK   (0x7f)
-#define QED_DORQ_ATTENTION_SIZE_SHIFT  (16)
+#define QED_DORQ_ATTENTION_REASON_MASK  (0xf)
+#define QED_DORQ_ATTENTION_OPAQUE_MASK  (0x)
+#define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
+#define QED_DORQ_ATTENTION_SIZE_MASK(0x7f)
+#define QED_DORQ_ATTENTION_SIZE_SHIFT   (16)
+
+#define QED_DB_REC_COUNT1000
+#define QED_DB_REC_INTERVAL 100
+
+static int qed_db_rec_flush_queue(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt)
+{
+   u32 count = QED_DB_REC_COUNT;
+   u32 usage = 1;
+
+   /* Wait for usage to 

[PATCH net-next 1/6] qed: Add doorbell overflow recovery mechanism

2018-10-22 Thread Ariel Elior
Add the database used to register doorbelling entities, and APIs for adding
and deleting entries, and logic for traversing the database and doorbelling
once on behalf of all entities.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed.h |  17 ++
 drivers/net/ethernet/qlogic/qed/qed_dev.c | 320 ++
 drivers/net/ethernet/qlogic/qed/qed_dev_api.h |  28 +++
 include/linux/qed/qed_if.h|  15 ++
 4 files changed, 380 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 5f0962d..882279e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -296,6 +296,12 @@ enum qed_wol_support {
QED_WOL_SUPPORT_PME,
 };
 
+enum qed_db_rec_exec {
+   DB_REC_DRY_RUN,
+   DB_REC_REAL_DEAL,
+   DB_REC_ONCE,
+};
+
 struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
@@ -425,6 +431,14 @@ struct qed_qm_info {
u8 num_pf_rls;
 };
 
+struct qed_db_recovery_info {
+   struct list_head list;
+
+   /* Lock to protect the doorbell recovery mechanism list */
+   spinlock_t lock;
+   u32 db_recovery_counter;
+};
+
 struct storm_stats {
u32 address;
u32 len;
@@ -640,6 +654,9 @@ struct qed_hwfn {
/* L2-related */
struct qed_l2_info *p_l2_info;
 
+   /* Mechanism for recovering from doorbell drop */
+   struct qed_db_recovery_info db_recovery_info;
+
/* Nvm images number and attributes */
struct qed_nvm_image_info nvm_info;
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 7ceb2b9..9cdc267 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -66,6 +66,318 @@
 
 static DEFINE_SPINLOCK(qm_lock);
 
+/ Doorbell Recovery ***/
+/* The doorbell recovery mechanism consists of a list of entries which 
represent
+ * doorbelling entities (l2 queues, roce sq/rq/cqs, the slowpath spq, etc). 
Each
+ * entity needs to register with the mechanism and provide the parameters
+ * describing it's doorbell, including a location where last used doorbell data
+ * can be found. The doorbell execute function will traverse the list and
+ * doorbell all of the registered entries.
+ */
+struct qed_db_recovery_entry {
+   struct list_head list_entry;
+   void __iomem *db_addr;
+   void *db_data;
+   enum qed_db_rec_width db_width;
+   enum qed_db_rec_space db_space;
+   u8 hwfn_idx;
+};
+
+/* Display a single doorbell recovery entry */
+static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
+struct qed_db_recovery_entry *db_entry,
+char *action)
+{
+   DP_VERBOSE(p_hwfn,
+  QED_MSG_SPQ,
+  "(%s: db_entry %p, addr %p, data %p, width %s, %s space, 
hwfn %d)\n",
+  action,
+  db_entry,
+  db_entry->db_addr,
+  db_entry->db_data,
+  db_entry->db_width == DB_REC_WIDTH_32B ? "32b" : "64b",
+  db_entry->db_space == DB_REC_USER ? "user" : "kernel",
+  db_entry->hwfn_idx);
+}
+
+/* Doorbell address sanity (address within doorbell bar range) */
+static bool qed_db_rec_sanity(struct qed_dev *cdev,
+ void __iomem *db_addr, void *db_data)
+{
+   /* Make sure doorbell address is within the doorbell bar */
+   if (db_addr < cdev->doorbells ||
+   (u8 __iomem *)db_addr >
+   (u8 __iomem *)cdev->doorbells + cdev->db_size) {
+   WARN(true,
+"Illegal doorbell address: %p. Legal range for doorbell 
addresses is [%p..%p]\n",
+db_addr,
+cdev->doorbells,
+(u8 __iomem *)cdev->doorbells + cdev->db_size);
+   return false;
+   }
+
+   /* ake sure doorbell data pointer is not null */
+   if (!db_data) {
+   WARN(true, "Illegal doorbell data pointer: %p", db_data);
+   return false;
+   }
+
+   return true;
+}
+
+/* Find hwfn according to the doorbell address */
+static struct qed_hwfn *qed_db_rec_find_hwfn(struct qed_dev *cdev,
+void __iomem *db_addr)
+{
+   struct qed_hwfn *p_hwfn;
+
+   /* In CMT doorbell bar is split down the middle between engine 0 and 
enigne 1 */
+   if (cdev->num_hwfns > 1)
+   p_hwfn = db_addr < cdev->hwfns[1].doorbells ?
+   >hwfns[0] : >hwfns[1];
+   else
+   p_hwfn = QED_LEADI

[PATCH net-next 5/6] qed: Expose the doorbell overflow recovery mechanism to the protocol drivers

2018-10-22 Thread Ariel Elior
Most of the doorbelling entities are outside of the core module.
L2 queues, Roce queues, iscsi and fcoe all need to register.
Make the APIs available for these drivers.

Signed-off-by: Ariel Elior 
Signed-off-by: Michal Kalderon 
Signed-off-by: Tomer Tayar 
---
 drivers/net/ethernet/qlogic/qed/qed_main.c |  2 ++
 include/linux/qed/qed_if.h | 27 +++
 2 files changed, 29 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f2c50ef..a0b761d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -2238,6 +2238,8 @@ static int qed_read_module_eeprom(struct qed_dev *cdev, 
char *buf,
.update_mac = _update_mac,
.update_mtu = _update_mtu,
.update_wol = _update_wol,
+   .db_recovery_add = _db_recovery_add,
+   .db_recovery_del = _db_recovery_del,
.read_module_eeprom = _read_module_eeprom,
 };
 
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index c3f9844..416d525 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -1010,6 +1010,33 @@ struct qed_common_ops {
  */
int (*set_led)(struct qed_dev *cdev,
   enum qed_led_mode mode);
+/**
+ * @brief db_recovery_add - add doorbell information to the doorbell
+ * recovery mechanism.
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address of where db_data is stored
+ * @param db_is_32b - doorbell is 32b pr 64b
+ * @param db_is_user - doorbell recovery addresses are user or kernel space
+ */
+   int (*db_recovery_add)(struct qed_dev *cdev,
+  void __iomem *db_addr,
+  void *db_data,
+  enum qed_db_rec_width db_width,
+  enum qed_db_rec_space db_space);
+
+/**
+ * @brief db_recovery_del - remove doorbell information from the doorbell
+ * recovery mechanism. db_data serves as key (db_addr is not unique).
+ *
+ * @param cdev
+ * @param db_addr - doorbell address
+ * @param db_data - address where db_data is stored. Serves as key for the
+ * entry to delete.
+ */
+   int (*db_recovery_del)(struct qed_dev *cdev,
+  void __iomem *db_addr, void *db_data);
 
 /**
  * @brief update_drv_state - API to inform the change in the driver state.
-- 
1.8.3.1



RE: [PATCH 2/2] bnx2x:Fix error handling for functions in bnx2x_link.c

2016-03-07 Thread Ariel Elior
> -Original Message-
> From: Nicholas Krause [mailto:xerofo...@gmail.com]
> Sent: Monday, March 07, 2016 4:12 AM
> To: Ariel Elior <ariel.el...@qlogic.com>
> Cc: netdev <netdev@vger.kernel.org>; linux-kernel 
> <linux-ker...@vger.kernel.org>
> Subject: [PATCH 2/2] bnx2x:Fix error handling for functions in bnx2x_link.c
> 
> This fixes various functions that call the function
> bnx2x_84833_get_reset_gpios to properly check if this
> function has returned a error code and if so return
> immediately with the error code to signal these function's
> 
> Signed-off-by: Nicholas Krause <xerofo...@gmail.com>
> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 23 ---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
> b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
> index a0b03c2..b0646d9 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
> @@ -10079,6 +10079,7 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy
> *phy,
>  {
>   struct bnx2x *bp = params->bp;
>   u8 reset_gpios;
> + int rc;
>   u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
>   offsetof(struct shmem2_region,
>   other_shmem_base_addr));
> @@ -10099,7 +10100,12 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy
> *phy,
>   reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
> params->chip_id);
> 
> - bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_LOW);
> + rc = bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_LOW);
> + if (rc) {
> + DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n failed 
> ",
> +reset_gpios);
> + return rc;
> + }
>   udelay(10);
>   DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
>   reset_gpios);
> @@ -13242,10 +13248,21 @@ static int bnx2x_84833_common_init_phy(struct
> bnx2x *bp,
>   u32 chip_id)
>  {
>   u8 reset_gpios;
> + int ret;
>   reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
> - bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_LOW);
> + ret = bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_LOW);
> + if (ret) {
> + DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
> +reset_gpios);
> + return ret;
> + }
>   udelay(10);
> - bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_HIGH);
> + ret = bnx2x_set_mult_gpio(bp, reset_gpios,
> MISC_REGISTERS_GPIO_OUTPUT_HIGH);
> + if (ret) {
> + DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
> +reset_gpios);
> + return ret;
> + }
>   DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
>   reset_gpios);
>   return 0;
> --
> 2.1.4
Thanks Nicholas.
Acked-by: Ariel Elior <ariel.el...@qlogic.com>


RE: [PATCH 1/2] bnx2x:Fix error handling for the function bnx2x_set_mutl_gpio

2016-03-07 Thread Ariel Elior
> -Original Message-
> From: Nicholas Krause [mailto:xerofo...@gmail.com]
> Sent: Monday, March 07, 2016 4:05 AM
> To: Ariel Elior <ariel.el...@qlogic.com>
> Cc: netdev <netdev@vger.kernel.org>; linux-kernel 
> <linux-ker...@vger.kernel.org>
> Subject: [PATCH 1/2] bnx2x:Fix error handling for the function 
> bnx2x_set_mutl_gpio
> 
> This fixes the error handling for the function bnx2x_set_mutl_gpio
> for checking if the function bnx2x_acquire_hw_lock ran successfully
> by not returning a error code and if it does return the error code
> to this function's caller in addition to exiting from this function
> immediately due to this failure.
> 
> Signed-off-by: Nicholas Krause <xerofo...@gmail.com>
> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> index c27af12..a55f1c2 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> @@ -2151,7 +2151,9 @@ int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32
> mode)
> 
>   /* Any port swapping should be handled by caller. */
> 
> - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
> + rc = bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
> + if (rc)
> + return rc;
>   /* read GPIO and mask except the float bits */
>   gpio_reg = REG_RD(bp, MISC_REG_GPIO);
>   gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
> --
> 2.1.4
Thanks Nicholas.
Acked-by: Ariel Elior <ariel.el...@qlogic.com>


RE: [PATCH net 0/7] bnx2x: endianness fixes

2016-03-02 Thread Ariel Elior
> -Original Message-
> From: Michal Schmidt [mailto:mschm...@redhat.com]
> Sent: Wednesday, March 02, 2016 2:47 PM
> To: netdev <netdev@vger.kernel.org>
> Cc: Yuval Mintz <yuval.mi...@qlogic.com>; Ariel Elior <ariel.el...@qlogic.com>
> Subject: [PATCH net 0/7] bnx2x: endianness fixes
> 
> Hello,
> this fixes a VLAN crash and some SRIOV bugs in bnx2x observed on ppc64.
> 
> Michal Schmidt (7):
>   bnx2x: fix crash on big-endian when adding VLAN
>   bnx2x: fix sending VF->PF messages on big-endian
>   bnx2x: fix receive of VF->PF mailbox messages by the PF on big-endian
>   bnx2x: access cfc_del_event only if the opcode is CFC_DEL
>   bnx2x: define fields of struct cfc_del_event_data as little-endian
>   bnx2x: define event data reserved fields as little-endian
>   bnx2x: fix indentation in bnx2x_sp_task()
> 
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h   | 36 
> ++-
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  | 22 +++---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 12 
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c  |  4 +--
>  4 files changed, 32 insertions(+), 42 deletions(-)
> 
> --
> 2.5.0
Hi Michal,
Thanks for making these changes!
Acked-By: Ariel Elior <ariel.el...@qlogic.com>


RE: bnx2x commits needed to use 7.51.10 firmware?

2016-02-03 Thread Ariel Elior
+Yuval

> -Original Message-
> From: Dan Streetman [mailto:dan.street...@canonical.com]
> Sent: Wednesday, February 03, 2016 2:20 AM
> To: Ariel Elior <ariel.el...@qlogic.com>
> Cc: netdev <netdev@vger.kernel.org>
> Subject: bnx2x commits needed to use 7.51.10 firmware?
> 
> Hi Ariel,
> 
> I'm trying to update the bnx2x driver in Ubuntu trusty (3.13 kernel)
> release to use the 7.51.10 firmware; can you help me determine which
> commits need to be backported?
> 
> Some reference is in Launchpad bug 1454286:
> https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1454286
> 
> basically, there are 87 commits between the current bnx2x driver level
> in Ubuntu trusty's kernel, and commit e42780b where the bnx2x driver
> is acutally updated to use the 7.51.10 firmware.  Can you provide
> guidance to which commits should be pulled back?  Do all 87 of them
> need to be included?
> 
> Thanks!


RE: [PATCH] bnx2x:Fix error handling and return statement in the function bnx2x_vf_init

2015-11-19 Thread Ariel Elior
> -Original Message-
> From: Nicholas Krause [mailto:xerofo...@gmail.com]
> Sent: Thursday, November 19, 2015 5:31 AM
> To: Ariel Elior <ariel.el...@qlogic.com>
> Cc: netdev <netdev@vger.kernel.org>; linux-kernel 
> <linux-ker...@vger.kernel.org>
> Subject: [PATCH] bnx2x:Fix error handling and return statement in the function
> bnx2x_vf_init
> 
> This fixes error handling and the return statement in the function
> bnx2x_vf_init to properly check and return the error code returned
> by the call to the function bnx2x_post_vf_bulletin in order to
> allow callers of bnx2x_vf_init to be properly signaled and be able to
> handle in their own intended error paths if a error code is returned
> by this particular function call.
> 
> Signed-off-by: Nicholas Krause <xerofo...@gmail.com>
> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
> b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
> index 9d02734..4434cdb 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
> @@ -2087,6 +2087,7 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf 
> *vf,
> dma_addr_t *sb_map)
>  {
>   struct bnx2x_func_init_params func_init = {0};
>   int i;
> + int rc;
> 
>   /* the sb resources are initialized at this point, do the
>* FW/HW initializations
> @@ -2129,9 +2130,9 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf 
> *vf,
> dma_addr_t *sb_map)
>   vf->state = VF_ENABLED;
> 
>   /* update vf bulletin board */
> - bnx2x_post_vf_bulletin(bp, vf->index);
> +     rc = bnx2x_post_vf_bulletin(bp, vf->index);
> 
> - return 0;
> + return rc;
>  }
> 
>  struct set_vf_state_cookie {
> --
> 2.5.0

Acked-by: Ariel Elior <ariel.el...@qlogic.com>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [BUG] bnx2x_config_vlan_mac called a NULL function pointer

2015-10-23 Thread Ariel Elior
Looking into it...

> -Original Message-
> From: Otto Sabart [mailto:osab...@redhat.com]
> Sent: Thursday, October 22, 2015 10:45 PM
> To: netdev <netdev@vger.kernel.org>
> Cc: Ariel Elior <ariel.el...@qlogic.com>; Adam Okuliar <aokul...@redhat.com>; 
> Jirka
> Hladky <jhla...@redhat.com>
> Subject: [BUG] bnx2x_config_vlan_mac called a NULL function pointer
> 
> Hello netdev,
> I probably found a bug in kernel-4.3.0-0.rc5 (bnx2x driver). So I opened
> new bug report in our bugzilla [0]. Michal Schmidt told me the best way
> to solve an upstream bug is to contact you directly to netdev list.. so
> here I am :).
> 
> Can somebody take a look at it?
> 
> [0] https://bugzilla.redhat.com/show_bug.cgi?id=1273894
> 
> 
> thanks,
> 
> Ota

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [RFC v2 net-next 00/10] Add new drivers: qed & qede

2015-09-24 Thread Ariel Elior
> -Original Message-
> From: Yuval Mintz [mailto:yuval.mi...@qlogic.com]
> Sent: Thursday, September 17, 2015 5:24 PM
> To: netdev <netdev@vger.kernel.org>
> Cc: Ariel Elior <ariel.el...@qlogic.com>; Yuval Mintz <yuval.mi...@qlogic.com>
> Subject: [RFC v2 net-next 00/10] Add new drivers: qed & qede
> 
> From: Ariel Elior <ariel.el...@qlogic.com>
> 
> This series implements the driver set for Qlogic's new 579xx series.
> These are 10/20/25/40/50/100 Gig capable converged nics, supporting
> ethernet (obviously), iscsi, fcoe, roce and iwarp protocols.
> 
> The overall driver design includes a common module ('qed') and protocol
> specific dependent modules for ethernet ('qede'), fcoe ('qedf'),
> iscsi ('qedi') and roce ('qedr').
> The common module contains all of the common logic, e.g. initialization,
> cleanup, infrastructure for interrupt handling, link management, slowpath
> etc. as well as protocol agnostic features, and supplying an abstraction
> layer for other modules.
> The protocol specific modules can be compiled and operated independently
> of each other, with the exception of the rdma modules which are dependent
> on the ethernet module, in accordance with the kernel rdma stack design.
> 
> This series only adds the core and ethernet modules, with basic L2
> capabilities. Future series will add the rest of the modules and enhance
> the L2 functionality.
> 
> Ths patch series is constructed of the following patches:
> qed:  Add module with basic common support
> qed:  Add basic L2 interface
> qede: Add basic Network driver
> qed:  Add slowpath L2 support
> qede: Add basic network device support
> qede: Add classification configuration
> qed:  Add link support
> qede: Add support for link
> qed:  Add statistics support
> qede: Add basic ethtool support
> 
> We don't expect the series to be accepted as is. We are looking for
> upstream community feedback and guidance. Although the series is quite
> large, it is what we viewed as the minimal set of patches to constitute
> a basic L2 driver.
> 
> This project is a team effort, thanks go to Yuval Mintz, Dmitry Kravkov,
> Michal Kalderon, Tomer Tayar, Manish Chopra, Sudarsana Kalluru,
> Rajesh Borundia, Sony Chacko, Artum Zolotushko, Harish Patil, Rasesh Mody,
> Sergey Ukhterov and Elad Manela, as well as former team members,
> Eilon Greenstein and Shmulik Ravid.
> 
> Changes from previos version:
> -
> 
> From Version 1:
>   - Removed private license file; Instead revised comments at source headers.
> 
> Thanks,
> Ariel Elior

Hi,
Just a friendly reminder that this request for comment is still out there, and 
well, no comments have been forthcoming.
Thanks,
Ariel
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: bnx2x - occasional high packet loss (on LAN)

2015-09-21 Thread Ariel Elior
> -Original Message-
> From: Nikola Ciprich [mailto:nikola.cipr...@linuxbox.cz]
> Sent: Monday, September 21, 2015 1:32 PM
> To: Ariel Elior <ariel.el...@qlogic.com>
> Cc: netdev <netdev@vger.kernel.org>; n...@linuxbox.cz
> Subject: Re: bnx2x - occasional high packet loss (on LAN)
> 
> Hello Ariel,
> 
> after few days of torturing NICs with flood pings, card
> seems to have given up with lots of errors..
> 
> I've uploaded new kernel log here:
> 
> http://nik.lbox.cz/download/dmesg.txt
> 
> Will this help?
> 
> I still have it in this hung state now, in case I could provide
> more info for diagnostics..
> 
> however please note this can be different problem then I was reporting
> originaly, since I only had high packet loss, while now whole card
> seems to be blocked..  but maybe it just is worse case of the same
> problem?

Hi Nikola,
Seems like the link below is the same file you shared before - I don't see any 
errors there.

Two things you can collect for me to help debug this issue:

1.
Output of ethtool -d eth1 after problem occurs (redirect to a file)

2.
dmesg after enabling link related debug messages. Use
modprobe bnx2x debug=0x4
Or
ethtool -s eth1 msglvl 0x4
to enable these prints.

This holds for both of your problems (unless it is the same issue).

Thanks,
Ariel
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: bnx2x - occasional high packet loss (on LAN)

2015-09-16 Thread Ariel Elior
Hi Nikola,
Please provide dmesg output from your system.
Thanks,
Ariel

> -Original Message-
> From: netdev-ow...@vger.kernel.org [mailto:netdev-ow...@vger.kernel.org] On
> Behalf Of Nikola Ciprich
> Sent: Tuesday, September 15, 2015 7:17 AM
> To: netdev 
> Cc: n...@linuxbox.cz
> Subject: bnx2x - occasional high packet loss (on LAN)
> 
> Hello,
> 
> I'm trying to track strange issue with one of our servers and
> like to ask for recommendations..
> 
> I've got three node cluster (nodes A..C) interconnected with stacked broadcom
> ICX6610. eth0 of each box is connected to first switch, eth1 to second one,
> bonding set as follows: "mode=802.3ad lacp_rate=fast xmit_hash_policy=layer2+3
> miimon=100"
> 
> It happened few times, that suddenly eth1 on box A started misbehaving and
> communication
> with other nodes (ie flood ping) started dropping up to 30% packets. When 
> this port
> has been shut on both sides, problem immediately vanished.
> 
> We've tried replacing card, cable and using different port on switch, but 
> problem
> repeated again yesterday..
> 
> Since it's "only" loss, and not link loss, bonding doesn't help me much..
> 
> however during weekend, port also had strange link issue:
> 
> Sep 12 15:23:45 remrprv1a kernel: [676373.296786] bnx2x :03:00.1 eth1: NIC
> Link is Down
> Sep 12 15:23:46 remrprv1a kernel: [676373.356638] bond0: link status 
> definitely
> down for interface eth1, disabling it
> Sep 12 15:23:46 remrprv1a kernel: [676374.299571] bnx2x :03:00.1 eth1: NIC
> Link is Up, 1 Mbps full duplex, Flow control: ON - receive & transmit
> Sep 12 15:23:47 remrprv1a kernel: [676374.364428] bond0: link status 
> definitely up
> for interface eth1, 1 Mbps full duplex
> Sep 12 15:23:47 remrprv1a kernel: [676374.372902] bond0: first active 
> interface up!
> Sep 12 15:24:24 remrprv1a kernel: [676411.402511] bnx2x :03:00.1 eth1: NIC
> Link is Down
> Sep 12 15:24:24 remrprv1a kernel: [676411.407422] bond0: link status 
> definitely
> down for interface eth1, disabling it
> Sep 12 15:24:25 remrprv1a kernel: [676412.405311] bnx2x :03:00.1 eth1: NIC
> Link is Up, 1 Mbps full duplex, Flow control: ON - receive & transmit
> Sep 12 15:24:25 remrprv1a kernel: [676412.408123] bond0: link status 
> definitely up
> for interface eth1, 0 Mbps full duplex
> Sep 12 15:24:51 remrprv1a kernel: [676438.477641] bnx2x :03:00.1 eth1: NIC
> Link is Down
> Sep 12 15:24:51 remrprv1a kernel: [676438.528513] bond0: link status 
> definitely
> down for interface eth1, disabling it
> Sep 12 15:24:52 remrprv1a kernel: [676439.480472] bnx2x :03:00.1 eth1: NIC
> Link is Up, 1 Mbps full duplex, Flow control: ON - receive & transmit
> Sep 12 15:24:52 remrprv1a kernel: [676439.536282] bond0: link status 
> definitely up
> for interface eth1, 1 Mbps full duplex
> 
> 0mbps link speed is quite weird I guess..
> 
> all three boxes are the same, running centos6 based system, 4.0.5 x86_64 
> kernel.
> 
> The only difference I noticed on them is, that irqbalance was enabled on 
> problematic
> box and not on the others.. So I disabled it and rebooted the box.. The 
> problem is,
> I can't really wait for the problem to reappear, so I'd like to ask, has 
> anybody
> seen similar problem? I of so, was it fixed in some newer kernel release? I 
> haven't
> found mention in the changelogs, but still.. or does somebody have a hint on 
> what
> else
> I should check?
> 
> I'll try to reproduce this on test system (enabling irqbalance and doing some 
> network
> benchmarks, but I'd be most happy if I could prevent it on this production 
> system..)
> 
> thanks a lot for any advance
> 
> with best regards
> 
> nikola ciprich
> 
> PS: here's lspci -vv of eths.. should I provide any further information, 
> please let me
> know:
> 
> http://nik.lbox.cz/download/lspci.txt
> 
> --
> -
> Ing. Nikola CIPRICH
> LinuxBox.cz, s.r.o.
> 28.rijna 168, 709 00 Ostrava
> 
> tel.:   +420 591 166 214
> fax:+420 596 621 273
> mobil:  +420 777 093 799
> www.linuxbox.cz
> 
> mobil servis: +420 737 238 656
> email servis: ser...@linuxbox.cz
> -
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH] bnx2x: Alloc 4k fragment for each rx ring buffer element

2015-04-19 Thread Ariel Elior
Hi Gabriel,
Thanks for pointing out this shortcoming.
However, I don't think that the solution you suggested would work as is.

@@ -628,21 +644,30 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct 
bnx2x_fastpath *fp,
bnx2x_fp_qstats(bp, fp)-rx_skb_alloc_failed++;
return err;
}
+   if (old_rx_pg.offset + old_rx_pg.len = PAGE_SIZE) {
+   /* Unmap the page as we finished passing it to
+* the stack
+*/
+   old_rx_pg.mapping = old_rx_pg.mapping -
+   old_rx_pg.offset;
+   dma_unmap_page(bp-pdev-dev,
+  dma_unmap_addr(old_rx_pg, mapping),
+  PAGE_SIZE, DMA_FROM_DEVICE);
+   }

This code assumes that pages are consumed by the device in order. This is not 
true.
The pages are consumed according to packet arrival order, which can be from 
different aggregations.

We'll come up with a compatible solution.

Thanks,
Ariel
--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html