Skip to content

Commit be24dd4

Browse files
committed
Merge tag 'misc-habanalabs-next-2021-10-18' of https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux into char-misc-next
Oded writes: This tag contains habanalabs driver changes for v5.16: - Add a new uAPI (under the memory ioctl) to request from the driver to export a DMA-BUF object that represents a memory region on the device's DRAM. This is needed to enable peer-to-peer over PCIe between habana device and an RDMA adapter (e.g. mlnx5 or efa rdma adapter). - Add debugfs node to dynamically configure CS timeout. Up until now, it was only configurable through kernel module parameter. - Fetch more comprehensive power information from the firmware. - Always take timestamp when waiting for user interrupt, as the user needs that information to optimize the graph runtime compilation. - Modify user interrupt to look on 64-bit user value as fence, instead of 32-bit. - Bypass reset in case of repeated h/w error event after device reset. This is to prevent endless loop of resets to the device. - Fix several bugs in multi CS completion code. - Fix race condition in fd close/open. - Update to latest firmware headers - Add select CRC32 in kconfig - Small fixes, cosmetics * tag 'misc-habanalabs-next-2021-10-18' of https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux: (25 commits) habanalabs: refactor fence handling in hl_cs_poll_fences habanalabs: context cleanup cosmetics habanalabs: simplify wait for interrupt with timestamp flow habanalabs: initialize hpriv fields before adding new node habanalabs: Unify frequency set/get functionality habanalabs: select CRC32 habanalabs: add support for dma-buf exporter habanalabs: define uAPI to export FD for DMA-BUF habanalabs: fix NULL pointer dereference habanalabs: fix race condition in multi CS completion habanalabs: use only u32 habanalabs: update firmware files habanalabs: bypass reset for continuous h/w error event habanalabs: take timestamp on wait for interrupt habanalabs: prevent race between fd close/open habanalabs: refactor reset log message habanalabs: define soft-reset as inference op habanalabs: fix debugfs device memory MMU VA translation habanalabs: add support for a long interrupt target value habanalabs: remove redundant cs validity checks ...
2 parents 2b74240 + b2faac3 commit be24dd4

File tree

27 files changed

+1309
-305
lines changed

27 files changed

+1309
-305
lines changed

Documentation/ABI/testing/debugfs-driver-habanalabs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ Description: Gets the state dump occurring on a CS timeout or failure.
226226
Writing an integer X discards X state dumps, so that the
227227
next read would return X+1-st newest state dump.
228228

229+
What: /sys/kernel/debug/habanalabs/hl<n>/timeout_locked
230+
Date: Sep 2021
231+
KernelVersion: 5.16
232+
233+
Description: Sets the command submission timeout value in seconds.
234+
229235
What: /sys/kernel/debug/habanalabs/hl<n>/stop_on_err
230236
Date: Mar 2020
231237
KernelVersion: 5.6

drivers/misc/habanalabs/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ config HABANA_AI
88
depends on PCI && HAS_IOMEM
99
select GENERIC_ALLOCATOR
1010
select HWMON
11+
select DMA_SHARED_BUFFER
12+
select CRC32
1113
help
1214
Enables PCIe card driver for Habana's AI Processors (AIP) that are
1315
designed to accelerate Deep Learning inference and training workloads.

drivers/misc/habanalabs/common/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ HL_COMMON_FILES := common/habanalabs_drv.o common/device.o common/context.o \
1111
common/command_buffer.o common/hw_queue.o common/irq.o \
1212
common/sysfs.o common/hwmon.o common/memory.o \
1313
common/command_submission.o common/firmware_if.o \
14-
common/state_dump.o
14+
common/state_dump.o common/hwmgr.o

drivers/misc/habanalabs/common/command_submission.c

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ static void hl_fence_init(struct hl_fence *fence, u64 sequence)
143143
fence->cs_sequence = sequence;
144144
fence->error = 0;
145145
fence->timestamp = ktime_set(0, 0);
146+
fence->mcs_handling_done = false;
146147
init_completion(&fence->completion);
147148
}
148149

