Joel writes: FSI changes for v5.18 * Improvements in SCOM and OCC drivers for error handling and retries * Addition of tracepoints for initialisation path * API for setting long running SBE FIFO operations * tag 'fsi-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi: fsi: Add trace events in initialization path fsi: sbefifo: Implement FSI_SBEFIFO_READ_TIMEOUT_SECONDS ioctl fsi: sbefifo: Use specified value of start of response timeout fsi: occ: Improve response status checking fsi: scom: Remove retries in indirect scoms fsi: scom: Fix error handling
Unified · Split
| @@ -24,9 +24,6 @@ · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | #include "fsi-master.h" | 25 | #include "fsi-master.h" |
| 26 | 26 | ||
| 27 | #define CREATE_TRACE_POINTS | ||
| 28 | #include <trace/events/fsi.h> | ||
| 29 | |||
| 30 | #define FSI_SLAVE_CONF_NEXT_MASK GENMASK(31, 31) | 27 | #define FSI_SLAVE_CONF_NEXT_MASK GENMASK(31, 31) |
| 31 | #define FSI_SLAVE_CONF_SLOTS_MASK GENMASK(23, 16) | 28 | #define FSI_SLAVE_CONF_SLOTS_MASK GENMASK(23, 16) |
| 32 | #define FSI_SLAVE_CONF_SLOTS_SHIFT 16 | 29 | #define FSI_SLAVE_CONF_SLOTS_SHIFT 16 |
| @@ -95,6 +92,9 @@ struct fsi_slave { · 62 unmodified lines | |||
| 95 | u8 t_echo_delay; | 92 | u8 t_echo_delay; |
| 96 | }; | 93 | }; |
| 97 | 94 | ||
| 95 | #define CREATE_TRACE_POINTS | ||
| 96 | #include <trace/events/fsi.h> | ||
| 97 | |||
| 98 | #define to_fsi_master(d) container_of(d, struct fsi_master, dev) | 98 | #define to_fsi_master(d) container_of(d, struct fsi_master, dev) |
| 99 | #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev) | 99 | #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev) |
| 100 | 100 | ||
| @@ -524,6 +524,8 @@ static int fsi_slave_scan(struct fsi_slave *slave) · 423 unmodified lines | |||
| 524 | dev->addr = engine_addr; | 524 | dev->addr = engine_addr; |
| 525 | dev->size = slots * engine_page_size; | 525 | dev->size = slots * engine_page_size; |
| 526 | 526 | ||
| 527 | trace_fsi_dev_init(dev); | ||
| 528 | |||
| 527 | dev_dbg(&slave->dev, | 529 | dev_dbg(&slave->dev, |
| 528 | "engine[%i]: type %x, version %x, addr %x size %x\n", | 530 | "engine[%i]: type %x, version %x, addr %x size %x\n", |
| 529 | dev->unit, dev->engine_type, version, | 531 | dev->unit, dev->engine_type, version, |
| @@ -1006,6 +1008,7 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id) · 476 unmodified lines | |||
| 1006 | 1008 | ||
| 1007 | crc = crc4(0, cfam_id, 32); | 1009 | crc = crc4(0, cfam_id, 32); |
| 1008 | if (crc) { | 1010 | if (crc) { |
| 1011 | trace_fsi_slave_invalid_cfam(master, link, cfam_id); | ||
| 1009 | dev_warn(&master->dev, "slave %02x:%02x invalid cfam id CRC!\n", | 1012 | dev_warn(&master->dev, "slave %02x:%02x invalid cfam id CRC!\n", |
| 1010 | link, id); | 1013 | link, id); |
| 1011 | return -EIO; | 1014 | return -EIO; |
| @@ -1080,6 +1083,8 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id) · 68 unmodified lines | |||
| 1080 | if (rc) | 1083 | if (rc) |
| 1081 | goto err_free; | 1084 | goto err_free; |
| 1082 | 1085 | ||
| 1086 | trace_fsi_slave_init(slave); | ||
| 1087 | |||
| 1083 | /* Create chardev for userspace access */ | 1088 | /* Create chardev for userspace access */ |
| 1084 | cdev_init(&slave->cdev, &cfam_fops); | 1089 | cdev_init(&slave->cdev, &cfam_fops); |
| 1085 | rc = cdev_device_add(&slave->cdev, &slave->dev); | 1090 | rc = cdev_device_add(&slave->cdev, &slave->dev); |
| @@ -449,11 +449,13 @@ static ssize_t cfam_reset_store(struct device *dev, struct device_attribute *att · 448 unmodified lines | |||
| 449 | { | 449 | { |
| 450 | struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev); | 450 | struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev); |
| 451 | 451 | ||
| 452 | trace_fsi_master_aspeed_cfam_reset(true); | ||
| 452 | mutex_lock(&aspeed->lock); | 453 | mutex_lock(&aspeed->lock); |
| 453 | gpiod_set_value(aspeed->cfam_reset_gpio, 1); | 454 | gpiod_set_value(aspeed->cfam_reset_gpio, 1); |
| 454 | usleep_range(900, 1000); | 455 | usleep_range(900, 1000); |
| 455 | gpiod_set_value(aspeed->cfam_reset_gpio, 0); | 456 | gpiod_set_value(aspeed->cfam_reset_gpio, 0); |
| 456 | mutex_unlock(&aspeed->lock); | 457 | mutex_unlock(&aspeed->lock); |
| 458 | trace_fsi_master_aspeed_cfam_reset(false); | ||
| 457 | 459 | ||
| 458 | return count; | 460 | return count; |
| 459 | } | 461 | } |
| @@ -451,6 +451,14 @@ static int occ_trigger_attn(struct occ *occ) · 450 unmodified lines | |||
| 451 | return rc; | 451 | return rc; |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | static bool fsi_occ_response_not_ready(struct occ_response *resp, u8 seq_no, | ||
| 455 | u8 cmd_type) | ||
| 456 | { | ||
| 457 | return resp->return_status == OCC_RESP_CMD_IN_PRG || | ||
| 458 | resp->return_status == OCC_RESP_CRIT_INIT || | ||
| 459 | resp->seq_no != seq_no || resp->cmd_type != cmd_type; | ||
| 460 | } | ||
| 461 | |||
| 454 | int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, | 462 | int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, |
| 455 | void *response, size_t *resp_len) | 463 | void *response, size_t *resp_len) |
| 456 | { | 464 | { |
| @@ -461,10 +469,11 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, · 4 unmodified lines | |||
| 461 | struct occ_response *resp = response; | 469 | struct occ_response *resp = response; |
| 462 | size_t user_resp_len = *resp_len; | 470 | size_t user_resp_len = *resp_len; |
| 463 | u8 seq_no; | 471 | u8 seq_no; |
| 472 | u8 cmd_type; | ||
| 464 | u16 checksum = 0; | 473 | u16 checksum = 0; |
| 465 | u16 resp_data_length; | 474 | u16 resp_data_length; |
| 466 | const u8 *byte_request = (const u8 *)request; | 475 | const u8 *byte_request = (const u8 *)request; |
| 467 | unsigned long start; | 476 | unsigned long end; |
| 468 | int rc; | 477 | int rc; |
| 469 | size_t i; | 478 | size_t i; |
| 470 | 479 | ||
| @@ -478,6 +487,8 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, · 7 unmodified lines | |||
| 478 | return -EINVAL; | 487 | return -EINVAL; |
| 479 | } | 488 | } |
| 480 | 489 | ||
| 490 | cmd_type = byte_request[1]; | ||
| 491 | |||
| 481 | /* Checksum the request, ignoring first byte (sequence number). */ | 492 | /* Checksum the request, ignoring first byte (sequence number). */ |
| 482 | for (i = 1; i < req_len - 2; ++i) | 493 | for (i = 1; i < req_len - 2; ++i) |
| 483 | checksum += byte_request[i]; | 494 | checksum += byte_request[i]; |
| @@ -509,51 +520,61 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, · 25 unmodified lines | |||
| 509 | if (rc) | 520 | if (rc) |
| 510 | goto done; | 521 | goto done; |
| 511 | 522 | ||
| 512 | /* Read occ response header */ | 523 | end = jiffies + timeout; |
| 513 | start = jiffies; | 524 | while (true) { |
| 514 | do { | 525 | /* Read occ response header */ |
| 515 | rc = occ_getsram(occ, 0, resp, 8); | 526 | rc = occ_getsram(occ, 0, resp, 8); |
| 516 | if (rc) | 527 | if (rc) |
| 517 | goto done; | 528 | goto done; |
| 518 | 529 | ||
| 519 | if (resp->return_status == OCC_RESP_CMD_IN_PRG || | 530 | if (fsi_occ_response_not_ready(resp, seq_no, cmd_type)) { |
| 520 | resp->return_status == OCC_RESP_CRIT_INIT || | 531 | if (time_after(jiffies, end)) { |
| 521 | resp->seq_no != seq_no) { | 532 | dev_err(occ->dev, |
| 522 | rc = -ETIMEDOUT; | 533 | "resp timeout status=%02x seq=%d cmd=%d, our seq=%d cmd=%d\n", |
| 523 | |||
| 524 | if (time_after(jiffies, start + timeout)) { | ||
| 525 | dev_err(occ->dev, "resp timeout status=%02x " | ||
| 526 | "resp seq_no=%d our seq_no=%d\n", | ||
| 527 | resp->return_status, resp->seq_no, | 534 | resp->return_status, resp->seq_no, |
| 528 | seq_no); | 535 | resp->cmd_type, seq_no, cmd_type); |
| 536 | rc = -ETIMEDOUT; | ||
| 529 | goto done; | 537 | goto done; |
| 530 | } | 538 | } |
| 531 | 539 | ||
| 532 | set_current_state(TASK_UNINTERRUPTIBLE); | 540 | set_current_state(TASK_UNINTERRUPTIBLE); |
| 533 | schedule_timeout(wait_time); | 541 | schedule_timeout(wait_time); |
| 534 | } | 542 | } else { |
| 535 | } while (rc); | 543 | /* Extract size of response data */ |
| 536 | 544 | resp_data_length = | |
| 537 | /* Extract size of response data */ | 545 | get_unaligned_be16(&resp->data_length); |
| 538 | resp_data_length = get_unaligned_be16(&resp->data_length); | 546 | |
| 547 | /* | ||
| 548 | * Message size is data length + 5 bytes header + 2 | ||
| 549 | * bytes checksum | ||
| 550 | */ | ||
| 551 | if ((resp_data_length + 7) > user_resp_len) { | ||
| 552 | rc = -EMSGSIZE; | ||
| 553 | goto done; | ||
| 554 | } | ||
| 539 | 555 | ||
| 540 | /* Message size is data length + 5 bytes header + 2 bytes checksum */ | 556 | /* |
| 541 | if ((resp_data_length + 7) > user_resp_len) { | 557 | * Get the entire response including the header again, |
| 542 | rc = -EMSGSIZE; | 558 | * in case it changed |
| 543 | goto done; | 559 | */ |
| 560 | if (resp_data_length > 1) { | ||
| 561 | rc = occ_getsram(occ, 0, resp, | ||
| 562 | resp_data_length + 7); | ||
| 563 | if (rc) | ||
| 564 | goto done; | ||
| 565 | |||
| 566 | if (!fsi_occ_response_not_ready(resp, seq_no, | ||
| 567 | cmd_type)) | ||
| 568 | break; | ||
| 569 | } else { | ||
| 570 | break; | ||
| 571 | } | ||
| 572 | } | ||
| 544 | } | 573 | } |
| 545 | 574 | ||
| 546 | dev_dbg(dev, "resp_status=%02x resp_data_len=%d\n", | 575 | dev_dbg(dev, "resp_status=%02x resp_data_len=%d\n", |
| 547 | resp->return_status, resp_data_length); | 576 | resp->return_status, resp_data_length); |
| 548 | 577 | ||
| 549 | /* Grab the rest */ | ||
| 550 | if (resp_data_length > 1) { | ||
| 551 | /* already got 3 bytes resp, also need 2 bytes checksum */ | ||
| 552 | rc = occ_getsram(occ, 8, &resp->data[3], resp_data_length - 1); | ||
| 553 | if (rc) | ||
| 554 | goto done; | ||
| 555 | } | ||
| 556 | |||
| 557 | occ->client_response_size = resp_data_length + 7; | 578 | occ->client_response_size = resp_data_length + 7; |
| 558 | rc = occ_verify_checksum(occ, resp, resp_data_length); | 579 | rc = occ_verify_checksum(occ, resp, resp_data_length); |
| 559 | 580 | ||
| @@ -598,7 +619,11 @@ static int occ_probe(struct platform_device *pdev) · 38 unmodified lines | |||
| 598 | occ->version = (uintptr_t)of_device_get_match_data(dev); | 619 | occ->version = (uintptr_t)of_device_get_match_data(dev); |
| 599 | occ->dev = dev; | 620 | occ->dev = dev; |
| 600 | occ->sbefifo = dev->parent; | 621 | occ->sbefifo = dev->parent; |
| 601 | occ->sequence_number = 1; | 622 | /* |
| 623 | * Quickly derive a pseudo-random number from jiffies so that | ||
| 624 | * re-probing the driver doesn't accidentally overlap sequence numbers. | ||
| 625 | */ | ||
| 626 | occ->sequence_number = (u8)((jiffies % 0xff) + 1); | ||
| 602 | mutex_init(&occ->occ_lock); | 627 | mutex_init(&occ->occ_lock); |
| 603 | 628 | ||
| 604 | if (dev->of_node) { | 629 | if (dev->of_node) { |
| @@ -32,6 +32,8 @@ · 31 unmodified lines | |||
| 32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
| 33 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
| 34 | 34 | ||
| 35 | #include <uapi/linux/fsi.h> | ||
| 36 | |||
| 35 | /* | 37 | /* |
| 36 | * The SBEFIFO is a pipe-like FSI device for communicating with | 38 | * The SBEFIFO is a pipe-like FSI device for communicating with |
| 37 | * the self boot engine on POWER processors. | 39 | * the self boot engine on POWER processors. |
| @@ -125,6 +127,7 @@ struct sbefifo { · 87 unmodified lines | |||
| 125 | bool dead; | 127 | bool dead; |
| 126 | bool async_ffdc; | 128 | bool async_ffdc; |
| 127 | bool timed_out; | 129 | bool timed_out; |
| 130 | u32 timeout_start_rsp_ms; | ||
| 128 | }; | 131 | }; |
| 129 | 132 | ||
| 130 | struct sbefifo_user { | 133 | struct sbefifo_user { |
| @@ -133,6 +136,7 @@ struct sbefifo_user { · 2 unmodified lines | |||
| 133 | void *cmd_page; | 136 | void *cmd_page; |
| 134 | void *pending_cmd; | 137 | void *pending_cmd; |
| 135 | size_t pending_len; | 138 | size_t pending_len; |
| 139 | u32 read_timeout_ms; | ||
| 136 | }; | 140 | }; |
| 137 | 141 | ||
| 138 | static DEFINE_MUTEX(sbefifo_ffdc_mutex); | 142 | static DEFINE_MUTEX(sbefifo_ffdc_mutex); |
| @@ -549,7 +553,7 @@ static int sbefifo_read_response(struct sbefifo *sbefifo, struct iov_iter *respo · 410 unmodified lines | |||
| 549 | 553 | ||
| 550 | dev_vdbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response)); | 554 | dev_vdbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response)); |
| 551 | 555 | ||
| 552 | timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_RSP); | 556 | timeout = msecs_to_jiffies(sbefifo->timeout_start_rsp_ms); |
| 553 | for (;;) { | 557 | for (;;) { |
| 554 | /* Grab FIFO status (this will handle parity errors) */ | 558 | /* Grab FIFO status (this will handle parity errors) */ |
| 555 | rc = sbefifo_wait(sbefifo, false, &status, timeout); | 559 | rc = sbefifo_wait(sbefifo, false, &status, timeout); |
| @@ -795,6 +799,7 @@ static int sbefifo_user_open(struct inode *inode, struct file *file) · 239 unmodified lines | |||
| 795 | return -ENOMEM; | 799 | return -ENOMEM; |
| 796 | } | 800 | } |
| 797 | mutex_init(&user->file_lock); | 801 | mutex_init(&user->file_lock); |
| 802 | user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; | ||
| 798 | 803 | ||
| 799 | return 0; | 804 | return 0; |
| 800 | } | 805 | } |
| @@ -837,7 +842,9 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf, · 36 unmodified lines | |||
| 837 | rc = mutex_lock_interruptible(&sbefifo->lock); | 842 | rc = mutex_lock_interruptible(&sbefifo->lock); |
| 838 | if (rc) | 843 | if (rc) |
| 839 | goto bail; | 844 | goto bail; |
| 845 | sbefifo->timeout_start_rsp_ms = user->read_timeout_ms; | ||
| 840 | rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter); | 846 | rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter); |
| 847 | sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; | ||
| 841 | mutex_unlock(&sbefifo->lock); | 848 | mutex_unlock(&sbefifo->lock); |
| 842 | if (rc < 0) | 849 | if (rc < 0) |
| 843 | goto bail; | 850 | goto bail; |
| @@ -927,12 +934,55 @@ static int sbefifo_user_release(struct inode *inode, struct file *file) · 83 unmodified lines | |||
| 927 | return 0; | 934 | return 0; |
| 928 | } | 935 | } |
| 929 | 936 | ||
| 937 | static int sbefifo_read_timeout(struct sbefifo_user *user, void __user *argp) | ||
| 938 | { | ||
| 939 | struct device *dev = &user->sbefifo->dev; | ||
| 940 | u32 timeout; | ||
| 941 | |||
| 942 | if (get_user(timeout, (__u32 __user *)argp)) | ||
| 943 | return -EFAULT; | ||
| 944 | |||
| 945 | if (timeout == 0) { | ||
| 946 | user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; | ||
| 947 | dev_dbg(dev, "Timeout reset to %d\n", user->read_timeout_ms); | ||
| 948 | return 0; | ||
| 949 | } | ||
| 950 | |||
| 951 | if (timeout < 10 || timeout > 120) | ||
| 952 | return -EINVAL; | ||
| 953 | |||
| 954 | user->read_timeout_ms = timeout * 1000; /* user timeout is in sec */ | ||
| 955 | |||
| 956 | dev_dbg(dev, "Timeout set to %d\n", user->read_timeout_ms); | ||
| 957 | |||
| 958 | return 0; | ||
| 959 | } | ||
| 960 | |||
| 961 | static long sbefifo_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 962 | { | ||
| 963 | struct sbefifo_user *user = file->private_data; | ||
| 964 | int rc = -ENOTTY; | ||
| 965 | |||
| 966 | if (!user) | ||
| 967 | return -EINVAL; | ||
| 968 | |||
| 969 | mutex_lock(&user->file_lock); | ||
| 970 | switch (cmd) { | ||
| 971 | case FSI_SBEFIFO_READ_TIMEOUT_SECONDS: | ||
| 972 | rc = sbefifo_read_timeout(user, (void __user *)arg); | ||
| 973 | break; | ||
| 974 | } | ||
| 975 | mutex_unlock(&user->file_lock); | ||
| 976 | return rc; | ||
| 977 | } | ||
| 978 | |||
| 930 | static const struct file_operations sbefifo_fops = { | 979 | static const struct file_operations sbefifo_fops = { |
| 931 | .owner = THIS_MODULE, | 980 | .owner = THIS_MODULE, |
| 932 | .open = sbefifo_user_open, | 981 | .open = sbefifo_user_open, |
| 933 | .read = sbefifo_user_read, | 982 | .read = sbefifo_user_read, |
| 934 | .write = sbefifo_user_write, | 983 | .write = sbefifo_user_write, |
| 935 | .release = sbefifo_user_release, | 984 | .release = sbefifo_user_release, |
| 985 | .unlocked_ioctl = sbefifo_user_ioctl, | ||
| 936 | }; | 986 | }; |
| 937 | 987 | ||
| 938 | static void sbefifo_free(struct device *dev) | 988 | static void sbefifo_free(struct device *dev) |
| @@ -972,6 +1022,7 @@ static int sbefifo_probe(struct device *dev) · 33 unmodified lines | |||
| 972 | sbefifo->fsi_dev = fsi_dev; | 1022 | sbefifo->fsi_dev = fsi_dev; |
| 973 | dev_set_drvdata(dev, sbefifo); | 1023 | dev_set_drvdata(dev, sbefifo); |
| 974 | mutex_init(&sbefifo->lock); | 1024 | mutex_init(&sbefifo->lock); |
| 1025 | sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; | ||
| 975 | 1026 | ||
| 976 | /* | 1027 | /* |
| 977 | * Try cleaning up the FIFO. If this fails, we still register the | 1028 | * Try cleaning up the FIFO. If this fails, we still register the |
| @@ -145,7 +145,7 @@ static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value, · 144 unmodified lines | |||
| 145 | uint64_t addr, uint32_t *status) | 145 | uint64_t addr, uint32_t *status) |
| 146 | { | 146 | { |
| 147 | uint64_t ind_data, ind_addr; | 147 | uint64_t ind_data, ind_addr; |
| 148 | int rc, retries, err = 0; | 148 | int rc, err; |
| 149 | 149 | ||
| 150 | if (value & ~XSCOM_DATA_IND_DATA) | 150 | if (value & ~XSCOM_DATA_IND_DATA) |
| 151 | return -EINVAL; | 151 | return -EINVAL; |
| @@ -156,19 +156,14 @@ static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value, · 4 unmodified lines | |||
| 156 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) | 156 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) |
| 157 | return rc; | 157 | return rc; |
| 158 | 158 | ||
| 159 | for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) { | 159 | rc = __get_scom(scom, &ind_data, addr, status); |
| 160 | rc = __get_scom(scom, &ind_data, addr, status); | 160 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) |
| 161 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) | 161 | return rc; |
| 162 | return rc; | ||
| 163 | 162 | ||
| 164 | err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT; | 163 | err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT; |
| 165 | *status = err << SCOM_STATUS_PIB_RESP_SHIFT; | 164 | *status = err << SCOM_STATUS_PIB_RESP_SHIFT; |
| 166 | if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED)) | ||
| 167 | return 0; | ||
| 168 | 165 | ||
| 169 | msleep(1); | 166 | return 0; |
| 170 | } | ||
| 171 | return rc; | ||
| 172 | } | 167 | } |
| 173 | 168 | ||
| 174 | static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value, | 169 | static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value, |
| @@ -188,7 +183,7 @@ static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value, · 13 unmodified lines | |||
| 188 | uint64_t addr, uint32_t *status) | 183 | uint64_t addr, uint32_t *status) |
| 189 | { | 184 | { |
| 190 | uint64_t ind_data, ind_addr; | 185 | uint64_t ind_data, ind_addr; |
| 191 | int rc, retries, err = 0; | 186 | int rc, err; |
| 192 | 187 | ||
| 193 | ind_addr = addr & XSCOM_ADDR_DIRECT_PART; | 188 | ind_addr = addr & XSCOM_ADDR_DIRECT_PART; |
| 194 | ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ; | 189 | ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ; |
| @@ -196,21 +191,15 @@ static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value, · 1 unmodified line | |||
| 196 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) | 191 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) |
| 197 | return rc; | 192 | return rc; |
| 198 | 193 | ||
| 199 | for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) { | 194 | rc = __get_scom(scom, &ind_data, addr, status); |
| 200 | rc = __get_scom(scom, &ind_data, addr, status); | 195 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) |
| 201 | if (rc || (*status & SCOM_STATUS_ANY_ERR)) | 196 | return rc; |
| 202 | return rc; | ||
| 203 | |||
| 204 | err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT; | ||
| 205 | *status = err << SCOM_STATUS_PIB_RESP_SHIFT; | ||
| 206 | *value = ind_data & XSCOM_DATA_IND_DATA; | ||
| 207 | 197 | ||
| 208 | if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED)) | 198 | err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT; |
| 209 | return 0; | 199 | *status = err << SCOM_STATUS_PIB_RESP_SHIFT; |
| 200 | *value = ind_data & XSCOM_DATA_IND_DATA; | ||
| 210 | 201 | ||
| 211 | msleep(1); | 202 | return 0; |
| 212 | } | ||
| 213 | return rc; | ||
| 214 | } | 203 | } |
| 215 | 204 | ||
| 216 | static int raw_put_scom(struct scom_device *scom, uint64_t value, | 205 | static int raw_put_scom(struct scom_device *scom, uint64_t value, |
| @@ -289,7 +278,7 @@ static int put_scom(struct scom_device *scom, uint64_t value, · 72 unmodified lines | |||
| 289 | int rc; | 278 | int rc; |
| 290 | 279 | ||
| 291 | rc = raw_put_scom(scom, value, addr, &status); | 280 | rc = raw_put_scom(scom, value, addr, &status); |
| 292 | if (rc == -ENODEV) | 281 | if (rc) |
| 293 | return rc; | 282 | return rc; |
| 294 | 283 | ||
| 295 | rc = handle_fsi2pib_status(scom, status); | 284 | rc = handle_fsi2pib_status(scom, status); |
| @@ -308,7 +297,7 @@ static int get_scom(struct scom_device *scom, uint64_t *value, · 12 unmodified lines | |||
| 308 | int rc; | 297 | int rc; |
| 309 | 298 | ||
| 310 | rc = raw_get_scom(scom, value, addr, &status); | 299 | rc = raw_get_scom(scom, value, addr, &status); |
| 311 | if (rc == -ENODEV) | 300 | if (rc) |
| 312 | return rc; | 301 | return rc; |
| 313 | 302 | ||
| 314 | rc = handle_fsi2pib_status(scom, status); | 303 | rc = handle_fsi2pib_status(scom, status); |
| @@ -122,6 +122,92 @@ TRACE_EVENT(fsi_master_break, · 121 unmodified lines | |||
| 122 | ) | 122 | ) |
| 123 | ); | 123 | ); |
| 124 | 124 | ||
| 125 | TRACE_EVENT(fsi_slave_init, | ||
| 126 | TP_PROTO(const struct fsi_slave *slave), | ||
| 127 | TP_ARGS(slave), | ||
| 128 | TP_STRUCT__entry( | ||
| 129 | __field(int, master_idx) | ||
| 130 | __field(int, master_n_links) | ||
| 131 | __field(int, idx) | ||
| 132 | __field(int, link) | ||
| 133 | __field(int, chip_id) | ||
| 134 | __field(__u32, cfam_id) | ||
| 135 | __field(__u32, size) | ||
| 136 | ), | ||
| 137 | TP_fast_assign( | ||
| 138 | __entry->master_idx = slave->master->idx; | ||
| 139 | __entry->master_n_links = slave->master->n_links; | ||
| 140 | __entry->idx = slave->cdev_idx; | ||
| 141 | __entry->link = slave->link; | ||
| 142 | __entry->chip_id = slave->chip_id; | ||
| 143 | __entry->cfam_id = slave->cfam_id; | ||
| 144 | __entry->size = slave->size; | ||
| 145 | ), | ||
| 146 | TP_printk("fsi%d: idx:%d link:%d/%d cid:%d cfam:%08x %08x", | ||
| 147 | __entry->master_idx, | ||
| 148 | __entry->idx, | ||
| 149 | __entry->link, | ||
| 150 | __entry->master_n_links, | ||
| 151 | __entry->chip_id, | ||
| 152 | __entry->cfam_id, | ||
| 153 | __entry->size | ||
| 154 | ) | ||
| 155 | ); | ||
| 156 | |||
| 157 | TRACE_EVENT(fsi_slave_invalid_cfam, | ||
| 158 | TP_PROTO(const struct fsi_master *master, int link, uint32_t cfam_id), | ||
| 159 | TP_ARGS(master, link, cfam_id), | ||
| 160 | TP_STRUCT__entry( | ||
| 161 | __field(int, master_idx) | ||
| 162 | __field(int, master_n_links) | ||
| 163 | __field(int, link) | ||
| 164 | __field(__u32, cfam_id) | ||
| 165 | ), | ||
| 166 | TP_fast_assign( | ||
| 167 | __entry->master_idx = master->idx; | ||
| 168 | __entry->master_n_links = master->n_links; | ||
| 169 | __entry->link = link; | ||
| 170 | __entry->cfam_id = cfam_id; | ||
| 171 | ), | ||
| 172 | TP_printk("fsi%d: cfam:%08x link:%d/%d", | ||
| 173 | __entry->master_idx, | ||
| 174 | __entry->cfam_id, | ||
| 175 | __entry->link, | ||
| 176 | __entry->master_n_links | ||
| 177 | ) | ||
| 178 | ); | ||
| 179 | |||
| 180 | TRACE_EVENT(fsi_dev_init, | ||
| 181 | TP_PROTO(const struct fsi_device *dev), | ||
| 182 | TP_ARGS(dev), | ||
| 183 | TP_STRUCT__entry( | ||
| 184 | __field(int, master_idx) | ||
| 185 | __field(int, link) | ||
| 186 | __field(int, type) | ||
| 187 | __field(int, unit) | ||
| 188 | __field(int, version) | ||
| 189 | __field(__u32, addr) | ||
| 190 | __field(__u32, size) | ||
| 191 | ), | ||
| 192 | TP_fast_assign( | ||
| 193 | __entry->master_idx = dev->slave->master->idx; | ||
| 194 | __entry->link = dev->slave->link; | ||
| 195 | __entry->type = dev->engine_type; | ||
| 196 | __entry->unit = dev->unit; | ||
| 197 | __entry->version = dev->version; | ||
| 198 | __entry->addr = dev->addr; | ||
| 199 | __entry->size = dev->size; | ||
| 200 | ), | ||
| 201 | TP_printk("fsi%d: slv%d: t:%02x u:%02x v:%02x %08x@%08x", | ||
| 202 | __entry->master_idx, | ||
| 203 | __entry->link, | ||
| 204 | __entry->type, | ||
| 205 | __entry->unit, | ||
| 206 | __entry->version, | ||
| 207 | __entry->size, | ||
| 208 | __entry->addr | ||
| 209 | ) | ||
| 210 | ); | ||
| 125 | 211 | ||
| 126 | #endif /* _TRACE_FSI_H */ | 212 | #endif /* _TRACE_FSI_H */ |
| 127 | 213 | ||
| @@ -72,6 +72,18 @@ TRACE_EVENT(fsi_master_aspeed_opb_error, · 71 unmodified lines | |||
| 72 | ) | 72 | ) |
| 73 | ); | 73 | ); |
| 74 | 74 | ||
| 75 | TRACE_EVENT(fsi_master_aspeed_cfam_reset, | ||
| 76 | TP_PROTO(bool start), | ||
| 77 | TP_ARGS(start), | ||
| 78 | TP_STRUCT__entry( | ||
| 79 | __field(bool, start) | ||
| 80 | ), | ||
| 81 | TP_fast_assign( | ||
| 82 | __entry->start = start; | ||
| 83 | ), | ||
| 84 | TP_printk("%s", __entry->start ? "start" : "end") | ||
| 85 | ); | ||
| 86 | |||
| 75 | #endif | 87 | #endif |
| 76 | 88 | ||
| 77 | #include <trace/define_trace.h> | 89 | #include <trace/define_trace.h> |
| @@ -55,4 +55,18 @@ struct scom_access { · 54 unmodified lines | |||
| 55 | #define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access) | 55 | #define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access) |
| 56 | #define FSI_SCOM_RESET _IOW('s', 0x03, __u32) | 56 | #define FSI_SCOM_RESET _IOW('s', 0x03, __u32) |
| 57 | 57 | ||
| 58 | /* | ||
| 59 | * /dev/sbefifo* ioctl interface | ||
| 60 | */ | ||
| 61 | |||
| 62 | /** | ||
| 63 | * FSI_SBEFIFO_READ_TIMEOUT sets the read timeout for response from SBE. | ||
| 64 | * | ||
| 65 | * The read timeout is specified in seconds. The minimum value of read | ||
| 66 | * timeout is 10 seconds (default) and the maximum value of read timeout is | ||
| 67 | * 120 seconds. A read timeout of 0 will reset the value to the default of | ||
| 68 | * (10 seconds). | ||
| 69 | */ | ||
| 70 | #define FSI_SBEFIFO_READ_TIMEOUT_SECONDS _IOW('s', 0x00, __u32) | ||
| 71 | |||
| 58 | #endif /* _UAPI_LINUX_FSI_H */ | 72 | #endif /* _UAPI_LINUX_FSI_H */ |