Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
0004  */
0005 #include <linux/device.h>
0006 #include <linux/sizes.h>
0007 #include <linux/badblocks.h>
0008 #include "nd-core.h"
0009 #include "pmem.h"
0010 #include "pfn.h"
0011 #include "btt.h"
0012 #include "nd.h"
0013 
0014 void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns)
0015 {
0016     struct nd_namespace_common *ndns = *_ndns;
0017     struct nvdimm_bus *nvdimm_bus;
0018 
0019     if (!ndns)
0020         return;
0021 
0022     nvdimm_bus = walk_to_nvdimm_bus(&ndns->dev);
0023     lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
0024     dev_WARN_ONCE(dev, ndns->claim != dev, "%s: invalid claim\n", __func__);
0025     ndns->claim = NULL;
0026     *_ndns = NULL;
0027     put_device(&ndns->dev);
0028 }
0029 
0030 void nd_detach_ndns(struct device *dev,
0031         struct nd_namespace_common **_ndns)
0032 {
0033     struct nd_namespace_common *ndns = *_ndns;
0034 
0035     if (!ndns)
0036         return;
0037     get_device(&ndns->dev);
0038     nvdimm_bus_lock(&ndns->dev);
0039     __nd_detach_ndns(dev, _ndns);
0040     nvdimm_bus_unlock(&ndns->dev);
0041     put_device(&ndns->dev);
0042 }
0043 
0044 bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach,
0045         struct nd_namespace_common **_ndns)
0046 {
0047     struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(&attach->dev);
0048 
0049     if (attach->claim)
0050         return false;
0051     lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
0052     dev_WARN_ONCE(dev, *_ndns, "%s: invalid claim\n", __func__);
0053     attach->claim = dev;
0054     *_ndns = attach;
0055     get_device(&attach->dev);
0056     return true;
0057 }
0058 
0059 bool nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach,
0060         struct nd_namespace_common **_ndns)
0061 {
0062     bool claimed;
0063 
0064     nvdimm_bus_lock(&attach->dev);
0065     claimed = __nd_attach_ndns(dev, attach, _ndns);
0066     nvdimm_bus_unlock(&attach->dev);
0067     return claimed;
0068 }
0069 
0070 static int namespace_match(struct device *dev, void *data)
0071 {
0072     char *name = data;
0073 
0074     return strcmp(name, dev_name(dev)) == 0;
0075 }
0076 
0077 static bool is_idle(struct device *dev, struct nd_namespace_common *ndns)
0078 {
0079     struct nd_region *nd_region = to_nd_region(dev->parent);
0080     struct device *seed = NULL;
0081 
0082     if (is_nd_btt(dev))
0083         seed = nd_region->btt_seed;
0084     else if (is_nd_pfn(dev))
0085         seed = nd_region->pfn_seed;
0086     else if (is_nd_dax(dev))
0087         seed = nd_region->dax_seed;
0088 
0089     if (seed == dev || ndns || dev->driver)
0090         return false;
0091     return true;
0092 }
0093 
0094 struct nd_pfn *to_nd_pfn_safe(struct device *dev)
0095 {
0096     /*
0097      * pfn device attributes are re-used by dax device instances, so we
0098      * need to be careful to correct device-to-nd_pfn conversion.
0099      */
0100     if (is_nd_pfn(dev))
0101         return to_nd_pfn(dev);
0102 
0103     if (is_nd_dax(dev)) {
0104         struct nd_dax *nd_dax = to_nd_dax(dev);
0105 
0106         return &nd_dax->nd_pfn;
0107     }
0108 
0109     WARN_ON(1);
0110     return NULL;
0111 }
0112 
0113 static void nd_detach_and_reset(struct device *dev,
0114         struct nd_namespace_common **_ndns)
0115 {
0116     /* detach the namespace and destroy / reset the device */
0117     __nd_detach_ndns(dev, _ndns);
0118     if (is_idle(dev, *_ndns)) {
0119         nd_device_unregister(dev, ND_ASYNC);
0120     } else if (is_nd_btt(dev)) {
0121         struct nd_btt *nd_btt = to_nd_btt(dev);
0122 
0123         nd_btt->lbasize = 0;
0124         kfree(nd_btt->uuid);
0125         nd_btt->uuid = NULL;
0126     } else if (is_nd_pfn(dev) || is_nd_dax(dev)) {
0127         struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
0128 
0129         kfree(nd_pfn->uuid);
0130         nd_pfn->uuid = NULL;
0131         nd_pfn->mode = PFN_MODE_NONE;
0132     }
0133 }
0134 
0135 ssize_t nd_namespace_store(struct device *dev,
0136         struct nd_namespace_common **_ndns, const char *buf,
0137         size_t len)
0138 {
0139     struct nd_namespace_common *ndns;
0140     struct device *found;
0141     char *name;
0142 
0143     if (dev->driver) {
0144         dev_dbg(dev, "namespace already active\n");
0145         return -EBUSY;
0146     }
0147 
0148     name = kstrndup(buf, len, GFP_KERNEL);
0149     if (!name)
0150         return -ENOMEM;
0151     strim(name);
0152 
0153     if (strncmp(name, "namespace", 9) == 0 || strcmp(name, "") == 0)
0154         /* pass */;
0155     else {
0156         len = -EINVAL;
0157         goto out;
0158     }
0159 
0160     ndns = *_ndns;
0161     if (strcmp(name, "") == 0) {
0162         nd_detach_and_reset(dev, _ndns);
0163         goto out;
0164     } else if (ndns) {
0165         dev_dbg(dev, "namespace already set to: %s\n",
0166                 dev_name(&ndns->dev));
0167         len = -EBUSY;
0168         goto out;
0169     }
0170 
0171     found = device_find_child(dev->parent, name, namespace_match);
0172     if (!found) {
0173         dev_dbg(dev, "'%s' not found under %s\n", name,
0174                 dev_name(dev->parent));
0175         len = -ENODEV;
0176         goto out;
0177     }
0178 
0179     ndns = to_ndns(found);
0180 
0181     switch (ndns->claim_class) {
0182     case NVDIMM_CCLASS_NONE:
0183         break;
0184     case NVDIMM_CCLASS_BTT:
0185     case NVDIMM_CCLASS_BTT2:
0186         if (!is_nd_btt(dev)) {
0187             len = -EBUSY;
0188             goto out_attach;
0189         }
0190         break;
0191     case NVDIMM_CCLASS_PFN:
0192         if (!is_nd_pfn(dev)) {
0193             len = -EBUSY;
0194             goto out_attach;
0195         }
0196         break;
0197     case NVDIMM_CCLASS_DAX:
0198         if (!is_nd_dax(dev)) {
0199             len = -EBUSY;
0200             goto out_attach;
0201         }
0202         break;
0203     default:
0204         len = -EBUSY;
0205         goto out_attach;
0206         break;
0207     }
0208 
0209     if (__nvdimm_namespace_capacity(ndns) < SZ_16M) {
0210         dev_dbg(dev, "%s too small to host\n", name);
0211         len = -ENXIO;
0212         goto out_attach;
0213     }
0214 
0215     WARN_ON_ONCE(!is_nvdimm_bus_locked(dev));
0216     if (!__nd_attach_ndns(dev, ndns, _ndns)) {
0217         dev_dbg(dev, "%s already claimed\n",
0218                 dev_name(&ndns->dev));
0219         len = -EBUSY;
0220     }
0221 
0222  out_attach:
0223     put_device(&ndns->dev); /* from device_find_child */
0224  out:
0225     kfree(name);
0226     return len;
0227 }
0228 
0229 /*
0230  * nd_sb_checksum: compute checksum for a generic info block
0231  *
0232  * Returns a fletcher64 checksum of everything in the given info block
0233  * except the last field (since that's where the checksum lives).
0234  */
0235 u64 nd_sb_checksum(struct nd_gen_sb *nd_gen_sb)
0236 {
0237     u64 sum;
0238     __le64 sum_save;
0239 
0240     BUILD_BUG_ON(sizeof(struct btt_sb) != SZ_4K);
0241     BUILD_BUG_ON(sizeof(struct nd_pfn_sb) != SZ_4K);
0242     BUILD_BUG_ON(sizeof(struct nd_gen_sb) != SZ_4K);
0243 
0244     sum_save = nd_gen_sb->checksum;
0245     nd_gen_sb->checksum = 0;
0246     sum = nd_fletcher64(nd_gen_sb, sizeof(*nd_gen_sb), 1);
0247     nd_gen_sb->checksum = sum_save;
0248     return sum;
0249 }
0250 EXPORT_SYMBOL(nd_sb_checksum);
0251 
0252 static int nsio_rw_bytes(struct nd_namespace_common *ndns,
0253         resource_size_t offset, void *buf, size_t size, int rw,
0254         unsigned long flags)
0255 {
0256     struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
0257     unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
0258     sector_t sector = offset >> 9;
0259     int rc = 0, ret = 0;
0260 
0261     if (unlikely(!size))
0262         return 0;
0263 
0264     if (unlikely(offset + size > nsio->size)) {
0265         dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n");
0266         return -EFAULT;
0267     }
0268 
0269     if (rw == READ) {
0270         if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align)))
0271             return -EIO;
0272         if (copy_mc_to_kernel(buf, nsio->addr + offset, size) != 0)
0273             return -EIO;
0274         return 0;
0275     }
0276 
0277     if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) {
0278         if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)
0279                 && !(flags & NVDIMM_IO_ATOMIC)) {
0280             long cleared;
0281 
0282             might_sleep();
0283             cleared = nvdimm_clear_poison(&ndns->dev,
0284                     nsio->res.start + offset, size);
0285             if (cleared < size)
0286                 rc = -EIO;
0287             if (cleared > 0 && cleared / 512) {
0288                 cleared /= 512;
0289                 badblocks_clear(&nsio->bb, sector, cleared);
0290             }
0291             arch_invalidate_pmem(nsio->addr + offset, size);
0292         } else
0293             rc = -EIO;
0294     }
0295 
0296     memcpy_flushcache(nsio->addr + offset, buf, size);
0297     ret = nvdimm_flush(to_nd_region(ndns->dev.parent), NULL);
0298     if (ret)
0299         rc = ret;
0300 
0301     return rc;
0302 }
0303 
0304 int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio,
0305         resource_size_t size)
0306 {
0307     struct nd_namespace_common *ndns = &nsio->common;
0308     struct range range = {
0309         .start = nsio->res.start,
0310         .end = nsio->res.end,
0311     };
0312 
0313     nsio->size = size;
0314     if (!devm_request_mem_region(dev, range.start, size,
0315                 dev_name(&ndns->dev))) {
0316         dev_warn(dev, "could not reserve region %pR\n", &nsio->res);
0317         return -EBUSY;
0318     }
0319 
0320     ndns->rw_bytes = nsio_rw_bytes;
0321     if (devm_init_badblocks(dev, &nsio->bb))
0322         return -ENOMEM;
0323     nvdimm_badblocks_populate(to_nd_region(ndns->dev.parent), &nsio->bb,
0324             &range);
0325 
0326     nsio->addr = devm_memremap(dev, range.start, size, ARCH_MEMREMAP_PMEM);
0327 
0328     return PTR_ERR_OR_ZERO(nsio->addr);
0329 }
0330 
0331 void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio)
0332 {
0333     struct resource *res = &nsio->res;
0334 
0335     devm_memunmap(dev, nsio->addr);
0336     devm_exit_badblocks(dev, &nsio->bb);
0337     devm_release_mem_region(dev, res->start, nsio->size);
0338 }