Ignore:
Timestamp:
Sep 18, 2022, 11:24:34 AM (3 years ago)
Author:
Paul Smedley
Message:

Add some additional functions to minimise upstream patches

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/branches/uniaud32-next/lib32/devres.c

    r720 r745  
    99
    1010#include <linux/device.h>
     11#include <linux/pci.h>
    1112#include <linux/module.h>
    1213#include <linux/slab.h>
     
    310311        return NULL;
    311312}
     313
     314/**
     315 * devres_get - Find devres, if non-existent, add one atomically
     316 * @dev: Device to lookup or add devres for
     317 * @new_res: Pointer to new initialized devres to add if not found
     318 * @match: Match function (optional)
     319 * @match_data: Data for the match function
     320 *
     321 * Find the latest devres of @dev which has the same release function
     322 * as @new_res and for which @match return 1.  If found, @new_res is
     323 * freed; otherwise, @new_res is added atomically.
     324 *
     325 * RETURNS:
     326 * Pointer to found or added devres.
     327 */
     328void * devres_get(struct device *dev, void *new_res,
     329                  dr_match_t match, void *match_data)
     330{
     331        struct devres *new_dr = container_of(new_res, struct devres, data);
     332        struct devres *dr;
     333        unsigned long flags;
     334
     335        spin_lock_irqsave(&dev->devres_lock, flags);
     336        dr = find_dr(dev, new_dr->node.release, match, match_data);
     337        if (!dr) {
     338                add_dr(dev, &new_dr->node);
     339                dr = new_dr;
     340                new_res = NULL;
     341        }
     342        spin_unlock_irqrestore(&dev->devres_lock, flags);
     343        devres_free(new_res);
     344
     345        return dr->data;
     346}
     347EXPORT_SYMBOL_GPL(devres_get);
    312348
    313349/*
     
    472508}
    473509EXPORT_SYMBOL(devm_ioremap);
     510
     511/**
     512 * devm_kvasprintf - Allocate resource managed space and format a string
     513 *                   into that.
     514 * @dev: Device to allocate memory for
     515 * @gfp: the GFP mask used in the devm_kmalloc() call when
     516 *       allocating memory
     517 * @fmt: The printf()-style format string
     518 * @ap: Arguments for the format string
     519 * RETURNS:
     520 * Pointer to allocated string on success, NULL on failure.
     521 */
     522char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
     523                      va_list ap)
     524{
     525        unsigned int len;
     526        char *p;
     527        va_list aq;
     528
     529        va_copy(aq, ap);
     530        len = vsnprintf(NULL, 0, fmt, aq);
     531        va_end(aq);
     532
     533        p = devm_kmalloc(dev, len+1, gfp);
     534        if (!p)
     535                return NULL;
     536
     537        vsnprintf(p, len+1, fmt, ap);
     538
     539        return p;
     540}
     541EXPORT_SYMBOL(devm_kvasprintf);
     542/**
     543 * devm_kasprintf - Allocate resource managed space and format a string
     544 *                  into that.
     545 * @dev: Device to allocate memory for
     546 * @gfp: the GFP mask used in the devm_kmalloc() call when
     547 *       allocating memory
     548 * @fmt: The printf()-style format string
     549 * @...: Arguments for the format string
     550 * RETURNS:
     551 * Pointer to allocated string on success, NULL on failure.
     552 */
     553char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...)
     554{
     555        va_list ap;
     556        char *p;
     557
     558        va_start(ap, fmt);
     559        p = devm_kvasprintf(dev, gfp, fmt, ap);
     560        va_end(ap);
     561
     562        return p;
     563}
     564EXPORT_SYMBOL_GPL(devm_kasprintf);
     565
     566/*
     567 * PCI iomap devres
     568 */
     569#define PCIM_IOMAP_MAX  PCI_STD_NUM_BARS
     570
     571struct pcim_iomap_devres {
     572        void __iomem *table[PCIM_IOMAP_MAX];
     573};
     574
     575static void pcim_iomap_release(struct device *gendev, void *res)
     576{
     577        struct pci_dev *dev = to_pci_dev(gendev);
     578        struct pcim_iomap_devres *this = res;
     579        int i;
     580
     581        for (i = 0; i < PCIM_IOMAP_MAX; i++)
     582                if (this->table[i])
     583                        pci_iounmap(dev, this->table[i]);
     584}
     585
     586/**
     587 * pcim_iomap_table - access iomap allocation table
     588 * @pdev: PCI device to access iomap table for
     589 *
     590 * Access iomap allocation table for @dev.  If iomap table doesn't
     591 * exist and @pdev is managed, it will be allocated.  All iomaps
     592 * recorded in the iomap table are automatically unmapped on driver
     593 * detach.
     594 *
     595 * This function might sleep when the table is first allocated but can
     596 * be safely called without context and guaranteed to succeed once
     597 * allocated.
     598 */
     599void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
     600{
     601        struct pcim_iomap_devres *dr, *new_dr;
     602
     603        dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
     604        if (dr)
     605                return dr->table;
     606
     607        new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
     608        if (!new_dr)
     609                return NULL;
     610        dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
     611        return dr->table;
     612}
     613EXPORT_SYMBOL(pcim_iomap_table);
     614
     615/**
     616 * pcim_iomap - Managed pcim_iomap()
     617 * @pdev: PCI device to iomap for
     618 * @bar: BAR to iomap
     619 * @maxlen: Maximum length of iomap
     620 *
     621 * Managed pci_iomap().  Map is automatically unmapped on driver
     622 * detach.
     623 */
     624void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
     625{
     626        void __iomem **tbl;
     627
     628        BUG_ON(bar >= PCIM_IOMAP_MAX);
     629
     630        tbl = (void __iomem **)pcim_iomap_table(pdev);
     631        if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
     632                return NULL;
     633
     634        tbl[bar] = pci_iomap(pdev, bar, maxlen);
     635        return tbl[bar];
     636}
     637EXPORT_SYMBOL(pcim_iomap);
     638
     639/**
     640 * pcim_iounmap - Managed pci_iounmap()
     641 * @pdev: PCI device to iounmap for
     642 * @addr: Address to unmap
     643 *
     644 * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
     645 */
     646void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
     647{
     648        void __iomem **tbl;
     649        int i;
     650
     651        pci_iounmap(pdev, addr);
     652
     653        tbl = (void __iomem **)pcim_iomap_table(pdev);
     654        BUG_ON(!tbl);
     655
     656        for (i = 0; i < PCIM_IOMAP_MAX; i++)
     657                if (tbl[i] == addr) {
     658                        tbl[i] = NULL;
     659                        return;
     660                }
     661        WARN_ON(1);
     662}
     663EXPORT_SYMBOL(pcim_iounmap);
     664
     665/**
     666 * pcim_iomap_regions - Request and iomap PCI BARs
     667 * @pdev: PCI device to map IO resources for
     668 * @mask: Mask of BARs to request and iomap
     669 * @name: Name used when requesting regions
     670 *
     671 * Request and iomap regions specified by @mask.
     672 */
     673int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
     674{
     675        void __iomem * const *iomap;
     676        int i, rc;
     677
     678        iomap = pcim_iomap_table(pdev);
     679        if (!iomap)
     680                return -ENOMEM;
     681
     682        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
     683                unsigned long len;
     684
     685                if (!(mask & (1 << i)))
     686                        continue;
     687
     688                rc = -EINVAL;
     689                len = pci_resource_len(pdev, i);
     690                if (!len)
     691                        goto err_inval;
     692
     693                rc = pci_request_region(pdev, i, name);
     694                if (rc)
     695                        goto err_inval;
     696
     697                rc = -ENOMEM;
     698                if (!pcim_iomap(pdev, i, 0))
     699                        goto err_region;
     700        }
     701
     702        return 0;
     703
     704 err_region:
     705        pci_release_region(pdev, i);
     706 err_inval:
     707        while (--i >= 0) {
     708                if (!(mask & (1 << i)))
     709                        continue;
     710                pcim_iounmap(pdev, iomap[i]);
     711                pci_release_region(pdev, i);
     712        }
     713
     714        return rc;
     715}
     716EXPORT_SYMBOL(pcim_iomap_regions);
Note: See TracChangeset for help on using the changeset viewer.