.. | .. |
---|
723 | 723 | range = page_address(ns->ctrl->discard_page); |
---|
724 | 724 | } |
---|
725 | 725 | |
---|
726 | | - __rq_for_each_bio(bio, req) { |
---|
727 | | - u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector); |
---|
728 | | - u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift; |
---|
| 726 | + if (queue_max_discard_segments(req->q) == 1) { |
---|
| 727 | + u64 slba = nvme_sect_to_lba(ns, blk_rq_pos(req)); |
---|
| 728 | + u32 nlb = blk_rq_sectors(req) >> (ns->lba_shift - 9); |
---|
729 | 729 | |
---|
730 | | - if (n < segments) { |
---|
731 | | - range[n].cattr = cpu_to_le32(0); |
---|
732 | | - range[n].nlb = cpu_to_le32(nlb); |
---|
733 | | - range[n].slba = cpu_to_le64(slba); |
---|
| 730 | + range[0].cattr = cpu_to_le32(0); |
---|
| 731 | + range[0].nlb = cpu_to_le32(nlb); |
---|
| 732 | + range[0].slba = cpu_to_le64(slba); |
---|
| 733 | + n = 1; |
---|
| 734 | + } else { |
---|
| 735 | + __rq_for_each_bio(bio, req) { |
---|
| 736 | + u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector); |
---|
| 737 | + u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift; |
---|
| 738 | + |
---|
| 739 | + if (n < segments) { |
---|
| 740 | + range[n].cattr = cpu_to_le32(0); |
---|
| 741 | + range[n].nlb = cpu_to_le32(nlb); |
---|
| 742 | + range[n].slba = cpu_to_le64(slba); |
---|
| 743 | + } |
---|
| 744 | + n++; |
---|
734 | 745 | } |
---|
735 | | - n++; |
---|
736 | 746 | } |
---|
737 | 747 | |
---|
738 | 748 | if (WARN_ON_ONCE(n != segments)) { |
---|
.. | .. |
---|
4406 | 4416 | nvme_get_fw_slot_info(ctrl); |
---|
4407 | 4417 | } |
---|
4408 | 4418 | |
---|
| 4419 | +static u32 nvme_aer_type(u32 result) |
---|
| 4420 | +{ |
---|
| 4421 | + return result & 0x7; |
---|
| 4422 | +} |
---|
| 4423 | + |
---|
| 4424 | +static u32 nvme_aer_subtype(u32 result) |
---|
| 4425 | +{ |
---|
| 4426 | + return (result & 0xff00) >> 8; |
---|
| 4427 | +} |
---|
| 4428 | + |
---|
4409 | 4429 | static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result) |
---|
4410 | 4430 | { |
---|
4411 | | - u32 aer_notice_type = (result & 0xff00) >> 8; |
---|
4412 | | - |
---|
4413 | | - trace_nvme_async_event(ctrl, aer_notice_type); |
---|
| 4431 | + u32 aer_notice_type = nvme_aer_subtype(result); |
---|
4414 | 4432 | |
---|
4415 | 4433 | switch (aer_notice_type) { |
---|
4416 | 4434 | case NVME_AER_NOTICE_NS_CHANGED: |
---|
.. | .. |
---|
4441 | 4459 | } |
---|
4442 | 4460 | } |
---|
4443 | 4461 | |
---|
| 4462 | +static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl) |
---|
| 4463 | +{ |
---|
| 4464 | + dev_warn(ctrl->device, "resetting controller due to AER\n"); |
---|
| 4465 | + nvme_reset_ctrl(ctrl); |
---|
| 4466 | +} |
---|
| 4467 | + |
---|
4444 | 4468 | void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, |
---|
4445 | 4469 | volatile union nvme_result *res) |
---|
4446 | 4470 | { |
---|
4447 | 4471 | u32 result = le32_to_cpu(res->u32); |
---|
4448 | | - u32 aer_type = result & 0x07; |
---|
| 4472 | + u32 aer_type = nvme_aer_type(result); |
---|
| 4473 | + u32 aer_subtype = nvme_aer_subtype(result); |
---|
4449 | 4474 | |
---|
4450 | 4475 | if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS) |
---|
4451 | 4476 | return; |
---|
4452 | 4477 | |
---|
| 4478 | + trace_nvme_async_event(ctrl, result); |
---|
4453 | 4479 | switch (aer_type) { |
---|
4454 | 4480 | case NVME_AER_NOTICE: |
---|
4455 | 4481 | nvme_handle_aen_notice(ctrl, result); |
---|
4456 | 4482 | break; |
---|
4457 | 4483 | case NVME_AER_ERROR: |
---|
| 4484 | + /* |
---|
| 4485 | + * For a persistent internal error, don't run async_event_work |
---|
| 4486 | + * to submit a new AER. The controller reset will do it. |
---|
| 4487 | + */ |
---|
| 4488 | + if (aer_subtype == NVME_AER_ERROR_PERSIST_INT_ERR) { |
---|
| 4489 | + nvme_handle_aer_persistent_error(ctrl); |
---|
| 4490 | + return; |
---|
| 4491 | + } |
---|
| 4492 | + fallthrough; |
---|
4458 | 4493 | case NVME_AER_SMART: |
---|
4459 | 4494 | case NVME_AER_CSS: |
---|
4460 | 4495 | case NVME_AER_VS: |
---|
4461 | | - trace_nvme_async_event(ctrl, aer_type); |
---|
4462 | 4496 | ctrl->aen_result = result; |
---|
4463 | 4497 | break; |
---|
4464 | 4498 | default: |
---|