Lines Matching +full:cmd +full:- +full:timeout +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0
19 #include <linux/fsi-sbefifo.h>
38 * The SBEFIFO is a pipe-like FSI device for communicating with
50 #define SBEFIFO_UP 0x00 /* FSI -> Host */
51 #define SBEFIFO_DOWN 0x40 /* Host -> FSI */
53 /* Per-bank registers */
85 SBE_STATE_IPLING = 0x1, // IPL'ing - autonomous mode (transient)
86 SBE_STATE_ISTEP = 0x2, // ISTEP - Running IPL by steps (transient)
92 SBE_STATE_QUIESCE = 0x8, // Final state - needs SBE reset to get out
103 #define sbefifo_vacant(sts) (SBEFIFO_FIFO_DEPTH - sbefifo_populated(sts))
106 /* Reset request timeout in ms */
109 /* Timeouts for commands in ms */
149 return sysfs_emit(buf, "%d\n", sbefifo->timed_out ? 1 : 0); in timeout_show()
151 static DEVICE_ATTR_RO(timeout);
170 ffdc_sz -= 3; in __sbefifo_dump_ffdc()
184 dev_warn(dev, "+---- SBE FFDC package %d for async err -----+\n", in __sbefifo_dump_ffdc()
187 dev_warn(dev, "+---- SBE FFDC package %d for cmd %02x:%02x -----+\n", in __sbefifo_dump_ffdc()
191 dev_warn(dev, "|-------------------------------------------|\n"); in __sbefifo_dump_ffdc()
198 ffdc_sz--; in __sbefifo_dump_ffdc()
199 if ((i & 3) == 3 || i == (w0 - 1)) { in __sbefifo_dump_ffdc()
207 dev_warn(dev, "+-------------------------------------------+\n"); in __sbefifo_dump_ffdc()
219 int sbefifo_parse_status(struct device *dev, u16 cmd, __be32 *response, in sbefifo_parse_status() argument
226 pr_debug("sbefifo: cmd %04x, response too small: %zd\n", in sbefifo_parse_status()
227 cmd, resp_len); in sbefifo_parse_status()
228 return -ENXIO; in sbefifo_parse_status()
230 dh = be32_to_cpu(response[resp_len - 1]); in sbefifo_parse_status()
232 dev_err(dev, "SBE cmd %02x:%02x status offset out of range: %d/%zd\n", in sbefifo_parse_status()
233 cmd >> 8, cmd & 0xff, dh, resp_len); in sbefifo_parse_status()
234 return -ENXIO; in sbefifo_parse_status()
236 s0 = be32_to_cpu(response[resp_len - dh]); in sbefifo_parse_status()
237 s1 = be32_to_cpu(response[resp_len - dh + 1]); in sbefifo_parse_status()
238 if (((s0 >> 16) != 0xC0DE) || ((s0 & 0xffff) != cmd)) { in sbefifo_parse_status()
239 dev_err(dev, "SBE cmd %02x:%02x, status signature invalid: 0x%08x 0x%08x\n", in sbefifo_parse_status()
240 cmd >> 8, cmd & 0xff, s0, s1); in sbefifo_parse_status()
241 return -ENXIO; in sbefifo_parse_status()
244 ffdc_sz = dh - 3; in sbefifo_parse_status()
245 dev_warn(dev, "SBE error cmd %02x:%02x status=%04x:%04x\n", in sbefifo_parse_status()
246 cmd >> 8, cmd & 0xff, s1 >> 16, s1 & 0xffff); in sbefifo_parse_status()
248 sbefifo_dump_ffdc(dev, &response[resp_len - dh + 2], in sbefifo_parse_status()
252 *data_len = resp_len - dh; in sbefifo_parse_status()
267 rc = fsi_device_read(sbefifo->fsi_dev, reg, &raw_word, in sbefifo_regr()
281 return fsi_device_write(sbefifo->fsi_dev, reg, &raw_word, in sbefifo_regw()
291 rc = fsi_slave_read(sbefifo->fsi_dev->slave, CFAM_GP_MBOX_SBM_ADDR, in sbefifo_check_sbe_state()
299 return -ESHUTDOWN; in sbefifo_check_sbe_state()
304 return -ESHUTDOWN; in sbefifo_check_sbe_state()
306 return -EBUSY; in sbefifo_check_sbe_state()
315 return -ESHUTDOWN; in sbefifo_check_sbe_state()
320 sbefifo->async_ffdc = true; in sbefifo_check_sbe_state()
328 return fsi_device_read(sbefifo->fsi_dev, SBEFIFO_DOWN, word, in sbefifo_down_read()
334 return fsi_device_write(sbefifo->fsi_dev, SBEFIFO_UP, &word, in sbefifo_up_write()
340 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_request_reset()
348 sbefifo->broken = true; in sbefifo_request_reset()
369 sbefifo->broken = false; in sbefifo_request_reset()
377 return -ETIMEDOUT; in sbefifo_request_reset()
382 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_cleanup_hw()
394 if (sbefifo->broken) in sbefifo_cleanup_hw()
402 sbefifo->broken = true; in sbefifo_cleanup_hw()
411 sbefifo->broken = true; in sbefifo_cleanup_hw()
420 sbefifo->broken = true; in sbefifo_cleanup_hw()
424 sbefifo->broken = false; in sbefifo_cleanup_hw()
449 u32 *status, unsigned long timeout) in sbefifo_wait() argument
451 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_wait()
461 end_time = jiffies + timeout; in sbefifo_wait()
471 return -ENXIO; in sbefifo_wait()
478 sysfs_notify(&sbefifo->dev.kobj, NULL, dev_attr_timeout.attr.name); in sbefifo_wait()
479 sbefifo->timed_out = true; in sbefifo_wait()
480 dev_err(dev, "%s FIFO Timeout (%u ms)! status=%08x\n", in sbefifo_wait()
481 up ? "UP" : "DOWN", jiffies_to_msecs(timeout), sts); in sbefifo_wait()
482 return -ETIMEDOUT; in sbefifo_wait()
486 sbefifo->timed_out = false; in sbefifo_wait()
495 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_send_command()
497 unsigned long timeout; in sbefifo_send_command() local
501 dev_dbg(dev, "sending command (%zd words, cmd=%04x)\n", in sbefifo_send_command()
505 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_CMD); in sbefifo_send_command()
508 rc = sbefifo_wait(sbefifo, true, &status, timeout); in sbefifo_send_command()
511 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_IN_CMD); in sbefifo_send_command()
520 while (len--) { in sbefifo_send_command()
527 remaining -= chunk; in sbefifo_send_command()
528 vacant -= chunk; in sbefifo_send_command()
533 rc = sbefifo_wait(sbefifo, true, &status, timeout); in sbefifo_send_command()
547 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_read_response()
549 unsigned long timeout; in sbefifo_read_response() local
557 timeout = msecs_to_jiffies(sbefifo->timeout_start_rsp_ms); in sbefifo_read_response()
560 rc = sbefifo_wait(sbefifo, false, &status, timeout); in sbefifo_read_response()
562 dev_dbg(dev, "timeout waiting (%u ms)\n", jiffies_to_msecs(timeout)); in sbefifo_read_response()
565 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_IN_RSP); in sbefifo_read_response()
574 while(len--) { in sbefifo_read_response()
592 sbefifo->broken = true; in sbefifo_read_response()
606 sbefifo->broken = true; in sbefifo_read_response()
610 return overflow ? -EOVERFLOW : 0; in sbefifo_read_response()
616 return -EFAULT; in sbefifo_read_response()
628 return -EIO; in sbefifo_read_response()
646 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_collect_async_ffdc()
651 __be32 cmd[2]; in sbefifo_collect_async_ffdc() local
654 sbefifo->async_ffdc = false; in sbefifo_collect_async_ffdc()
663 cmd[0] = cpu_to_be32(2); in sbefifo_collect_async_ffdc()
664 cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC); in sbefifo_collect_async_ffdc()
665 rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter); in sbefifo_collect_async_ffdc()
670 ffdc_sz = SBEFIFO_MAX_FFDC_SIZE - iov_iter_count(&ffdc_iter); in sbefifo_collect_async_ffdc()
689 struct device *dev = &sbefifo->fsi_dev->dev; in __sbefifo_submit()
692 if (sbefifo->dead) in __sbefifo_submit()
693 return -ENODEV; in __sbefifo_submit()
698 return -EINVAL; in __sbefifo_submit()
707 if (sbefifo->async_ffdc) in __sbefifo_submit()
711 if (rc != 0 && rc != -EOVERFLOW) in __sbefifo_submit()
726 * sbefifo_submit() - Submit and SBE fifo command and receive response
729 * @cmd_len: The command size (in 32-bit words)
734 * overflows, returns -EOVERFLOW
746 return -ENODEV; in sbefifo_submit()
749 return -ENODEV; in sbefifo_submit()
750 if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC)) in sbefifo_submit()
751 return -ENODEV; in sbefifo_submit()
753 return -EINVAL; in sbefifo_submit()
762 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_submit()
766 mutex_unlock(&sbefifo->lock); in sbefifo_submit()
769 rbytes -= iov_iter_count(&resp_iter); in sbefifo_submit()
782 if (is_vmalloc_addr(user->pending_cmd)) in sbefifo_release_command()
783 vfree(user->pending_cmd); in sbefifo_release_command()
784 user->pending_cmd = NULL; in sbefifo_release_command()
785 user->pending_len = 0; in sbefifo_release_command()
790 struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev); in sbefifo_user_open()
795 return -ENOMEM; in sbefifo_user_open()
797 file->private_data = user; in sbefifo_user_open()
798 user->sbefifo = sbefifo; in sbefifo_user_open()
799 user->cmd_page = (void *)__get_free_page(GFP_KERNEL); in sbefifo_user_open()
800 if (!user->cmd_page) { in sbefifo_user_open()
802 return -ENOMEM; in sbefifo_user_open()
804 mutex_init(&user->file_lock); in sbefifo_user_open()
805 user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_user_open()
813 struct sbefifo_user *user = file->private_data; in sbefifo_user_read()
821 return -EINVAL; in sbefifo_user_read()
822 sbefifo = user->sbefifo; in sbefifo_user_read()
824 return -EINVAL; in sbefifo_user_read()
826 mutex_lock(&user->file_lock); in sbefifo_user_read()
828 /* Cronus relies on -EAGAIN after a short read */ in sbefifo_user_read()
829 if (user->pending_len == 0) { in sbefifo_user_read()
830 rc = -EAGAIN; in sbefifo_user_read()
833 if (user->pending_len < 8) { in sbefifo_user_read()
834 rc = -EINVAL; in sbefifo_user_read()
837 cmd_len = user->pending_len >> 2; in sbefifo_user_read()
845 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_user_read()
848 sbefifo->timeout_start_rsp_ms = user->read_timeout_ms; in sbefifo_user_read()
849 rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter); in sbefifo_user_read()
850 sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_user_read()
851 mutex_unlock(&sbefifo->lock); in sbefifo_user_read()
856 rc = len - iov_iter_count(&resp_iter); in sbefifo_user_read()
859 mutex_unlock(&user->file_lock); in sbefifo_user_read()
866 struct sbefifo_user *user = file->private_data; in sbefifo_user_write()
871 return -EINVAL; in sbefifo_user_write()
872 sbefifo = user->sbefifo; in sbefifo_user_write()
874 return -EINVAL; in sbefifo_user_write()
876 return -EINVAL; in sbefifo_user_write()
878 mutex_lock(&user->file_lock); in sbefifo_user_write()
880 /* Can we use the pre-allocate buffer ? If not, allocate */ in sbefifo_user_write()
882 user->pending_cmd = user->cmd_page; in sbefifo_user_write()
884 user->pending_cmd = vmalloc(len); in sbefifo_user_write()
885 if (!user->pending_cmd) { in sbefifo_user_write()
886 rc = -ENOMEM; in sbefifo_user_write()
891 if (copy_from_user(user->pending_cmd, buf, len)) { in sbefifo_user_write()
892 rc = -EFAULT; in sbefifo_user_write()
897 if (len == 4 && be32_to_cpu(*(__be32 *)user->pending_cmd) == in sbefifo_user_write()
901 user->pending_len = 0; in sbefifo_user_write()
904 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_user_write()
907 rc = sbefifo_request_reset(user->sbefifo); in sbefifo_user_write()
908 mutex_unlock(&sbefifo->lock); in sbefifo_user_write()
915 user->pending_len = len; in sbefifo_user_write()
917 if (!user->pending_len) in sbefifo_user_write()
920 mutex_unlock(&user->file_lock); in sbefifo_user_write()
928 struct sbefifo_user *user = file->private_data; in sbefifo_user_release()
931 return -EINVAL; in sbefifo_user_release()
934 free_page((unsigned long)user->cmd_page); in sbefifo_user_release()
942 struct device *dev = &user->sbefifo->dev; in sbefifo_read_timeout()
943 u32 timeout; in sbefifo_read_timeout() local
945 if (get_user(timeout, (__u32 __user *)argp)) in sbefifo_read_timeout()
946 return -EFAULT; in sbefifo_read_timeout()
948 if (timeout == 0) { in sbefifo_read_timeout()
949 user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_read_timeout()
950 dev_dbg(dev, "Timeout reset to %d\n", user->read_timeout_ms); in sbefifo_read_timeout()
954 if (timeout < 10 || timeout > 120) in sbefifo_read_timeout()
955 return -EINVAL; in sbefifo_read_timeout()
957 user->read_timeout_ms = timeout * 1000; /* user timeout is in sec */ in sbefifo_read_timeout()
959 dev_dbg(dev, "Timeout set to %d\n", user->read_timeout_ms); in sbefifo_read_timeout()
964 static long sbefifo_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) in sbefifo_user_ioctl() argument
966 struct sbefifo_user *user = file->private_data; in sbefifo_user_ioctl()
967 int rc = -ENOTTY; in sbefifo_user_ioctl()
970 return -EINVAL; in sbefifo_user_ioctl()
972 mutex_lock(&user->file_lock); in sbefifo_user_ioctl()
973 switch (cmd) { in sbefifo_user_ioctl()
978 mutex_unlock(&user->file_lock); in sbefifo_user_ioctl()
995 put_device(&sbefifo->fsi_dev->dev); in sbefifo_free()
1016 return -ENOMEM; in sbefifo_probe()
1021 return -ENODEV; in sbefifo_probe()
1024 sbefifo->magic = SBEFIFO_MAGIC; in sbefifo_probe()
1025 sbefifo->fsi_dev = fsi_dev; in sbefifo_probe()
1027 mutex_init(&sbefifo->lock); in sbefifo_probe()
1028 sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_probe()
1035 if (rc && rc != -ESHUTDOWN) in sbefifo_probe()
1039 sbefifo->dev.type = &fsi_cdev_type; in sbefifo_probe()
1040 sbefifo->dev.parent = dev; in sbefifo_probe()
1041 sbefifo->dev.release = sbefifo_free; in sbefifo_probe()
1042 device_initialize(&sbefifo->dev); in sbefifo_probe()
1045 rc = fsi_get_new_minor(fsi_dev, fsi_dev_sbefifo, &sbefifo->dev.devt, &didx); in sbefifo_probe()
1049 dev_set_name(&sbefifo->dev, "sbefifo%d", didx); in sbefifo_probe()
1050 cdev_init(&sbefifo->cdev, &sbefifo_fops); in sbefifo_probe()
1051 rc = cdev_device_add(&sbefifo->cdev, &sbefifo->dev); in sbefifo_probe()
1054 rc, dev_name(&sbefifo->dev)); in sbefifo_probe()
1059 for_each_available_child_of_node(dev->of_node, np) { in sbefifo_probe()
1060 snprintf(child_name, sizeof(child_name), "%s-dev%d", in sbefifo_probe()
1061 dev_name(&sbefifo->dev), child_idx++); in sbefifo_probe()
1068 device_create_file(&sbefifo->dev, &dev_attr_timeout); in sbefifo_probe()
1072 fsi_free_minor(sbefifo->dev.devt); in sbefifo_probe()
1074 put_device(&sbefifo->dev); in sbefifo_probe()
1083 if (dev->of_node) in sbefifo_unregister_child()
1084 of_node_clear_flag(dev->of_node, OF_POPULATED); in sbefifo_unregister_child()
1095 device_remove_file(&sbefifo->dev, &dev_attr_timeout); in sbefifo_remove()
1097 mutex_lock(&sbefifo->lock); in sbefifo_remove()
1098 sbefifo->dead = true; in sbefifo_remove()
1099 mutex_unlock(&sbefifo->lock); in sbefifo_remove()
1101 cdev_device_del(&sbefifo->cdev, &sbefifo->dev); in sbefifo_remove()
1102 fsi_free_minor(sbefifo->dev.devt); in sbefifo_remove()
1104 put_device(&sbefifo->dev); in sbefifo_remove()