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 | ||
