> -----Original Message----- > From: Gerd Hoffmann [mailto:kraxel@xxxxxxxxxx] > Sent: Friday, February 21, 2014 12:57 AM > To: linux-fbdev@xxxxxxxxxxxxxxx > Cc: linux-kernel@xxxxxxxxxxxxxxx; gregkh@xxxxxxxxxxxxxxxxxxx; KY Srinivasan; > Haiyang Zhang; jasowang@xxxxxxxxxx; Gerd Hoffmann; Jean-Christophe > Plagniol-Villard; Tomi Valkeinen; open list:Hyper-V CORE AND... > Subject: [PATCH 4/4] hyperv-fb: add support for generation 2 virtual machines. > > UEFI-based generation 2 virtual machines support vmbus devices only. > There is no pci bus. Thus they use a different mechanism for the > graphics framebuffer: Instead of using the vga pci bar a chunk of > memory muct be allocated from the hyperv mmio region declared using > APCI. This patch implements support for it. > > Based on a patch by Haiyang Zhang <haiyangz@xxxxxxxxxxxxx> > > Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx> > --- > drivers/video/hyperv_fb.c | 86 +++++++++++++++++++++++++++++++++------- > ------- > 1 file changed, 60 insertions(+), 26 deletions(-) > > diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c > index 130708f..f956cd9 100644 > --- a/drivers/video/hyperv_fb.c > +++ b/drivers/video/hyperv_fb.c > @@ -42,6 +42,7 @@ > #include <linux/completion.h> > #include <linux/fb.h> > #include <linux/pci.h> > +#include <linux/efi.h> > > #include <linux/hyperv.h> > > @@ -212,6 +213,7 @@ struct synthvid_msg { > > struct hvfb_par { > struct fb_info *info; > + struct resource mem; > bool fb_ready; /* fb device is ready */ > struct completion wait; > u32 synthvid_version; > @@ -460,13 +462,13 @@ static int synthvid_connect_vsp(struct hv_device > *hdev) > goto error; > } > > - if (par->synthvid_version == SYNTHVID_VERSION_WIN7) { > + if (par->synthvid_version == SYNTHVID_VERSION_WIN7) > screen_depth = SYNTHVID_DEPTH_WIN7; > - screen_fb_size = SYNTHVID_FB_SIZE_WIN7; > - } else { > + else > screen_depth = SYNTHVID_DEPTH_WIN8; > - screen_fb_size = SYNTHVID_FB_SIZE_WIN8; > - } > + > + screen_fb_size = hdev->channel->offermsg.offer. > + mmio_megabytes * 1024 * 1024; > > return 0; > > @@ -627,26 +629,46 @@ static void hvfb_get_option(struct fb_info *info) > /* Get framebuffer memory from Hyper-V video pci space */ > static int hvfb_getmem(struct fb_info *info) > { > - struct pci_dev *pdev; > - ulong fb_phys; > + struct hvfb_par *par = info->par; > + struct pci_dev *pdev = NULL; > void __iomem *fb_virt; > + bool gen2vm = efi_enabled(EFI_BOOT); Gerd, efi_enabled() returns an int and not a bool. That is the fix that Haiyang made last night. K. Y > + int ret; > > - pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, > + par->mem.name = "hyperv_fb"; > + par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY; > + if (gen2vm) { > + ret = allocate_resource(&hyperv_mmio, &par->mem, > + screen_fb_size, > + 0, -1, > + screen_fb_size, > + NULL, NULL); > + if (ret != 0) { > + pr_err("Unable to allocate framebuffer memory\n"); > + return -ENODEV; > + } > + } else { > + pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, > PCI_DEVICE_ID_HYPERV_VIDEO, NULL); > - if (!pdev) { > - pr_err("Unable to find PCI Hyper-V video\n"); > - return -ENODEV; > - } > + if (!pdev) { > + pr_err("Unable to find PCI Hyper-V video\n"); > + return -ENODEV; > + } > > - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || > - pci_resource_len(pdev, 0) < screen_fb_size) > - goto err1; > + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || > + pci_resource_len(pdev, 0) < screen_fb_size) > + goto err1; > > - fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1; > - if (!request_mem_region(fb_phys, screen_fb_size, > KBUILD_MODNAME)) > - goto err1; > + par->mem.end = pci_resource_end(pdev, 0); > + par->mem.start = par->mem.end - screen_fb_size + 1; > + ret = request_resource(&pdev->resource[0], &par->mem); > + if (ret != 0) { > + pr_err("Unable to request framebuffer memory\n"); > + return -ENODEV; > + } > + } > > - fb_virt = ioremap(fb_phys, screen_fb_size); > + fb_virt = ioremap(par->mem.start, screen_fb_size); > if (!fb_virt) > goto err2; > > @@ -654,30 +676,42 @@ static int hvfb_getmem(struct fb_info *info) > if (!info->apertures) > goto err3; > > - info->apertures->ranges[0].base = pci_resource_start(pdev, 0); > - info->apertures->ranges[0].size = pci_resource_len(pdev, 0); > - info->fix.smem_start = fb_phys; > + if (gen2vm) { > + info->apertures->ranges[0].base = screen_info.lfb_base; > + info->apertures->ranges[0].size = screen_info.lfb_size; > + } else { > + info->apertures->ranges[0].base = pci_resource_start(pdev, 0); > + info->apertures->ranges[0].size = pci_resource_len(pdev, 0); > + } > + > + info->fix.smem_start = par->mem.start; > info->fix.smem_len = screen_fb_size; > info->screen_base = fb_virt; > info->screen_size = screen_fb_size; > > - pci_dev_put(pdev); > + if (!gen2vm) > + pci_dev_put(pdev); > + > return 0; > > err3: > iounmap(fb_virt); > err2: > - release_mem_region(fb_phys, screen_fb_size); > + release_resource(&par->mem); > err1: > - pci_dev_put(pdev); > + if (!gen2vm) > + pci_dev_put(pdev); > + > return -ENOMEM; > } > > /* Release the framebuffer */ > static void hvfb_putmem(struct fb_info *info) > { > + struct hvfb_par *par = info->par; > + > iounmap(info->screen_base); > - release_mem_region(info->fix.smem_start, screen_fb_size); > + release_resource(&par->mem); > } > > > -- > 1.8.3.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel