diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qed/qed_dev.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_dev.c | 85 |
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) */ |
104 | static bool qed_db_rec_sanity(struct qed_dev *cdev, | 104 | static 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 */ |
302 | static void qed_db_recovery_ring(struct qed_hwfn *p_hwfn, | 302 | static 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 */ |
353 | void qed_db_recovery_execute(struct qed_hwfn *p_hwfn, | 344 | void 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 | ||