From patchwork Thu Aug 24 20:32:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Corbet X-Patchwork-Id: 110949 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp6208079qge; Thu, 24 Aug 2017 13:32:15 -0700 (PDT) X-Received: by 10.99.154.26 with SMTP id o26mr2858637pge.225.1503606735428; Thu, 24 Aug 2017 13:32:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1503606735; cv=none; d=google.com; s=arc-20160816; b=rdVzgYIXXd1XoPGLO5k5dblWgnF8/sVnmJRerMtL5i77kfTASgonwGESte+HO4AXek UWiSo6bsjM9t9jIqWdEBLVk6K6RBT3JfxoKSWUS3IwJR96R07V/w5/Gh8nNj/CF4kodz 9qTwzLZT59zlkB8CnRio4Uuh0Aubpl0fexl8yZoJYl3i5KnE8w165kfswXTDNh5vX6nj B3Ytm9gkB4moVuedI0X0MqJpEzdD95KJKaeNWOLuDDdQhm0LnGW6EGqM3OGetIdVyaoR oRZdtD/5VacYx8x8VrbjLzAF0jN67MXs+FXfZ7YQApI2bn3oyw/38sT9kqX1v7b7ZZcS B1Hw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :organization:message-id:subject:cc:to:from:date :arc-authentication-results; bh=+L3Cs3WHjG/2THoQv5mJse9poJsygBYXcxqeXXCCGm4=; b=J2+2DokgKBxLg8bfdHmpgGHLW66npjkaWjhjfyXWtjTQs8MxpUM/Y3AuxDjJBRlnqu ntxtshaIW3d3dzhjBZPLHdYa6vNIiMp4IiK1VNGwS8WYOv1yAJMZQg92aXj2IW7qzDCI DHr1xe+jRgEv9FxgeO6J92eYOrww+52PC/8UTw3KsTi6roIhbTpUWbSseQO96rm0/W6g YjNg5XshhFIZB2/S/BfCA/GyoKdQwWo6BnnuuLQZFV3itLAHD929yYwqkyH0LXZC/Qa0 diWcsyaJbusrktHtJM6joiLMGTsviR/egjNgZ7f3U49iOrxHIfT3PSuz3gAoqJl/LOMv brRQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a8si3314718pgn.223.2017.08.24.13.32.14; Thu, 24 Aug 2017 13:32:15 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753710AbdHXUcL (ORCPT + 26 others); Thu, 24 Aug 2017 16:32:11 -0400 Received: from ms.lwn.net ([45.79.88.28]:47518 "EHLO ms.lwn.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753041AbdHXUcJ (ORCPT ); Thu, 24 Aug 2017 16:32:09 -0400 Received: from lwn.net (localhost [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ms.lwn.net (Postfix) with ESMTPSA id E6A9A2D0; Thu, 24 Aug 2017 20:32:08 +0000 (UTC) Date: Thu, 24 Aug 2017 14:32:08 -0600 From: Jonathan Corbet To: linux-doc@vger.kernel.org Cc: LKML Subject: [PATCH] doc: Add documentation for the genalloc subsystem Message-ID: <20170824143208.0401f561@lwn.net> Organization: LWN.net MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Genalloc/genpool has kerneldoc comments, but nothing has ever been pulled into the docs themselves. Here's a first attempt, repurposed from an article I wrote at https://lwn.net/Articles/729653/. Signed-off-by: Jonathan Corbet --- Documentation/core-api/genalloc.rst | 144 ++++++++++++++++++++++++++++++++++++ Documentation/core-api/index.rst | 1 + 2 files changed, 145 insertions(+) create mode 100644 Documentation/core-api/genalloc.rst -- 2.13.4 diff --git a/Documentation/core-api/genalloc.rst b/Documentation/core-api/genalloc.rst new file mode 100644 index 000000000000..6981fd627ccd --- /dev/null +++ b/Documentation/core-api/genalloc.rst @@ -0,0 +1,144 @@ +The genalloc/genpool subsystem +============================== + +There are a number of memory-allocation subsystems in the kernel, each +aimed at a specific need. Sometimes, however, a kernel developer needs to +implement a new allocator for a specific range of special-purpose memory; +often that memory is located on a device somewhere. The author of the +driver for that device can certainly write a little allocator to get the +job done, but that is the way to fill the kernel with dozens of poorly +tested allocators. Back in 2005, Jes Sorensen lifted one of those +allocators from the sym53c8xx_2 driver and posted_ it as a generic module +for the creation of ad hoc memory allocators. This code was merged +for the 2.6.13 release; it has been modified considerably since then. + +.. _posted https://lwn.net/Articles/125842/ + +Code using this allocator should include . The action +begins with the creation of a pool using one of: + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_create + +.. kernel-doc:: lib/genalloc.c + :functions: devm_gen_pool_create + +A call to :c:func:`gen_pool_create` will create a pool. The granularity of +allocations is set with min_alloc_order; it is a log-base-2 number like +those used by the page allocator, but it refers to bytes rather than pages. +So, if min_alloc_order is passed as 3, then all allocations will be a +multiple of eight bytes. Increasing min_alloc_order decreases the memory +required to track the memory in the pool. The nid parameter specifies +which NUMA node should be used for the allocation of the housekeeping +structures; it can be -1 if the caller doesn't care. + +The "managed" interface :c:func:`devm_gen_pool_create` ties the pool to a +specific device. Among other things, it will automatically clean up the +pool when the given device is destroyed. + +A pool is shut down with: + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_destroy + +It's worth noting that, if there are still allocations outstanding from the +given pool, this function will take the rather extreme step of invoking +BUG(), crashing the entire system. You have been warned. + +A freshly created pool has no memory to allocate. It is fairly useless in +that state, so one of the first orders of business is usually to add memory +to the pool. That can be done with one of: + +.. kernel-doc:: include/linux/genalloc.h + :functions: gen_pool_add + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_add_virt + +A call to :c:func:`gen_pool_add` will place the size bytes of memory +starting at addr (in the kernel's virtual address space) into the given +pool, once again using nid as the node ID for ancillary memory allocations. +The :c:func:`gen_pool_add_virt` variant associates an explicit physical +address with the memory; this is only necessary if the pool will be used +for DMA allocations. + +The functions for allocating memory from the pool (and putting it back) +are: + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_alloc + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_dma_alloc + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_free + +As one would expect, :c:func:`gen_pool_alloc` will allocate size< bytes +from the given pool. The :c:func:`gen_pool_dma_alloc` variant allocates +memory for use with DMA operations, returning the associated physical +address in the space pointed to by dma. This will only work if the memory +was added with :c:func:`gen_pool_add_virt`. Note that this function +departs from the usual genpool pattern of using unsigned long values to +represent kernel addresses; it returns a void * instead. + +That all seems relatively simple; indeed, some developers clearly found it +to be too simple. After all, the interface above provides no control over +how the allocation functions choose which specific piece of memory to +return. If that sort of control is needed, the following functions will be +of interest: + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_alloc_algo + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_set_algo + +Allocations with :c:func:`gen_pool_alloc_algo` specify an algorithm to be +used to choose the memory to be allocated; the default algorithm can be set +with :c:func:`gen_pool_set_algo`. The data value is passed to the +algorithm; most ignore it, but it is occasionally needed. One can, +naturally, write a special-purpose algorithm, but there is a fair set +already available: + +- gen_pool_first_fit is a simple first-fit allocator; this is the default + algorithm if none other has been specified. + +- gen_pool_first_fit_align forces the allocation to have a specific + alignment (passed via data in a genpool_data_align structure). + +- gen_pool_first_fit_order_align aligns the allocation to the order of the + size. A 60-byte allocation will thus be 64-byte aligned, for example. + +- gen_pool_best_fit, as one would expect, is a simple best-fit allocator. + +- gen_pool_fixed_alloc allocates at a specific offset (passed in a + genpool_data_fixed structure via the data parameter) within the pool. + If the indicated memory is not available the allocation fails. + +There is a handful of other functions, mostly for purposes like querying +the space available in the pool or iterating through chunks of memory. +Most users, however, should not need much beyond what has been described +above. With luck, wider awareness of this module will help to prevent the +writing of special-purpose memory allocators in the future. + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_virt_to_phys + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_for_each_chunk + +.. kernel-doc:: lib/genalloc.c + :functions: addr_in_gen_pool + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_avail + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_size + +.. kernel-doc:: lib/genalloc.c + :functions: gen_pool_get + +.. kernel-doc:: lib/genalloc.c + :functions: of_gen_pool_get diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index 0606be3a3111..d5bbe035316d 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -20,6 +20,7 @@ Core utilities genericirq flexible-arrays librs + genalloc Interfaces for kernel debugging ===============================