aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/qlogic/qed/qed_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/qlogic/qed/qed_dev.c')
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c85
1 files changed, 34 insertions, 51 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 9df8c4b3b54e..866cdc86a3f2 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -102,11 +102,15 @@ static void qed_db_recovery_dp_entry(struct qed_hwfn *p_hwfn,
102 102
103/* Doorbell address sanity (address within doorbell bar range) */ 103/* Doorbell address sanity (address within doorbell bar range) */
104static bool qed_db_rec_sanity(struct qed_dev *cdev, 104static bool qed_db_rec_sanity(struct qed_dev *cdev,
105 void __iomem *db_addr, void *db_data) 105 void __iomem *db_addr,
106 enum qed_db_rec_width db_width,
107 void *db_data)
106{ 108{
109 u32 width = (db_width == DB_REC_WIDTH_32B) ? 32 : 64;
110
107 /* Make sure doorbell address is within the doorbell bar */ 111 /* Make sure doorbell address is within the doorbell bar */
108 if (db_addr < cdev->doorbells || 112 if (db_addr < cdev->doorbells ||
109 (u8 __iomem *)db_addr > 113 (u8 __iomem *)db_addr + width >
110 (u8 __iomem *)cdev->doorbells + cdev->db_size) { 114 (u8 __iomem *)cdev->doorbells + cdev->db_size) {
111 WARN(true, 115 WARN(true,
112 "Illegal doorbell address: %p. Legal range for doorbell addresses is [%p..%p]\n", 116 "Illegal doorbell address: %p. Legal range for doorbell addresses is [%p..%p]\n",
@@ -159,7 +163,7 @@ int qed_db_recovery_add(struct qed_dev *cdev,
159 } 163 }
160 164
161 /* Sanitize doorbell address */ 165 /* Sanitize doorbell address */
162 if (!qed_db_rec_sanity(cdev, db_addr, db_data)) 166 if (!qed_db_rec_sanity(cdev, db_addr, db_width, db_data))
163 return -EINVAL; 167 return -EINVAL;
164 168
165 /* Obtain hwfn from doorbell address */ 169 /* Obtain hwfn from doorbell address */
@@ -205,10 +209,6 @@ int qed_db_recovery_del(struct qed_dev *cdev,
205 return 0; 209 return 0;
206 } 210 }
207 211
208 /* Sanitize doorbell address */
209 if (!qed_db_rec_sanity(cdev, db_addr, db_data))
210 return -EINVAL;
211
212 /* Obtain hwfn from doorbell address */ 212 /* Obtain hwfn from doorbell address */
213 p_hwfn = qed_db_rec_find_hwfn(cdev, db_addr); 213 p_hwfn = qed_db_rec_find_hwfn(cdev, db_addr);
214 214
@@ -300,31 +300,24 @@ void qed_db_recovery_dp(struct qed_hwfn *p_hwfn)
300 300
301/* Ring the doorbell of a single doorbell recovery entry */ 301/* Ring the doorbell of a single doorbell recovery entry */
302static void qed_db_recovery_ring(struct qed_hwfn *p_hwfn, 302static void qed_db_recovery_ring(struct qed_hwfn *p_hwfn,
303 struct qed_db_recovery_entry *db_entry, 303 struct qed_db_recovery_entry *db_entry)
304 enum qed_db_rec_exec db_exec) 304{
305{ 305 /* Print according to width */
306 if (db_exec != DB_REC_ONCE) { 306 if (db_entry->db_width == DB_REC_WIDTH_32B) {
307 /* Print according to width */ 307 DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
308 if (db_entry->db_width == DB_REC_WIDTH_32B) { 308 "ringing doorbell address %p data %x\n",
309 DP_VERBOSE(p_hwfn, QED_MSG_SPQ, 309 db_entry->db_addr,
310 "%s doorbell address %p data %x\n", 310 *(u32 *)db_entry->db_data);
311 db_exec == DB_REC_DRY_RUN ? 311 } else {
312 "would have rung" : "ringing", 312 DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
313 db_entry->db_addr, 313 "ringing doorbell address %p data %llx\n",
314 *(u32 *)db_entry->db_data); 314 db_entry->db_addr,
315 } else { 315 *(u64 *)(db_entry->db_data));
316 DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
317 "%s doorbell address %p data %llx\n",
318 db_exec == DB_REC_DRY_RUN ?
319 "would have rung" : "ringing",
320 db_entry->db_addr,
321 *(u64 *)(db_entry->db_data));
322 }
323 } 316 }
324 317
325 /* Sanity */ 318 /* Sanity */
326 if (!qed_db_rec_sanity(p_hwfn->cdev, db_entry->db_addr, 319 if (!qed_db_rec_sanity(p_hwfn->cdev, db_entry->db_addr,
327 db_entry->db_data)) 320 db_entry->db_width, db_entry->db_data))
328 return; 321 return;
329 322
330 /* Flush the write combined buffer. Since there are multiple doorbelling 323 /* Flush the write combined buffer. Since there are multiple doorbelling
@@ -334,14 +327,12 @@ static void qed_db_recovery_ring(struct qed_hwfn *p_hwfn,
334 wmb(); 327 wmb();
335 328
336 /* Ring the doorbell */ 329 /* Ring the doorbell */
337 if (db_exec == DB_REC_REAL_DEAL || db_exec == DB_REC_ONCE) { 330 if (db_entry->db_width == DB_REC_WIDTH_32B)
338 if (db_entry->db_width == DB_REC_WIDTH_32B) 331 DIRECT_REG_WR(db_entry->db_addr,
339 DIRECT_REG_WR(db_entry->db_addr, 332 *(u32 *)(db_entry->db_data));
340 *(u32 *)(db_entry->db_data)); 333 else
341 else 334 DIRECT_REG_WR64(db_entry->db_addr,
342 DIRECT_REG_WR64(db_entry->db_addr, 335 *(u64 *)(db_entry->db_data));
343 *(u64 *)(db_entry->db_data));
344 }
345 336
346 /* Flush the write combined buffer. Next doorbell may come from a 337 /* Flush the write combined buffer. Next doorbell may come from a
347 * different entity to the same address... 338 * different entity to the same address...
@@ -350,29 +341,21 @@ static void qed_db_recovery_ring(struct qed_hwfn *p_hwfn,
350} 341}
351 342
352/* Traverse the doorbell recovery entry list and ring all the doorbells */ 343/* Traverse the doorbell recovery entry list and ring all the doorbells */
353void qed_db_recovery_execute(struct qed_hwfn *p_hwfn, 344void qed_db_recovery_execute(struct qed_hwfn *p_hwfn)
354 enum qed_db_rec_exec db_exec)
355{ 345{
356 struct qed_db_recovery_entry *db_entry = NULL; 346 struct qed_db_recovery_entry *db_entry = NULL;
357 347
358 if (db_exec != DB_REC_ONCE) { 348 DP_NOTICE(p_hwfn, "Executing doorbell recovery. Counter was %d\n",
359 DP_NOTICE(p_hwfn, 349 p_hwfn->db_recovery_info.db_recovery_counter);
360 "Executing doorbell recovery. Counter was %d\n",
361 p_hwfn->db_recovery_info.db_recovery_counter);
362 350
363 /* Track amount of times recovery was executed */ 351 /* Track amount of times recovery was executed */
364 p_hwfn->db_recovery_info.db_recovery_counter++; 352 p_hwfn->db_recovery_info.db_recovery_counter++;
365 }
366 353
367 /* Protect the list */ 354 /* Protect the list */
368 spin_lock_bh(&p_hwfn->db_recovery_info.lock); 355 spin_lock_bh(&p_hwfn->db_recovery_info.lock);
369 list_for_each_entry(db_entry, 356 list_for_each_entry(db_entry,
370 &p_hwfn->db_recovery_info.list, list_entry) { 357 &p_hwfn->db_recovery_info.list, list_entry)
371 qed_db_recovery_ring(p_hwfn, db_entry, db_exec); 358 qed_db_recovery_ring(p_hwfn, db_entry);
372 if (db_exec == DB_REC_ONCE)
373 break;
374 }
375
376 spin_unlock_bh(&p_hwfn->db_recovery_info.lock); 359 spin_unlock_bh(&p_hwfn->db_recovery_info.lock);
377} 360}
378 361