Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: libsas: Add sas_execute_internal_abort_single()

The internal abort feature is common to hisi_sas and pm8001 HBAs, and the
driver support is similar also, so add a common handler.

Two modes of operation will be supported:

- single: Abort a single tagged command

- device: Abort all commands associated with a specific domain device

A new protocol is added, SAS_PROTOCOL_INTERNAL_ABORT, so the common queue
command API may be re-used.

Only add "single" support as a first step.

Link: https://lore.kernel.org/r/1647001432-239276-2-git-send-email-john.garry@huawei.com
Tested-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Acked-by: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

John Garry and committed by
Martin K. Petersen
5c9bf363 2ea3a393

+90
+74
drivers/scsi/libsas/sas_scsi_host.c
··· 920 920 #define TASK_TIMEOUT (20 * HZ) 921 921 #define TASK_RETRY 3 922 922 923 + static int sas_execute_internal_abort(struct domain_device *device, 924 + enum sas_internal_abort type, u16 tag, 925 + unsigned int qid, void *data) 926 + { 927 + struct sas_ha_struct *ha = device->port->ha; 928 + struct sas_internal *i = to_sas_internal(ha->core.shost->transportt); 929 + struct sas_task *task = NULL; 930 + int res, retry; 931 + 932 + for (retry = 0; retry < TASK_RETRY; retry++) { 933 + task = sas_alloc_slow_task(GFP_KERNEL); 934 + if (!task) 935 + return -ENOMEM; 936 + 937 + task->dev = device; 938 + task->task_proto = SAS_PROTOCOL_INTERNAL_ABORT; 939 + task->task_done = sas_task_internal_done; 940 + task->slow_task->timer.function = sas_task_internal_timedout; 941 + task->slow_task->timer.expires = jiffies + TASK_TIMEOUT; 942 + add_timer(&task->slow_task->timer); 943 + 944 + task->abort_task.tag = tag; 945 + task->abort_task.type = type; 946 + 947 + res = i->dft->lldd_execute_task(task, GFP_KERNEL); 948 + if (res) { 949 + del_timer_sync(&task->slow_task->timer); 950 + pr_err("Executing internal abort failed %016llx (%d)\n", 951 + SAS_ADDR(device->sas_addr), res); 952 + break; 953 + } 954 + 955 + wait_for_completion(&task->slow_task->completion); 956 + res = TMF_RESP_FUNC_FAILED; 957 + 958 + /* Even if the internal abort timed out, return direct. */ 959 + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { 960 + pr_err("Internal abort: timeout %016llx\n", 961 + SAS_ADDR(device->sas_addr)); 962 + res = -EIO; 963 + break; 964 + } 965 + 966 + if (task->task_status.resp == SAS_TASK_COMPLETE && 967 + task->task_status.stat == SAS_SAM_STAT_GOOD) { 968 + res = TMF_RESP_FUNC_COMPLETE; 969 + break; 970 + } 971 + 972 + if (task->task_status.resp == SAS_TASK_COMPLETE && 973 + task->task_status.stat == TMF_RESP_FUNC_SUCC) { 974 + res = TMF_RESP_FUNC_SUCC; 975 + break; 976 + } 977 + 978 + pr_err("Internal abort: task to dev %016llx response: 0x%x status 0x%x\n", 979 + SAS_ADDR(device->sas_addr), task->task_status.resp, 980 + task->task_status.stat); 981 + sas_free_task(task); 982 + task = NULL; 983 + } 984 + BUG_ON(retry == TASK_RETRY && task != NULL); 985 + sas_free_task(task); 986 + return res; 987 + } 988 + 989 + int sas_execute_internal_abort_single(struct domain_device *device, u16 tag, 990 + unsigned int qid, void *data) 991 + { 992 + return sas_execute_internal_abort(device, SAS_INTERNAL_ABORT_SINGLE, 993 + tag, qid, data); 994 + } 995 + EXPORT_SYMBOL_GPL(sas_execute_internal_abort_single); 996 + 923 997 int sas_execute_tmf(struct domain_device *device, void *parameter, 924 998 int para_len, int force_phy_id, 925 999 struct sas_tmf_task *tmf)
+14
include/scsi/libsas.h
··· 557 557 int force_phy_id; 558 558 }; 559 559 560 + /* LLDDs rely on these values */ 561 + enum sas_internal_abort { 562 + SAS_INTERNAL_ABORT_SINGLE = 0, 563 + }; 564 + 565 + struct sas_internal_abort_task { 566 + enum sas_internal_abort type; 567 + u16 tag; 568 + }; 569 + 560 570 struct sas_smp_task { 561 571 struct scatterlist smp_req; 562 572 struct scatterlist smp_resp; ··· 606 596 struct sas_ata_task ata_task; 607 597 struct sas_smp_task smp_task; 608 598 struct sas_ssp_task ssp_task; 599 + struct sas_internal_abort_task abort_task; 609 600 }; 610 601 611 602 struct scatterlist *scatter; ··· 694 683 extern int sas_change_queue_depth(struct scsi_device *, int new_depth); 695 684 extern int sas_bios_param(struct scsi_device *, struct block_device *, 696 685 sector_t capacity, int *hsc); 686 + int sas_execute_internal_abort_single(struct domain_device *device, 687 + u16 tag, unsigned int qid, 688 + void *data); 697 689 extern struct scsi_transport_template * 698 690 sas_domain_attach_transport(struct sas_domain_function_template *); 699 691 extern struct device_attribute dev_attr_phy_event_threshold;
+2
include/scsi/sas.h
··· 95 95 SAS_PROTOCOL_SSP = 0x08, 96 96 SAS_PROTOCOL_ALL = 0x0E, 97 97 SAS_PROTOCOL_STP_ALL = SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA, 98 + /* these are internal to libsas */ 99 + SAS_PROTOCOL_INTERNAL_ABORT = 0x10, 98 100 }; 99 101 100 102 /* From the spec; local phys only */