+ tmp = cpp->interface;
+
+ PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x\n", __func__, tmp);
+
+ err = send(sockfd, &tmp, 4, 0);
+ if (err != 4) {
+ RTE_LOG(ERR, PMD, "%s: error writing to socket\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#define NFP_BRIDGE_OP_READ 20
+#define NFP_BRIDGE_OP_WRITE 30
+#define NFP_BRIDGE_OP_IOCTL 40
+
+/*
+ * This is the code to be executed by a service core. The CPP bridge interface
+ * is based on a unix socket and requests usually received by a kernel char
+ * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
+ * can be executed with a wrapper library and LD_LIBRARY being completely
+ * unaware of the CPP bridge performing the NFP kernel char driver for CPP
+ * accesses.
+ */
+static int32_t
+nfp_cpp_bridge_service_func(void *args)
+{
+ struct sockaddr address;
+ struct nfp_cpp *cpp = args;
+ int sockfd, datafd, op, ret;
+
+ unlink("/tmp/nfp_cpp");
+ sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ RTE_LOG(ERR, PMD, "%s: socket creation error. Service failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ memset(&address, 0, sizeof(struct sockaddr));
+
+ address.sa_family = AF_UNIX;
+ strcpy(address.sa_data, "/tmp/nfp_cpp");
+
+ ret = bind(sockfd, (const struct sockaddr *)&address,
+ sizeof(struct sockaddr));
+ if (ret < 0) {
+ RTE_LOG(ERR, PMD, "%s: bind error (%d). Service failed\n",
+ __func__, errno);
+ close(sockfd);
+ return ret;
+ }
+
+ ret = listen(sockfd, 20);
+ if (ret < 0) {
+ RTE_LOG(ERR, PMD, "%s: listen error(%d). Service failed\n",
+ __func__, errno);
+ close(sockfd);
+ return ret;
+ }
+
+ for (;;) {
+ datafd = accept(sockfd, NULL, NULL);
+ if (datafd < 0) {
+ RTE_LOG(ERR, PMD, "%s: accept call error (%d)\n",
+ __func__, errno);
+ RTE_LOG(ERR, PMD, "%s: service failed\n", __func__);
+ close(sockfd);
+ return -EIO;
+ }
+
+ while (1) {
+ ret = recv(datafd, &op, 4, 0);
+ if (ret <= 0) {
+ PMD_CPP_LOG(DEBUG, "%s: socket close\n",
+ __func__);
+ break;
+ }
+
+ PMD_CPP_LOG(DEBUG, "%s: getting op %u\n", __func__, op);
+
+ if (op == NFP_BRIDGE_OP_READ)
+ nfp_cpp_bridge_serve_read(datafd, cpp);
+
+ if (op == NFP_BRIDGE_OP_WRITE)
+ nfp_cpp_bridge_serve_write(datafd, cpp);
+
+ if (op == NFP_BRIDGE_OP_IOCTL)
+ nfp_cpp_bridge_serve_ioctl(datafd, cpp);
+
+ if (op == 0)
+ break;
+ }
+ close(datafd);
+ }
+ close(sockfd);
+
+ return 0;
+}
+
+#define DEFAULT_FW_PATH "/lib/firmware/netronome"
+
+static int
+nfp_fw_upload(struct rte_pci_device *dev, struct nfp_nsp *nsp, char *card)
+{
+ struct nfp_cpp *cpp = nsp->cpp;
+ int fw_f;
+ char *fw_buf;
+ char fw_name[125];
+ char serial[40];
+ struct stat file_stat;
+ off_t fsize, bytes;
+
+ /* Looking for firmware file in order of priority */
+
+ /* First try to find a firmware image specific for this device */
+ snprintf(serial, sizeof(serial),
+ "serial-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
+ cpp->serial[0], cpp->serial[1], cpp->serial[2], cpp->serial[3],
+ cpp->serial[4], cpp->serial[5], cpp->interface >> 8,
+ cpp->interface & 0xff);
+
+ snprintf(fw_name, sizeof(fw_name), "%s/%s.nffw", DEFAULT_FW_PATH,
+ serial);
+
+ PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
+ fw_f = open(fw_name, O_RDONLY);
+ if (fw_f >= 0)
+ goto read_fw;
+
+ /* Then try the PCI name */
+ snprintf(fw_name, sizeof(fw_name), "%s/pci-%s.nffw", DEFAULT_FW_PATH,
+ dev->device.name);
+
+ PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
+ fw_f = open(fw_name, O_RDONLY);
+ if (fw_f >= 0)
+ goto read_fw;
+
+ /* Finally try the card type and media */
+ snprintf(fw_name, sizeof(fw_name), "%s/%s", DEFAULT_FW_PATH, card);
+ PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name);
+ fw_f = open(fw_name, O_RDONLY);
+ if (fw_f < 0) {
+ PMD_DRV_LOG(INFO, "Firmware file %s not found.", fw_name);
+ return -ENOENT;
+ }
+
+read_fw:
+ if (fstat(fw_f, &file_stat) < 0) {
+ PMD_DRV_LOG(INFO, "Firmware file %s size is unknown", fw_name);
+ close(fw_f);
+ return -ENOENT;
+ }
+
+ fsize = file_stat.st_size;
+ PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %" PRIu64 "",
+ fw_name, (uint64_t)fsize);
+
+ fw_buf = malloc((size_t)fsize);
+ if (!fw_buf) {
+ PMD_DRV_LOG(INFO, "malloc failed for fw buffer");
+ close(fw_f);