Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751108AbdCQHCa (ORCPT ); Fri, 17 Mar 2017 03:02:30 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]:4423 "EHLO dggrg03-dlp.huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1750926AbdCQHC3 (ORCPT ); Fri, 17 Mar 2017 03:02:29 -0400 Subject: Re: [HMM 16/16] mm/hmm/devmem: dummy HMM device for ZONE_DEVICE memory v2 To: =?UTF-8?B?SsOpcsO0bWUgR2xpc3Nl?= , , , References: <1489680335-6594-1-git-send-email-jglisse@redhat.com> <1489680335-6594-17-git-send-email-jglisse@redhat.com> CC: John Hubbard , Naoya Horiguchi , David Nellans , "Evgeny Baskakov" , Mark Hairgrove , Sherry Cheung , Subhash Gutti From: Bob Liu Message-ID: Date: Fri, 17 Mar 2017 14:55:57 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: <1489680335-6594-17-git-send-email-jglisse@redhat.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit X-Originating-IP: [10.142.83.150] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.58CB8897.003F,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 2d6d2f64d1835b658efb84c306d13579 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5399 Lines: 188 Hi Jérôme, On 2017/3/17 0:05, Jérôme Glisse wrote: > This introduce a dummy HMM device class so device driver can use it to > create hmm_device for the sole purpose of registering device memory. May I ask where is the latest dummy HMM device driver? I can only get this one: https://patchwork.kernel.org/patch/4352061/ Thanks, Bob > It is usefull to device driver that want to manage multiple physical > device memory under same struct device umbrella. > > Changed since v1: > - Improve commit message > - Add drvdata parameter to set on struct device > > Signed-off-by: Jérôme Glisse > Signed-off-by: Evgeny Baskakov > Signed-off-by: John Hubbard > Signed-off-by: Mark Hairgrove > Signed-off-by: Sherry Cheung > Signed-off-by: Subhash Gutti > --- > include/linux/hmm.h | 22 +++++++++++- > mm/hmm.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 117 insertions(+), 1 deletion(-) > > diff --git a/include/linux/hmm.h b/include/linux/hmm.h > index 3054ce7..e4e6b36 100644 > --- a/include/linux/hmm.h > +++ b/include/linux/hmm.h > @@ -79,11 +79,11 @@ > > #if IS_ENABLED(CONFIG_HMM) > > +#include > #include > #include > #include > > - > struct hmm; > > /* > @@ -433,6 +433,26 @@ static inline unsigned long hmm_devmem_page_get_drvdata(struct page *page) > > return drvdata[1]; > } > + > + > +/* > + * struct hmm_device - fake device to hang device memory onto > + * > + * @device: device struct > + * @minor: device minor number > + */ > +struct hmm_device { > + struct device device; > + unsigned minor; > +}; > + > +/* > + * Device driver that wants to handle multiple devices memory through a single > + * fake device can use hmm_device to do so. This is purely a helper and it > + * is not needed to make use of any HMM functionality. > + */ > +struct hmm_device *hmm_device_new(void *drvdata); > +void hmm_device_put(struct hmm_device *hmm_device); > #endif /* IS_ENABLED(CONFIG_HMM_DEVMEM) */ > > > diff --git a/mm/hmm.c b/mm/hmm.c > index 019f379..c477bd1 100644 > --- a/mm/hmm.c > +++ b/mm/hmm.c > @@ -24,6 +24,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -1132,4 +1133,99 @@ int hmm_devmem_fault_range(struct hmm_devmem *devmem, > return 0; > } > EXPORT_SYMBOL(hmm_devmem_fault_range); > + > +/* > + * A device driver that wants to handle multiple devices memory through a > + * single fake device can use hmm_device to do so. This is purely a helper > + * and it is not needed to make use of any HMM functionality. > + */ > +#define HMM_DEVICE_MAX 256 > + > +static DECLARE_BITMAP(hmm_device_mask, HMM_DEVICE_MAX); > +static DEFINE_SPINLOCK(hmm_device_lock); > +static struct class *hmm_device_class; > +static dev_t hmm_device_devt; > + > +static void hmm_device_release(struct device *device) > +{ > + struct hmm_device *hmm_device; > + > + hmm_device = container_of(device, struct hmm_device, device); > + spin_lock(&hmm_device_lock); > + clear_bit(hmm_device->minor, hmm_device_mask); > + spin_unlock(&hmm_device_lock); > + > + kfree(hmm_device); > +} > + > +struct hmm_device *hmm_device_new(void *drvdata) > +{ > + struct hmm_device *hmm_device; > + int ret; > + > + hmm_device = kzalloc(sizeof(*hmm_device), GFP_KERNEL); > + if (!hmm_device) > + return ERR_PTR(-ENOMEM); > + > + ret = alloc_chrdev_region(&hmm_device->device.devt,0,1,"hmm_device"); > + if (ret < 0) { > + kfree(hmm_device); > + return NULL; > + } > + > + spin_lock(&hmm_device_lock); > + hmm_device->minor=find_first_zero_bit(hmm_device_mask,HMM_DEVICE_MAX); > + if (hmm_device->minor >= HMM_DEVICE_MAX) { > + spin_unlock(&hmm_device_lock); > + kfree(hmm_device); > + return NULL; > + } > + set_bit(hmm_device->minor, hmm_device_mask); > + spin_unlock(&hmm_device_lock); > + > + dev_set_name(&hmm_device->device, "hmm_device%d", hmm_device->minor); > + hmm_device->device.devt = MKDEV(MAJOR(hmm_device_devt), > + hmm_device->minor); > + hmm_device->device.release = hmm_device_release; > + dev_set_drvdata(&hmm_device->device, drvdata); > + hmm_device->device.class = hmm_device_class; > + device_initialize(&hmm_device->device); > + > + return hmm_device; > +} > +EXPORT_SYMBOL(hmm_device_new); > + > +void hmm_device_put(struct hmm_device *hmm_device) > +{ > + put_device(&hmm_device->device); > +} > +EXPORT_SYMBOL(hmm_device_put); > + > +static int __init hmm_init(void) > +{ > + int ret; > + > + ret = alloc_chrdev_region(&hmm_device_devt, 0, > + HMM_DEVICE_MAX, > + "hmm_device"); > + if (ret) > + return ret; > + > + hmm_device_class = class_create(THIS_MODULE, "hmm_device"); > + if (IS_ERR(hmm_device_class)) { > + unregister_chrdev_region(hmm_device_devt, HMM_DEVICE_MAX); > + return PTR_ERR(hmm_device_class); > + } > + return 0; > +} > + > +static void __exit hmm_exit(void) > +{ > + unregister_chrdev_region(hmm_device_devt, HMM_DEVICE_MAX); > + class_destroy(hmm_device_class); > +} > + > +module_init(hmm_init); > +module_exit(hmm_exit); > +MODULE_LICENSE("GPL"); > #endif /* IS_ENABLED(CONFIG_HMM_DEVMEM) */ >