Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

misc: bcm-vk: add ioctl load_image

Add ioctl support to issue load_image operation to VK card.

Co-developed-by: Desmond Yan <desmond.yan@broadcom.com>
Co-developed-by: James Hu <james.hu@broadcom.com>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Desmond Yan <desmond.yan@broadcom.com>
Signed-off-by: James Hu <james.hu@broadcom.com>
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
Link: https://lore.kernel.org/r/20210120175827.14820-8-scott.branden@broadcom.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Scott Branden and committed by
Greg Kroah-Hartman
7367e0ad 22c30607

+98
+3
drivers/misc/bcm-vk/bcm_vk.h
··· 12 12 #include <linux/mutex.h> 13 13 #include <linux/pci.h> 14 14 #include <linux/sched/signal.h> 15 + #include <linux/uaccess.h> 15 16 #include <uapi/linux/misc/bcm_vk.h> 16 17 17 18 #include "bcm_vk_msg.h" ··· 221 220 222 221 struct bcm_vk_dauth_info dauth_info; 223 222 223 + /* mutex to protect the ioctls */ 224 + struct mutex mutex; 224 225 struct miscdevice miscdev; 225 226 int devid; /* dev id allocated */ 226 227
+95
drivers/misc/bcm-vk/bcm_vk_dev.c
··· 10 10 #include <linux/idr.h> 11 11 #include <linux/kref.h> 12 12 #include <linux/module.h> 13 + #include <linux/mutex.h> 13 14 #include <linux/pci.h> 14 15 #include <linux/pci_regs.h> 15 16 #include <uapi/linux/misc/bcm_vk.h> ··· 581 580 } 582 581 } 583 582 583 + static long bcm_vk_load_image(struct bcm_vk *vk, 584 + const struct vk_image __user *arg) 585 + { 586 + struct device *dev = &vk->pdev->dev; 587 + const char *image_name; 588 + struct vk_image image; 589 + u32 next_loadable; 590 + enum soc_idx idx; 591 + int image_idx; 592 + int ret = -EPERM; 593 + 594 + if (copy_from_user(&image, arg, sizeof(image))) 595 + return -EACCES; 596 + 597 + if ((image.type != VK_IMAGE_TYPE_BOOT1) && 598 + (image.type != VK_IMAGE_TYPE_BOOT2)) { 599 + dev_err(dev, "invalid image.type %u\n", image.type); 600 + return ret; 601 + } 602 + 603 + next_loadable = bcm_vk_next_boot_image(vk); 604 + if (next_loadable != image.type) { 605 + dev_err(dev, "Next expected image %u, Loading %u\n", 606 + next_loadable, image.type); 607 + return ret; 608 + } 609 + 610 + /* 611 + * if something is pending download already. This could only happen 612 + * for now when the driver is being loaded, or if someone has issued 613 + * another download command in another shell. 614 + */ 615 + if (test_and_set_bit(BCM_VK_WQ_DWNLD_PEND, vk->wq_offload) != 0) { 616 + dev_err(dev, "Download operation already pending.\n"); 617 + return ret; 618 + } 619 + 620 + image_name = image.filename; 621 + if (image_name[0] == '\0') { 622 + /* Use default image name if NULL */ 623 + idx = get_soc_idx(vk); 624 + if (idx == VK_IDX_INVALID) 625 + goto err_idx; 626 + 627 + /* Image idx starts with boot1 */ 628 + image_idx = image.type - VK_IMAGE_TYPE_BOOT1; 629 + image_name = get_load_fw_name(vk, &image_tab[idx][image_idx]); 630 + if (!image_name) { 631 + dev_err(dev, "No suitable image found for type %d", 632 + image.type); 633 + ret = -ENOENT; 634 + goto err_idx; 635 + } 636 + } else { 637 + /* Ensure filename is NULL terminated */ 638 + image.filename[sizeof(image.filename) - 1] = '\0'; 639 + } 640 + ret = bcm_vk_load_image_by_type(vk, image.type, image_name); 641 + dev_info(dev, "Load %s, ret %d\n", image_name, ret); 642 + err_idx: 643 + clear_bit(BCM_VK_WQ_DWNLD_PEND, vk->wq_offload); 644 + 645 + return ret; 646 + } 647 + 584 648 static void bcm_to_v_reset_doorbell(struct bcm_vk *vk, u32 db_val) 585 649 { 586 650 vkwrite32(vk, db_val, BAR_0, VK_BAR0_RESET_DB_BASE); ··· 702 636 return 0; 703 637 } 704 638 639 + static long bcm_vk_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 640 + { 641 + long ret = -EINVAL; 642 + struct bcm_vk_ctx *ctx = file->private_data; 643 + struct bcm_vk *vk = container_of(ctx->miscdev, struct bcm_vk, miscdev); 644 + void __user *argp = (void __user *)arg; 645 + 646 + dev_dbg(&vk->pdev->dev, 647 + "ioctl, cmd=0x%02x, arg=0x%02lx\n", 648 + cmd, arg); 649 + 650 + mutex_lock(&vk->mutex); 651 + 652 + switch (cmd) { 653 + case VK_IOCTL_LOAD_IMAGE: 654 + ret = bcm_vk_load_image(vk, argp); 655 + break; 656 + 657 + default: 658 + break; 659 + } 660 + 661 + mutex_unlock(&vk->mutex); 662 + 663 + return ret; 664 + } 665 + 705 666 static const struct file_operations bcm_vk_fops = { 706 667 .owner = THIS_MODULE, 707 668 .open = bcm_vk_open, 708 669 .release = bcm_vk_release, 670 + .unlocked_ioctl = bcm_vk_ioctl, 709 671 }; 710 672 711 673 static int bcm_vk_on_panic(struct notifier_block *nb, ··· 764 670 return -ENOMEM; 765 671 766 672 kref_init(&vk->kref); 673 + mutex_init(&vk->mutex); 767 674 768 675 err = pci_enable_device(pdev); 769 676 if (err) {