@@ -431,11 +432,10 @@ static void cs_handle_tdr(struct hl_device *hdev, struct hl_cs *cs)
431432
/* Don't cancel TDR in case this CS was timedout because we might be
432433
* running from the TDR context
433434
*/
434-
if (cs && (cs->timedout ||
435-
hdev->timeout_jiffies == MAX_SCHEDULE_TIMEOUT))
435+
if (cs->timedout || hdev->timeout_jiffies == MAX_SCHEDULE_TIMEOUT)
436436
return;
437437

438-
if (cs && cs->tdr_active)
438+
if (cs->tdr_active)
439439
cancel_delayed_work_sync(&cs->work_tdr);
440440

441441
spin_lock(&hdev->cs_mirror_lock);
@@ -536,10 +536,21 @@ static void complete_multi_cs(struct hl_device *hdev, struct hl_cs *cs)
536536
mcs_compl->timestamp =
537537
ktime_to_ns(fence->timestamp);
538538
complete_all(&mcs_compl->completion);
539+
540+
/*
541+
* Setting mcs_handling_done inside the lock ensures
542+
* at least one fence have mcs_handling_done set to
543+
* true before wait for mcs finish. This ensures at
544+
* least one CS will be set as completed when polling
545+
* mcs fences.
546+
*/
547+
fence->mcs_handling_done = true;
539548
}
540549

541550
spin_unlock(&mcs_compl->lock);
542551
}
552+
/* In case CS completed without mcs completion initialized */
553+
fence->mcs_handling_done = true;
543554
}
544555

545556
static inline void cs_release_sob_reset_handler(struct hl_device *hdev,
@@ -2371,32 +2382,48 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data)
23712382
break;
23722383
}
23732384

2374-
mcs_data->stream_master_qid_map |= fence->stream_master_qid_map;
2375-
2376-
if (status == CS_WAIT_STATUS_BUSY)
2377-
continue;
2378-
2379-
mcs_data->completion_bitmap |= BIT(i);
2380-
2381-
/*
2382-
* best effort to extract timestamp. few notes:
2383-
* - if even single fence is gone we cannot extract timestamp
2384-
* (as fence not exist anymore)
2385-
* - for all completed CSs we take the earliest timestamp.
2386-
* for this we have to validate that:
2387-
* 1. given timestamp was indeed set
2388-
* 2. the timestamp is earliest of all timestamps so far
2389-
*/
2385+
switch (status) {
2386+
case CS_WAIT_STATUS_BUSY:
2387+
/* CS did not finished, keep waiting on its QID*/
2388+
mcs_data->stream_master_qid_map |=
2389+
fence->stream_master_qid_map;
2390+
break;
2391+
case CS_WAIT_STATUS_COMPLETED:
2392+
/*
2393+
* Using mcs_handling_done to avoid possibility of mcs_data
2394+
* returns to user indicating CS completed before it finished
2395+
* all of its mcs handling, to avoid race the next time the
2396+
* user waits for mcs.
2397+
*/
2398+
if (!fence->mcs_handling_done)
2399+
break;
23902400

2391-
if (status == CS_WAIT_STATUS_GONE) {
2401+
mcs_data->completion_bitmap |= BIT(i);
2402+
/*
2403+
* For all completed CSs we take the earliest timestamp.
2404+
* For this we have to validate that the timestamp is
2405+
* earliest of all timestamps so far.
2406+
*/
2407+
if (mcs_data->update_ts &&
2408+
(ktime_compare(fence->timestamp, first_cs_time) < 0))
2409+
first_cs_time = fence->timestamp;
2410+
break;
2411+
case CS_WAIT_STATUS_GONE:
23922412
mcs_data->update_ts = false;
23932413
mcs_data->gone_cs = true;
2394-
} else if (mcs_data->update_ts &&
2395-
(ktime_compare(fence->timestamp,
2396-
ktime_set(0, 0)) > 0) &&
2397-
(ktime_compare(fence->timestamp, first_cs_time) < 0)) {
2398-
first_cs_time = fence->timestamp;
2414+
/*
2415+
* It is possible to get an old sequence numbers from user
2416+
* which related to already completed CSs and their fences
2417+
* already gone. In this case, CS set as completed but
2418+
* no need to consider its QID for mcs completion.
2419+
*/
2420+
mcs_data->completion_bitmap |= BIT(i);
2421+
break;
2422+
default:
2423+
dev_err(hdev->dev, "Invalid fence status\n");
2424+
return -EINVAL;
23992425
}
2426+
24002427
}
24012428

24022429
hl_fences_put(mcs_data->fence_arr, arr_len);
@@ -2740,13 +2767,14 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
27402767

27412768
static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
27422769
u32 timeout_us, u64 user_address,
2743-
u32 target_value, u16 interrupt_offset,
2744-
enum hl_cs_wait_status *status)
2770+
u64 target_value, u16 interrupt_offset,
2771+
enum hl_cs_wait_status *status,
2772+
u64 *timestamp)
27452773
{
27462774
struct hl_user_pending_interrupt *pend;
27472775
struct hl_user_interrupt *interrupt;
27482776
unsigned long timeout, flags;
2749-
u32 completion_value;
2777+
u64 completion_value;
27502778
long completion_rc;
27512779
int rc = 0;
27522780

@@ -2780,15 +2808,17 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
27802808
/* We check for completion value as interrupt could have been received
27812809
* before we added the node to the wait list
27822810
*/
2783-
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 4)) {
2811+
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) {
27842812
dev_err(hdev->dev, "Failed to copy completion value from user\n");
27852813
rc = -EFAULT;
27862814
goto remove_pending_user_interrupt;
27872815
}
27882816

2789-
if (completion_value >= target_value)
2817+
if (completion_value >= target_value) {
27902818
*status = CS_WAIT_STATUS_COMPLETED;
2791-
else
2819+
/* There was no interrupt, we assume the completion is now. */
2820+
pend->fence.timestamp = ktime_get();
2821+
} else
27922822
*status = CS_WAIT_STATUS_BUSY;
27932823

27942824
if (!timeout_us || (*status == CS_WAIT_STATUS_COMPLETED))
@@ -2812,7 +2842,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
28122842
reinit_completion(&pend->fence.completion);
28132843
spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
28142844

2815-
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 4)) {
2845+
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) {
28162846
dev_err(hdev->dev, "Failed to copy completion value from user\n");
28172847
rc = -EFAULT;
28182848

@@ -2839,6 +2869,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
28392869
list_del(&pend->wait_list_node);
28402870
spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
28412871

2872+
*timestamp = ktime_to_ns(pend->fence.timestamp);
2873+
28422874
kfree(pend);
28432875
hl_ctx_put(ctx);
28442876

@@ -2852,6 +2884,7 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
28522884
struct asic_fixed_properties *prop;
28532885
union hl_wait_cs_args *args = data;
28542886
enum hl_cs_wait_status status;
2887+
u64 timestamp;
28552888
int rc;
28562889

28572890
prop = &hdev->asic_prop;
@@ -2881,7 +2914,8 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
28812914

28822915
rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx,
28832916
args->in.interrupt_timeout_us, args->in.addr,
2884-
args->in.target, interrupt_offset, &status);
2917+
args->in.target, interrupt_offset, &status,
2918+
&timestamp);
28852919

