root/drivers/misc/habanalabs/firmware_if.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hl_fw_push_fw_to_device
  2. hl_fw_send_pci_access_msg
  3. hl_fw_send_cpu_message
  4. hl_fw_test_cpu_queue
  5. hl_fw_cpu_accessible_dma_pool_alloc
  6. hl_fw_cpu_accessible_dma_pool_free
  7. hl_fw_send_heartbeat
  8. hl_fw_armcp_info_get
  9. hl_fw_get_eeprom_data

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 /*
   4  * Copyright 2016-2019 HabanaLabs, Ltd.
   5  * All Rights Reserved.
   6  */
   7 
   8 #include "habanalabs.h"
   9 
  10 #include <linux/firmware.h>
  11 #include <linux/genalloc.h>
  12 #include <linux/io-64-nonatomic-lo-hi.h>
  13 
  14 /**
  15  * hl_fw_push_fw_to_device() - Push FW code to device.
  16  * @hdev: pointer to hl_device structure.
  17  *
  18  * Copy fw code from firmware file to device memory.
  19  *
  20  * Return: 0 on success, non-zero for failure.
  21  */
  22 int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
  23                                 void __iomem *dst)
  24 {
  25         const struct firmware *fw;
  26         const u64 *fw_data;
  27         size_t fw_size;
  28         int rc;
  29 
  30         rc = request_firmware(&fw, fw_name, hdev->dev);
  31         if (rc) {
  32                 dev_err(hdev->dev, "Firmware file %s is not found!\n", fw_name);
  33                 goto out;
  34         }
  35 
  36         fw_size = fw->size;
  37         if ((fw_size % 4) != 0) {
  38                 dev_err(hdev->dev, "Illegal %s firmware size %zu\n",
  39                         fw_name, fw_size);
  40                 rc = -EINVAL;
  41                 goto out;
  42         }
  43 
  44         dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
  45 
  46         fw_data = (const u64 *) fw->data;
  47 
  48         memcpy_toio(dst, fw_data, fw_size);
  49 
  50 out:
  51         release_firmware(fw);
  52         return rc;
  53 }
  54 
  55 int hl_fw_send_pci_access_msg(struct hl_device *hdev, u32 opcode)
  56 {
  57         struct armcp_packet pkt = {};
  58 
  59         pkt.ctl = cpu_to_le32(opcode << ARMCP_PKT_CTL_OPCODE_SHIFT);
  60 
  61         return hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt,
  62                                 sizeof(pkt), HL_DEVICE_TIMEOUT_USEC, NULL);
  63 }
  64 
  65 int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
  66                                 u16 len, u32 timeout, long *result)
  67 {
  68         struct armcp_packet *pkt;
  69         dma_addr_t pkt_dma_addr;
  70         u32 tmp;
  71         int rc = 0;
  72 
  73         pkt = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, len,
  74                                                                 &pkt_dma_addr);
  75         if (!pkt) {
  76                 dev_err(hdev->dev,
  77                         "Failed to allocate DMA memory for packet to CPU\n");
  78                 return -ENOMEM;
  79         }
  80 
  81         memcpy(pkt, msg, len);
  82 
  83         mutex_lock(&hdev->send_cpu_message_lock);
  84 
  85         if (hdev->disabled)
  86                 goto out;
  87 
  88         if (hdev->device_cpu_disabled) {
  89                 rc = -EIO;
  90                 goto out;
  91         }
  92 
  93         rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, len, pkt_dma_addr);
  94         if (rc) {
  95                 dev_err(hdev->dev, "Failed to send CB on CPU PQ (%d)\n", rc);
  96                 goto out;
  97         }
  98 
  99         rc = hl_poll_timeout_memory(hdev, &pkt->fence, tmp,
 100                                 (tmp == ARMCP_PACKET_FENCE_VAL), 1000,
 101                                 timeout, true);
 102 
 103         hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
 104 
 105         if (rc == -ETIMEDOUT) {
 106                 dev_err(hdev->dev, "Device CPU packet timeout (0x%x)\n", tmp);
 107                 hdev->device_cpu_disabled = true;
 108                 goto out;
 109         }
 110 
 111         tmp = le32_to_cpu(pkt->ctl);
 112 
 113         rc = (tmp & ARMCP_PKT_CTL_RC_MASK) >> ARMCP_PKT_CTL_RC_SHIFT;
 114         if (rc) {
 115                 dev_err(hdev->dev, "F/W ERROR %d for CPU packet %d\n",
 116                         rc,
 117                         (tmp & ARMCP_PKT_CTL_OPCODE_MASK)
 118                                                 >> ARMCP_PKT_CTL_OPCODE_SHIFT);
 119                 rc = -EIO;
 120         } else if (result) {
 121                 *result = (long) le64_to_cpu(pkt->result);
 122         }
 123 
 124 out:
 125         mutex_unlock(&hdev->send_cpu_message_lock);
 126 
 127         hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, len, pkt);
 128 
 129         return rc;
 130 }
 131 
 132 int hl_fw_test_cpu_queue(struct hl_device *hdev)
 133 {
 134         struct armcp_packet test_pkt = {};
 135         long result;
 136         int rc;
 137 
 138         test_pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEST <<
 139                                         ARMCP_PKT_CTL_OPCODE_SHIFT);
 140         test_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
 141 
 142         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &test_pkt,
 143                         sizeof(test_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
 144 
 145         if (!rc) {
 146                 if (result == ARMCP_PACKET_FENCE_VAL)
 147                         dev_info(hdev->dev,
 148                                 "queue test on CPU queue succeeded\n");
 149                 else
 150                         dev_err(hdev->dev,
 151                                 "CPU queue test failed (0x%08lX)\n", result);
 152         } else {
 153                 dev_err(hdev->dev, "CPU queue test failed, error %d\n", rc);
 154         }
 155 
 156         return rc;
 157 }
 158 
 159 void *hl_fw_cpu_accessible_dma_pool_alloc(struct hl_device *hdev, size_t size,
 160                                                 dma_addr_t *dma_handle)
 161 {
 162         u64 kernel_addr;
 163 
 164         kernel_addr = gen_pool_alloc(hdev->cpu_accessible_dma_pool, size);
 165 
 166         *dma_handle = hdev->cpu_accessible_dma_address +
 167                 (kernel_addr - (u64) (uintptr_t) hdev->cpu_accessible_dma_mem);
 168 
 169         return (void *) (uintptr_t) kernel_addr;
 170 }
 171 
 172 void hl_fw_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size,
 173                                         void *vaddr)
 174 {
 175         gen_pool_free(hdev->cpu_accessible_dma_pool, (u64) (uintptr_t) vaddr,
 176                         size);
 177 }
 178 
 179 int hl_fw_send_heartbeat(struct hl_device *hdev)
 180 {
 181         struct armcp_packet hb_pkt = {};
 182         long result;
 183         int rc;
 184 
 185         hb_pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEST <<
 186                                         ARMCP_PKT_CTL_OPCODE_SHIFT);
 187         hb_pkt.value = cpu_to_le64(ARMCP_PACKET_FENCE_VAL);
 188 
 189         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &hb_pkt,
 190                         sizeof(hb_pkt), HL_DEVICE_TIMEOUT_USEC, &result);
 191 
 192         if ((rc) || (result != ARMCP_PACKET_FENCE_VAL))
 193                 rc = -EIO;
 194 
 195         return rc;
 196 }
 197 
 198 int hl_fw_armcp_info_get(struct hl_device *hdev)
 199 {
 200         struct asic_fixed_properties *prop = &hdev->asic_prop;
 201         struct armcp_packet pkt = {};
 202         void *armcp_info_cpu_addr;
 203         dma_addr_t armcp_info_dma_addr;
 204         long result;
 205         int rc;
 206 
 207         armcp_info_cpu_addr =
 208                         hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
 209                                         sizeof(struct armcp_info),
 210                                         &armcp_info_dma_addr);
 211         if (!armcp_info_cpu_addr) {
 212                 dev_err(hdev->dev,
 213                         "Failed to allocate DMA memory for ArmCP info packet\n");
 214                 return -ENOMEM;
 215         }
 216 
 217         memset(armcp_info_cpu_addr, 0, sizeof(struct armcp_info));
 218 
 219         pkt.ctl = cpu_to_le32(ARMCP_PACKET_INFO_GET <<
 220                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 221         pkt.addr = cpu_to_le64(armcp_info_dma_addr);
 222         pkt.data_max_size = cpu_to_le32(sizeof(struct armcp_info));
 223 
 224         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 225                                         HL_ARMCP_INFO_TIMEOUT_USEC, &result);
 226         if (rc) {
 227                 dev_err(hdev->dev,
 228                         "Failed to send ArmCP info pkt, error %d\n", rc);
 229                 goto out;
 230         }
 231 
 232         memcpy(&prop->armcp_info, armcp_info_cpu_addr,
 233                         sizeof(prop->armcp_info));
 234 
 235         rc = hl_build_hwmon_channel_info(hdev, prop->armcp_info.sensors);
 236         if (rc) {
 237                 dev_err(hdev->dev,
 238                         "Failed to build hwmon channel info, error %d\n", rc);
 239                 rc = -EFAULT;
 240                 goto out;
 241         }
 242 
 243 out:
 244         hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
 245                         sizeof(struct armcp_info), armcp_info_cpu_addr);
 246 
 247         return rc;
 248 }
 249 
 250 int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size)
 251 {
 252         struct armcp_packet pkt = {};
 253         void *eeprom_info_cpu_addr;
 254         dma_addr_t eeprom_info_dma_addr;
 255         long result;
 256         int rc;
 257 
 258         eeprom_info_cpu_addr =
 259                         hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
 260                                         max_size, &eeprom_info_dma_addr);
 261         if (!eeprom_info_cpu_addr) {
 262                 dev_err(hdev->dev,
 263                         "Failed to allocate DMA memory for ArmCP EEPROM packet\n");
 264                 return -ENOMEM;
 265         }
 266 
 267         memset(eeprom_info_cpu_addr, 0, max_size);
 268 
 269         pkt.ctl = cpu_to_le32(ARMCP_PACKET_EEPROM_DATA_GET <<
 270                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 271         pkt.addr = cpu_to_le64(eeprom_info_dma_addr);
 272         pkt.data_max_size = cpu_to_le32(max_size);
 273 
 274         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 275                         HL_ARMCP_EEPROM_TIMEOUT_USEC, &result);
 276 
 277         if (rc) {
 278                 dev_err(hdev->dev,
 279                         "Failed to send ArmCP EEPROM packet, error %d\n", rc);
 280                 goto out;
 281         }
 282 
 283         /* result contains the actual size */
 284         memcpy(data, eeprom_info_cpu_addr, min((size_t)result, max_size));
 285 
 286 out:
 287         hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, max_size,
 288                         eeprom_info_cpu_addr);
 289 
 290         return rc;
 291 }

/* [<][>][^][v][top][bottom][index][help] */