+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include "ifpga_feature_dev.h"
-
-static u64
-pr_err_handle(struct feature_fme_pr *fme_pr)
-{
- struct feature_fme_pr_status fme_pr_status;
- unsigned long err_code;
- u64 fme_pr_error;
- int i;
-
- fme_pr_status.csr = readq(&fme_pr->ccip_fme_pr_status);
- if (!fme_pr_status.pr_status)
- return 0;
-
- err_code = readq(&fme_pr->ccip_fme_pr_err);
- fme_pr_error = err_code;
-
- for (i = 0; i < PR_MAX_ERR_NUM; i++) {
- if (err_code & (1 << i))
- dev_info(NULL, "%s\n", pr_err_msg[i]);
- }
-
- writeq(fme_pr_error, &fme_pr->ccip_fme_pr_err);
- return fme_pr_error;
-}
-
-static int fme_pr_write_init(struct ifpga_fme_hw *fme_dev,
- struct fpga_pr_info *info)
-{
- struct feature_fme_pr *fme_pr;
- struct feature_fme_pr_ctl fme_pr_ctl;
- struct feature_fme_pr_status fme_pr_status;
-
- fme_pr = get_fme_feature_ioaddr_by_index(fme_dev,
- FME_FEATURE_ID_PR_MGMT);
- if (!fme_pr)
- return -EINVAL;
-
- if (info->flags != FPGA_MGR_PARTIAL_RECONFIG)
- return -EINVAL;
-
- dev_info(fme_dev, "resetting PR before initiated PR\n");
-
- fme_pr_ctl.csr = readq(&fme_pr->ccip_fme_pr_control);
- fme_pr_ctl.pr_reset = 1;
- writeq(fme_pr_ctl.csr, &fme_pr->ccip_fme_pr_control);
-
- fme_pr_ctl.pr_reset_ack = 1;
-
- if (fpga_wait_register_field(pr_reset_ack, fme_pr_ctl,
- &fme_pr->ccip_fme_pr_control,
- PR_WAIT_TIMEOUT, 1)) {
- dev_err(fme_dev, "maximum PR timeout\n");
- return -ETIMEDOUT;
- }
-
- fme_pr_ctl.csr = readq(&fme_pr->ccip_fme_pr_control);
- fme_pr_ctl.pr_reset = 0;
- writeq(fme_pr_ctl.csr, &fme_pr->ccip_fme_pr_control);
-
- dev_info(fme_dev, "waiting for PR resource in HW to be initialized and ready\n");
-
- fme_pr_status.pr_host_status = PR_HOST_STATUS_IDLE;
-
- if (fpga_wait_register_field(pr_host_status, fme_pr_status,
- &fme_pr->ccip_fme_pr_status,
- PR_WAIT_TIMEOUT, 1)) {
- dev_err(fme_dev, "maximum PR timeout\n");
- return -ETIMEDOUT;
- }
-
- dev_info(fme_dev, "check if have any previous PR error\n");
- pr_err_handle(fme_pr);
- return 0;
-}
-
-static int fme_pr_write(struct ifpga_fme_hw *fme_dev,
- int port_id, const char *buf, size_t count,
- struct fpga_pr_info *info)
-{
- struct feature_fme_pr *fme_pr;
- struct feature_fme_pr_ctl fme_pr_ctl;
- struct feature_fme_pr_status fme_pr_status;
- struct feature_fme_pr_data fme_pr_data;
- int delay, pr_credit;
- int ret = 0;
-
- fme_pr = get_fme_feature_ioaddr_by_index(fme_dev,
- FME_FEATURE_ID_PR_MGMT);
- if (!fme_pr)
- return -EINVAL;
-
- dev_info(fme_dev, "set PR port ID and start request\n");
-
- fme_pr_ctl.csr = readq(&fme_pr->ccip_fme_pr_control);
- fme_pr_ctl.pr_regionid = port_id;
- fme_pr_ctl.pr_start_req = 1;
- writeq(fme_pr_ctl.csr, &fme_pr->ccip_fme_pr_control);
-
- dev_info(fme_dev, "pushing data from bitstream to HW\n");
-
- fme_pr_status.csr = readq(&fme_pr->ccip_fme_pr_status);
- pr_credit = fme_pr_status.pr_credit;
-
- while (count > 0) {
- delay = 0;
- while (pr_credit <= 1) {
- if (delay++ > PR_WAIT_TIMEOUT) {
- dev_err(fme_dev, "maximum try\n");
-
- info->pr_err = pr_err_handle(fme_pr);
- return info->pr_err ? -EIO : -ETIMEDOUT;
- }
- udelay(1);
-
- fme_pr_status.csr = readq(&fme_pr->ccip_fme_pr_status);
- pr_credit = fme_pr_status.pr_credit;
- };
-
- if (count >= fme_dev->pr_bandwidth) {
- switch (fme_dev->pr_bandwidth) {
- case 4:
- fme_pr_data.rsvd = 0;
- fme_pr_data.pr_data_raw = *((const u32 *)buf);
- writeq(fme_pr_data.csr,
- &fme_pr->ccip_fme_pr_data);
- break;
- default:
- ret = -EFAULT;
- goto done;
- }
-
- buf += fme_dev->pr_bandwidth;
- count -= fme_dev->pr_bandwidth;
- pr_credit--;
- } else {
- WARN_ON(1);
- ret = -EINVAL;
- goto done;
- }
- }
-
-done:
- return ret;
-}
-
-static int fme_pr_write_complete(struct ifpga_fme_hw *fme_dev,
- struct fpga_pr_info *info)
-{
- struct feature_fme_pr *fme_pr;
- struct feature_fme_pr_ctl fme_pr_ctl;
-
- fme_pr = get_fme_feature_ioaddr_by_index(fme_dev,
- FME_FEATURE_ID_PR_MGMT);
-
- fme_pr_ctl.csr = readq(&fme_pr->ccip_fme_pr_control);
- fme_pr_ctl.pr_push_complete = 1;
- writeq(fme_pr_ctl.csr, &fme_pr->ccip_fme_pr_control);
-
- dev_info(fme_dev, "green bitstream push complete\n");
- dev_info(fme_dev, "waiting for HW to release PR resource\n");
-
- fme_pr_ctl.pr_start_req = 0;
-
- if (fpga_wait_register_field(pr_start_req, fme_pr_ctl,
- &fme_pr->ccip_fme_pr_control,
- PR_WAIT_TIMEOUT, 1)) {
- printf("maximum try.\n");
- return -ETIMEDOUT;
- }
-
- dev_info(fme_dev, "PR operation complete, checking status\n");
- info->pr_err = pr_err_handle(fme_pr);
- if (info->pr_err)
- return -EIO;
-
- dev_info(fme_dev, "PR done successfully\n");
- return 0;
-}
-
-static int fpga_pr_buf_load(struct ifpga_fme_hw *fme_dev,
- struct fpga_pr_info *info, const char *buf,
- size_t count)
-{
- int ret;
-
- info->state = FPGA_PR_STATE_WRITE_INIT;
- ret = fme_pr_write_init(fme_dev, info);
- if (ret) {
- dev_err(fme_dev, "Error preparing FPGA for writing\n");
- info->state = FPGA_PR_STATE_WRITE_INIT_ERR;
- return ret;
- }
-
- /*
- * Write the FPGA image to the FPGA.
- */
- info->state = FPGA_PR_STATE_WRITE;
- ret = fme_pr_write(fme_dev, info->port_id, buf, count, info);
- if (ret) {
- dev_err(fme_dev, "Error while writing image data to FPGA\n");
- info->state = FPGA_PR_STATE_WRITE_ERR;
- return ret;
- }
-
- /*
- * After all the FPGA image has been written, do the device specific
- * steps to finish and set the FPGA into operating mode.
- */
- info->state = FPGA_PR_STATE_WRITE_COMPLETE;
- ret = fme_pr_write_complete(fme_dev, info);
- if (ret) {
- dev_err(fme_dev, "Error after writing image data to FPGA\n");
- info->state = FPGA_PR_STATE_WRITE_COMPLETE_ERR;
- return ret;
- }
- info->state = FPGA_PR_STATE_DONE;
-
- return 0;
-}
-
-static int fme_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
- u64 *status)
-{
- struct feature_fme_header *fme_hdr;
- struct feature_fme_capability fme_capability;
- struct ifpga_fme_hw *fme = &hw->fme;
- struct fpga_pr_info info;
- struct ifpga_port_hw *port;
- int ret = 0;
-
- if (!buffer || size == 0)
- return -EINVAL;
- if (fme->state != IFPGA_FME_IMPLEMENTED)
- return -EINVAL;
-
- /*
- * Padding extra zeros to align PR buffer with PR bandwidth, HW will
- * ignore these zeros automatically.
- */
- size = IFPGA_ALIGN(size, fme->pr_bandwidth);
-
- /* get fme header region */
- fme_hdr = get_fme_feature_ioaddr_by_index(fme,
- FME_FEATURE_ID_HEADER);
- if (!fme_hdr)
- return -EINVAL;
-
- /* check port id */
- fme_capability.csr = readq(&fme_hdr->capability);
- if (port_id >= fme_capability.num_ports) {
- dev_err(fme, "port number more than maximum\n");
- return -EINVAL;
- }
-
- opae_memset(&info, 0, sizeof(struct fpga_pr_info));
- info.flags = FPGA_MGR_PARTIAL_RECONFIG;
- info.port_id = port_id;
-
- spinlock_lock(&fme->lock);
-
- /* get port device by port_id */
- port = &hw->port[port_id];
-
- /* Disable Port before PR */
- fpga_port_disable(port);
-
- ret = fpga_pr_buf_load(fme, &info, (void *)buffer, size);
-
- *status = info.pr_err;
-
- /* Re-enable Port after PR finished */
- fpga_port_enable(port);
- spinlock_unlock(&fme->lock);
-
- return ret;
-}
-
-int do_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size, u64 *status)
-{
- struct bts_header *bts_hdr;
- void *buf;
- struct ifpga_port_hw *port;
- int ret;
-
- if (!buffer || size == 0) {
- dev_err(hw, "invalid parameter\n");
- return -EINVAL;
- }
-
- bts_hdr = (struct bts_header *)buffer;
-
- if (is_valid_bts(bts_hdr)) {
- dev_info(hw, "this is a valid bitsteam..\n");
- size -= (sizeof(struct bts_header) +
- bts_hdr->metadata_len);
- buf = (u8 *)buffer + sizeof(struct bts_header) +
- bts_hdr->metadata_len;
- } else {
- return -EINVAL;
- }
-
- /* clean port error before do PR */
- port = &hw->port[port_id];
- ret = port_clear_error(port);
- if (ret) {
- dev_err(hw, "port cannot clear error\n");
- return -EINVAL;
- }
-
- return fme_pr(hw, port_id, buf, size, status);
-}
-
-static int fme_pr_mgmt_init(struct ifpga_feature *feature)
-{
- struct feature_fme_pr *fme_pr;
- struct feature_header fme_pr_header;
- struct ifpga_fme_hw *fme;
-
- dev_info(NULL, "FME PR MGMT Init.\n");
-
- fme = (struct ifpga_fme_hw *)feature->parent;
-
- fme_pr = (struct feature_fme_pr *)feature->addr;
-
- fme_pr_header.csr = readq(&fme_pr->header);
- if (fme_pr_header.revision == 2) {
- dev_info(NULL, "using 512-bit PR\n");
- fme->pr_bandwidth = 64;
- } else {
- dev_info(NULL, "using 32-bit PR\n");
- fme->pr_bandwidth = 4;
- }
-
- return 0;
-}
-
-static void fme_pr_mgmt_uinit(struct ifpga_feature *feature)
-{
- UNUSED(feature);
-
- dev_info(NULL, "FME PR MGMT UInit.\n");
-}
-
-struct ifpga_feature_ops fme_pr_mgmt_ops = {
- .init = fme_pr_mgmt_init,
- .uinit = fme_pr_mgmt_uinit,
-};