28862920
if (rc) {
28872921
if (rc != -EINTR)
@@ -2893,6 +2927,11 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
28932927

28942928
memset(args, 0, sizeof(*args));
28952929

2930+
if (timestamp) {
2931+
args->out.timestamp_nsec = timestamp;
2932+
args->out.flags |= HL_WAIT_CS_STATUS_FLAG_TIMESTAMP_VLD;
2933+
}
2934+
28962935
switch (status) {
28972936
case CS_WAIT_STATUS_COMPLETED:
28982937
args->out.status = HL_WAIT_CS_STATUS_COMPLETED;

drivers/misc/habanalabs/common/context.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,6 @@ int hl_ctx_create(struct hl_device *hdev, struct hl_fpriv *hpriv)
181181
return rc;
182182
}
183183

184-
void hl_ctx_free(struct hl_device *hdev, struct hl_ctx *ctx)
185-
{
186-
if (kref_put(&ctx->refcount, hl_ctx_do_release) == 1)
187-
return;
188-
}
189-
190184
int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
191185
{
192186
int rc = 0;
@@ -392,7 +386,7 @@ void hl_ctx_mgr_fini(struct hl_device *hdev, struct hl_ctx_mgr *mgr)
392386
idp = &mgr->ctx_handles;
393387

394388
idr_for_each_entry(idp, ctx, id)
395-
hl_ctx_free(hdev, ctx);
389+
kref_put(&ctx->refcount, hl_ctx_do_release);
396390

397391
idr_destroy(&mgr->ctx_handles);
398392
mutex_destroy(&mgr->ctx_lock);

drivers/misc/habanalabs/common/debugfs.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,45 @@ static ssize_t hl_state_dump_write(struct file *f, const char __user *buf,
11671167
return count;
11681168
}
11691169

1170+
static ssize_t hl_timeout_locked_read(struct file *f, char __user *buf,
1171+
size_t count, loff_t *ppos)
1172+
{
1173+
struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
1174+
struct hl_device *hdev = entry->hdev;
1175+
char tmp_buf[200];
1176+
ssize_t rc;
1177+
1178+
if (*ppos)
1179+
return 0;
1180+
1181+
sprintf(tmp_buf, "%d\n",
1182+
jiffies_to_msecs(hdev->timeout_jiffies) / 1000);
1183+
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
1184+
strlen(tmp_buf) + 1);
1185+
1186+
return rc;
1187+
}
1188+
1189+
static ssize_t hl_timeout_locked_write(struct file *f, const char __user *buf,
1190+
size_t count, loff_t *ppos)
1191+
{
1192+
struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
1193+
struct hl_device *hdev = entry->hdev;
1194+
u32 value;
1195+
ssize_t rc;
1196+
1197+
rc = kstrtouint_from_user(buf, count, 10, &value);
1198+
if (rc)
1199+
return rc;
1200+
1201+
if (value)
1202+
hdev->timeout_jiffies = msecs_to_jiffies(value * 1000);
1203+
else
1204+
hdev->timeout_jiffies = MAX_SCHEDULE_TIMEOUT;
1205+
1206+
return count;
1207+
}
1208+
11701209
static const struct file_operations hl_data32b_fops = {
11711210
.owner = THIS_MODULE,
11721211
.read = hl_data_read32,
@@ -1240,6 +1279,12 @@ static const struct file_operations hl_state_dump_fops = {
12401279
.write = hl_state_dump_write
12411280
};
12421281

1282+
static const struct file_operations hl_timeout_locked_fops = {
1283+
.owner = THIS_MODULE,
1284+
.read = hl_timeout_locked_read,
1285+
.write = hl_timeout_locked_write
1286+
};
1287+
12431288
static const struct hl_info_list hl_debugfs_list[] = {
12441289
{"command_buffers", command_buffers_show, NULL},
12451290
{"command_submission", command_submission_show, NULL},
@@ -1421,6 +1466,12 @@ void hl_debugfs_add_device(struct hl_device *hdev)
14211466
dev_entry,
14221467
&hl_state_dump_fops);
14231468

1469+
debugfs_create_file("timeout_locked",
1470+
0644,
1471+
dev_entry->root,
1472+
dev_entry,
1473+
&hl_timeout_locked_fops);
1474+
14241475
for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
14251476
debugfs_create_file(hl_debugfs_list[i].name,
14261477
0444,

0 commit comments

Comments
 (0)