From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751253AbdAQMPX (ORCPT ); Tue, 17 Jan 2017 07:15:23 -0500 Received: from mail-sn1nam02on0067.outbound.protection.outlook.com ([104.47.36.67]:26994 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751039AbdAQMPJ (ORCPT ); Tue, 17 Jan 2017 07:15:09 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Tomasz.Nowicki@caviumnetworks.com; Subject: Re: [PATCH v8 06/18] iommu: iommu_get_group_resv_regions To: Eric Auger , , , , , , , , , , References: <1484127714-3263-1-git-send-email-eric.auger@redhat.com> <1484127714-3263-7-git-send-email-eric.auger@redhat.com> CC: , , , , , , , , , , From: Tomasz Nowicki Message-ID: <15053a96-c3c2-69d4-760b-a213f4bff53f@caviumnetworks.com> Date: Tue, 17 Jan 2017 13:14:31 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 Thunderbird/45.5.1 MIME-Version: 1.0 In-Reply-To: <1484127714-3263-7-git-send-email-eric.auger@redhat.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [31.172.191.173] X-ClientProxiedBy: DB5PR09CA0107.eurprd09.prod.outlook.com (10.166.167.33) To CY1PR07MB2167.namprd07.prod.outlook.com (10.164.112.21) X-MS-Office365-Filtering-Correlation-Id: 58693a6f-1b42-4126-32c5-08d43ed26bcf X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:CY1PR07MB2167; X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;3:phawWCrk65YNNjKJG9jHDWI3WfQVnOdnN1giVvyamKYsb+0jFEJi15qnlL5Hw3QnpWeCVBX4V1NvFAZ2tEvSeWUFSvTfoaxsGZUbTcD+gnX0BB3srsmwunwz0jdc+M808fgyKfNIu8/xnI5Z0F9E5VNapXM7NVhhkL5Lhl0/Er3laG9grbhdSvOJxM9hW1HsBJbcUnwaA/S6FmdxvEWwsI31bU4Tq6HuOF1z6vdxvEepPSt9lfw4DApBFDqhmeBeqLjUDhcWfkrZ/QOeqvNL7Q== X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;25:F4geNkrD60FN5WMzt/be/MrhcYwKk70TvQMpDd2ujWJrUChLoLVPqioSBSO9DxcSWb1ud4NFYrJBPFXGGYgMwgKUL61CGmnW0GtgMl5eDWAGvhi33sdeoID93SHibQmEw28yqZoI7exazwW1PoB2TH2U/23GduOtCO5Z0IIuje7HSM7QCyhkam6S35WNVErz4tSY0qSQnXN1MoF/unqR7CBIy/x5XVo8pvvbCZBqE5XlTzgQhDPKl1/p+NgRyicxJWAfL892fvzXIq1HoRyCyHj4SpbdcQ74UDTqxAh9Vi/ZJB7ZVzr3YilX23mT7pGeCpyNDwnmKK+mpiLRoKwnxWoe4Bc7nrLSCwWZrpb97YcB5ThPsBqZp1SBukF1r7TRBH31oWBCe5Ba0tFL1JUXZPaSrPm4UG1zvjp9yROLFX/OqtUJYMX3ZuYorZ6uk8vfQanGZeW8Xq+gb9EyZPraK8bXRcQuxJQAw9TRjMa3IgwrfGjSirsK6nh3fIxtJpYKZb9IpVnKaNqCqdIEpguasv35D6IiZMewNbqbeoQdOETg+QkQnLmiooR7rxNem2AFGgy3vQaUIIfBujPDCWGpVHO1yA9d0mN3rOEbhCoWY+oudvA1AyvYGApNcf+1Faf44Sm2Q77X7B/v8p3g05gtc42XyL+JLLGhKkXqUd2L1xMnHwZCqBi60AMul0+q+7UGyb5+HKxLKxfRGSd4chsvPZV+5oR+dAZVVz2318aYhtkxiF4JdP4XRKxv+JbtF1d7GSQn1dFWVpQ5ecxnp2IAdPlGF8RAC4wwrSDVMVI5ELgPVucJqsWfEumK4+dByNdp X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;31:cB9hKwSGwXcKJNDHKMo/NqTFZvBWPwnUng6dtFPRSlknzs/ew8Nnp+3kqC4ZF5f11nw8c8sNDFRl1fWfWe6ERG/KjrfGbLcQE8hMbCG+VXUg8f2lSWPiyfSof/Wb5FeNRU+FeCQyWwMP+VHyUUDz8mve4xuIpZTS6db5E9HIQnb64Ptgr9+pgjjh1qypm2KRb2hmsSdRMYBK1a3fpe7q3at3SQ8lXFxIjD7kdfM69kdhUGVhE4Nd1pJ2LjTl1o4GI+vZf7GtGNBqieheQABVY6yZtytnSfgRpk0amnSpeIk=;20:JyxeU6jYvHXzIT/Ny+Dmm0IfyirUWo3Mw3abTJnphlf7sL0Ab0BmVfV3ekDv4FU0l57MFLCvXFpfP17skzHncDwhLbrjx5EmcIDuZBFwXtGkLa4vBTA3RQV/GhndPRKdwbqK527IEDEq+uE296XJH/mr4UwF29xjsdNeeNj1PPASneh4sQw9qkgD1y/QXrKJSbydaGos0b1J3/CSPKZq/80kQAlLTXtAzdrw7AO1wfplP8MkLE+ds3tYo6xn5InszJtepUHPUH479ymXZiUcYLF+UY9q96XiOOGEgsgoSMIakAuTJXGOIBKihEr9e4ZBZ9YioFUDXDzVGFAGzTMuGddx0MVoNtss+p/yvajeE2UAP88ZNBZBXwn4GTmVx9oskSGls/ls+cdFY/SDaUt4HM7pk+LnyYUOimCfSTrKPzbQA5OxGXFtAFbOtbiNhHHUY7SAPWm2zbLwcwf+nsnyzGQzovgQ/s/UWxi6WuVEQ/NT3/yyzKrEdDUKFuqg087gX9kCRNDHciYL4eZmqG/vwf5IsMi0FMgxdaQYywAR+iT9sU7WnUGPWIbteHuD4LFXkiDUhUZz7t94TGR1g9IDS+lXZs/cKywayzzI9wR5vfw= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(131327999870524); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6041248)(20161123562025)(20161123555025)(20161123564025)(20161123560025)(6072148);SRVR:CY1PR07MB2167;BCL:0;PCL:0;RULEID:;SRVR:CY1PR07MB2167; X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;4:KNwd1ITfobPkhv0eOFAD6+nO7mRPx8ZDht+NEg1GMyKC3Vd7dlE3SaTzBE5On9lPdRn7tbQ9NhvUc36RxP3Jv2T4xW8c+EitNlJpbkTJd+B/69ll/rswHL7ECkVLzJbYYlHMFWGPZa8MOO1z/WPAj2J3yh+WYSCTJbifUj4JDsctHpc09jtai8PyqentGXvQFRMESko9E5cTY6O+MPNgwu0l/J2UqmuGKtGBPgJo+cJGywsSpso1FE7+OGSA+bEFQH+ogB04Hn/ioGeNl4eNrZ6EIM5bVVfh8/ZYNIVHdrBt3yr0cX820nJor6LYOHr1nJaZDgGAGqDV4E3FnD8Oworh1t8iglgtVOT2eCVz559mEBzM1Qh1cymfMTv9rH75W7fAlR+57zaDKeX/5R3JVp+XGNP/r8qOm01BjDBYxDSlo7QvCmS6kg7M6Y6rl3KdwsExcqBR4qppx7sIWhH0U+VeyksiXLiqpkY8GsgMyM4wDicChB7IIXrQkNpQqRs5vWUwBc4ickQKXzBprsjkTD6hoi/j5RD+5j4yWay3ktc5UO7EvhHHOXWRULfhJt1PMvAsCiceceLVk4Os4vUIIZtx4E0CGVj/RR0m9CIbWejvd4bC7BUcrgC8MPd3K6AQ X-Forefront-PRVS: 01901B3451 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(979002)(6009001)(6049001)(7916002)(39450400003)(199003)(189002)(24454002)(101416001)(68736007)(2201001)(31696002)(5001770100001)(4001350100001)(189998001)(230700001)(77096006)(50466002)(2950100002)(3846002)(92566002)(97736004)(64126003)(6666003)(47776003)(106356001)(6116002)(105586002)(90366009)(5660300001)(65956001)(7416002)(33646002)(36756003)(66066001)(81166006)(8676002)(83506001)(81156014)(39060400001)(38730400001)(6486002)(31686004)(2906002)(25786008)(42186005)(229853002)(5890100001)(305945005)(4326007)(7736002)(76176999)(54356999)(50986999)(23746002)(8656002)(54906002)(30001)(921003)(83996005)(2101003)(1121003)(969003)(989001)(999001)(1009001)(1019001);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR07MB2167;H:[10.0.0.85];FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?Windows-1252?Q?1;CY1PR07MB2167;23:aEba/uBprwtWskmX2MCtYxgAB7WD4Dc9CSW5t?= =?Windows-1252?Q?4smcPx7FuQChR9gcSI2AES38ptLNZ1SZqxYjW0+k8BReQ7n2xYYDsMgd?= =?Windows-1252?Q?luG12oeEAyIAraIVkh33TdzkoaU4yxdaKcWuDmBWi01xb78a7VAno/Ak?= =?Windows-1252?Q?XG6KVl/6/vnmOzTVY39BsaXTUKt7T5lDsiZTRTdkWdKhE3Srh3ALiGmG?= =?Windows-1252?Q?A5FXc36M5EQOaZIoRIymdTptkjQ6hecHM2BO4YV7qu/xIlQNgcMAJT24?= =?Windows-1252?Q?k8Ks6PZjADHQ8dEIhXkc+dcWl1UTBHKzsHNGwgih3T2Nira/HuhHElfd?= =?Windows-1252?Q?auk0xGWTPIV3nYM+/j1bI/fkbQjLuDk/j6dZcYBMvn7LqiNaEszs9LE2?= =?Windows-1252?Q?6h5zrjvaQfga0X1S2qx85IMe05kxuCrNeZg7WVt/r8xWj2/WmmH+4t7G?= =?Windows-1252?Q?C0vBNEuPduCewQWfrLK8vauJx7M9gmYrBJYXTDLhMvH0pepCaO15zqKc?= =?Windows-1252?Q?BpdF4YP1OjsJunZIaIGP5wMzv8CznBLTayRu7AbukpNOPp3zxAg1It8h?= =?Windows-1252?Q?BZDciEbNyH8xEelPWTe/07M4eaO9H+P2HjkCacASXB7lv4wuErT3xyW1?= =?Windows-1252?Q?KsCtNDtFeQKNJTyAFZh6EaDa2DlsYlGyJseLchGEPan+TVzbTvtorrgE?= =?Windows-1252?Q?Bw38K9Fp9RRRIBbz08RuQWk1oaKktVKMRPejGFjDdgHdfKnuZ8xWt0pH?= =?Windows-1252?Q?8C5F3VpLo0Mqr9d8BM6K2Bm5ywQHuU+J4BIMarTQSvppVAvKI8Up0oOQ?= =?Windows-1252?Q?rCSAtdCK7fpCG9ocV1fyFdwBVQ1xUI8/pcnDQHRLgZQBOUjQpv+Dv2Bl?= =?Windows-1252?Q?EhZRp2JDpIMLs8SiS8H/0qEpKAXwtfJaAi50mkFGzxPd8bT/BtOUgeb0?= =?Windows-1252?Q?huGQjlUskW0D/h7sNpuj5LhH0EuupCnOPmG0y9iqHDhkTwmPZDQtyAc6?= =?Windows-1252?Q?jYarXBM5QtcrxFCZLZB/AK/9HSx9by9qyx4CZcJ9fRgBOx3cP0KLFBUQ?= =?Windows-1252?Q?xwjGfikeGzY1+hrOFt+HfMkvsUhvxSXSgz96xbHnwyP5H+dWusHDiKei?= =?Windows-1252?Q?qYu5YCkh4RMQZRhoJOXQ3q++Dwen3DNsnLZElTpfZz9OuqguI9QsxO9T?= =?Windows-1252?Q?KjrlkTFa5pAgsaVXOdGYp7eKqQX2h30MtIM57DUA2wUDrRp8HIgfUNcj?= =?Windows-1252?Q?dWEHYUCSW1+8MG/WczddC2DsuYYPSfkVB3ylbzfUjxoOheAP4rpCmzab?= =?Windows-1252?Q?22hWbn7zankPLLFQVR/Xx0WYUDLgGRcL6zQyEWuJg63tZ+OC+gNrH7FK?= =?Windows-1252?Q?gNSGml/cgKpw3p58QzEPx+FkS8fIcWu3BQqyhhj9O6TeoC01zBjoEEW1?= =?Windows-1252?Q?CFbNSvul+b22xYqyvxLN1ROdRHp8iJW2Wd3RvCFL6lWCY/xKVreEasIn?= =?Windows-1252?Q?h/Ka1Cd7KWkvIsAxbzKs5xvHNG8IfzI1UaxoK490ySiu/ptNc6mCFRGz?= =?Windows-1252?Q?JyAY8ra3AB9wVDHDkDc+UEN6feYp9qZbsyZKfPCnPddHsA1pqwzS0EnE?= =?Windows-1252?Q?iIXgudxj75IGNmq7xUaIa/d/4tTzngstnnrLxiHVR8AmHzlFGsIxe+sA?= =?Windows-1252?Q?NhV8O0v5A=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;6:BlRKOOtWDSJ0IGXFGaUyb7yBB+DSuQXw2gGG0ETcrUwgM6R6WhBBr5pQb0HeQW4BB3k6bDh5R6NDn1Jmh68j8UH2VEK5kg6FsOhEJe7s9djK/4gkfMikoKckrGy2+XR9eBQNwAfUjs5lsjCDbxk8J2EURYYd2nV0DjulqbqVycVPoSnLGD33Ro5WNPCm+pZywsz7w5Ra02INbaAqzNwmWmUa9Z0JzDUvNjr8LmEaP9+jMVc2RHD8jOYbkl0HeaK+14gb+sKrrmFF1iP/Lu5PuAPssca6aCcpteuec2q0Y0WcHaA3eySPBDyTetlvYLE0aGpdqWErUT3jbvWRGHXIF5Lg9u37btarxOKesxdBisKeEtDxJejQyXPzuet5tjSXJjjpWJdJhrLk7WQLzqzBAh2S68JnqUp6j+fPe9f/RGU=;5:hMmm+MUQJ1VV3JbGRCjr7WwGnS5JWvRMH42Gm1deCE3tBqjmkq2q56BLXCpsk8gN2mt3GmBZwo3nJITRzSN7VR1k5756MZcaAMzNAfSSp1YDQXCRBO3QP1JDJyESAhY9PuISAqC16ekX/nLqB6FwoCJRqWYY85cutmoacVYP3mE=;24:bSV5J6eSf6P1cb2mG9W3R9XeNTKKnQKxye3T0q+owBsesuxyQDgMraF+AswSZiu7nqz8NsNZ+ihr5Rd1l6zbyfwybKDgE8g8FbDl70OKcIk= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2167;7:eT6zLDL3JwYSRGR8uG4x7yzwfnB84CrWueszhsLiAPFYxKTlWp+SQClnzA/g6+BYMM2+5Ozjzv50jFixGPglK9Jc9R8tRrdi2nLRVaGAYQ5Y12zg/Mz8k3q6uBu+g1gmqu7pjy+4wAc119DJMLqhQdRvq/w5q2OMJgIRQb3HJhe6YGJSgZZ/p5lB05M5eeMNAs/mgrVczp0CXPNDHHPtGaRwxljLXYl/xaJKrdP0IdHcTUmc+vmVRAMiWBVsMBhNGQWt6LH1sgaHHyQFspr95NoHhkHbI93Qyj8a9Nv9CCisOGVDEMfYZXzCdJX9IZBQAqQbYpMh6j+p7lUp2gPsvk0L23Bxa1NdGXX5HQPCcCopzosBcwVCqrZJpURHTutvuyuRNuSx19E1XJOvkEXupsoxz4RWjrIlmd+1kAOqNoCw5kmJIGJOzJK9h1lGWtelDYPfew4Ea5mpv0aQ5wrFIg== X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Jan 2017 12:14:39.8795 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR07MB2167 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 11.01.2017 10:41, Eric Auger wrote: > Introduce iommu_get_group_resv_regions whose role consists in > enumerating all devices from the group and collecting their > reserved regions. The list is sorted and overlaps between > regions of the same type are handled by merging the regions. > > Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Thanks, Tomasz > > --- > v6 -> v7: > - avoid merge of regions of different type > > v3 -> v4: > - take the iommu_group lock in iommu_get_group_resv_regions > - the list now is sorted and overlaps are checked > > NOTE: > - we do not move list elements from device to group list since > the iommu_put_resv_regions() could not be called. > - at the moment I did not introduce any iommu_put_group_resv_regions > since it simply consists in voiding/freeing the list > --- > drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/iommu.h | 8 +++++ > 2 files changed, 106 insertions(+) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 41c1906..640056b 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) > return sprintf(buf, "%s\n", group->name); > } > > +/** > + * iommu_insert_resv_region - Insert a new region in the > + * list of reserved regions. > + * @new: new region to insert > + * @regions: list of regions > + * > + * The new element is sorted by address with respect to the other > + * regions of the same type. In case it overlaps with another > + * region of the same type, regions are merged. In case it > + * overlaps with another region of different type, regions are > + * not merged. > + */ > +static int iommu_insert_resv_region(struct iommu_resv_region *new, > + struct list_head *regions) > +{ > + struct iommu_resv_region *region; > + phys_addr_t start = new->start; > + phys_addr_t end = new->start + new->length - 1; > + struct list_head *pos = regions->next; > + > + while (pos != regions) { > + struct iommu_resv_region *entry = > + list_entry(pos, struct iommu_resv_region, list); > + phys_addr_t a = entry->start; > + phys_addr_t b = entry->start + entry->length - 1; > + int type = entry->type; > + > + if (end < a) { > + goto insert; > + } else if (start > b) { > + pos = pos->next; > + } else if ((start >= a) && (end <= b)) { > + if (new->type == type) > + goto done; > + else > + pos = pos->next; > + } else { > + if (new->type == type) { > + phys_addr_t new_start = min(a, start); > + phys_addr_t new_end = max(b, end); > + > + list_del(&entry->list); > + entry->start = new_start; > + entry->length = new_end - new_start + 1; > + iommu_insert_resv_region(entry, regions); > + } else { > + pos = pos->next; > + } > + } > + } > +insert: > + region = iommu_alloc_resv_region(new->start, new->length, > + new->prot, new->type); > + if (!region) > + return -ENOMEM; > + > + list_add_tail(®ion->list, pos); > +done: > + return 0; > +} > + > +static int > +iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, > + struct list_head *group_resv_regions) > +{ > + struct iommu_resv_region *entry; > + int ret; > + > + list_for_each_entry(entry, dev_resv_regions, list) { > + ret = iommu_insert_resv_region(entry, group_resv_regions); > + if (ret) > + break; > + } > + return ret; > +} > + > +int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + struct iommu_device *device; > + int ret = 0; > + > + mutex_lock(&group->mutex); > + list_for_each_entry(device, &group->devices, list) { > + struct list_head dev_resv_regions; > + > + INIT_LIST_HEAD(&dev_resv_regions); > + iommu_get_resv_regions(device->dev, &dev_resv_regions); > + ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); > + iommu_put_resv_regions(device->dev, &dev_resv_regions); > + if (ret) > + break; > + } > + mutex_unlock(&group->mutex); > + return ret; > +} > +EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); > + > static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); > > static void iommu_group_release(struct kobject *kobj) > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index f6bb55d3..bec3730 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -246,6 +246,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, > extern int iommu_request_dm_for_dev(struct device *dev); > extern struct iommu_resv_region * > iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); > +extern int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head); > > extern int iommu_attach_group(struct iommu_domain *domain, > struct iommu_group *group); > @@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev, > { > } > > +static inline int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + return -ENODEV; > +} > + > static inline int iommu_request_dm_for_dev(struct device *dev) > { > return -ENODEV; > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tomasz Nowicki Subject: Re: [PATCH v8 06/18] iommu: iommu_get_group_resv_regions Date: Tue, 17 Jan 2017 13:14:31 +0100 Message-ID: <15053a96-c3c2-69d4-760b-a213f4bff53f@caviumnetworks.com> References: <1484127714-3263-1-git-send-email-eric.auger@redhat.com> <1484127714-3263-7-git-send-email-eric.auger@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Cc: drjones-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, punit.agrawal-5wv7dgnIgG8@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, geethasowjanya.akula-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, pranav.sawargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, shankerd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, gpkulkarni-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org To: Eric Auger , , , , , , , , , , Return-path: In-Reply-To: <1484127714-3263-7-git-send-email-eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org List-Id: kvm.vger.kernel.org On 11.01.2017 10:41, Eric Auger wrote: > Introduce iommu_get_group_resv_regions whose role consists in > enumerating all devices from the group and collecting their > reserved regions. The list is sorted and overlaps between > regions of the same type are handled by merging the regions. > > Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Thanks, Tomasz > > --- > v6 -> v7: > - avoid merge of regions of different type > > v3 -> v4: > - take the iommu_group lock in iommu_get_group_resv_regions > - the list now is sorted and overlaps are checked > > NOTE: > - we do not move list elements from device to group list since > the iommu_put_resv_regions() could not be called. > - at the moment I did not introduce any iommu_put_group_resv_regions > since it simply consists in voiding/freeing the list > --- > drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/iommu.h | 8 +++++ > 2 files changed, 106 insertions(+) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 41c1906..640056b 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) > return sprintf(buf, "%s\n", group->name); > } > > +/** > + * iommu_insert_resv_region - Insert a new region in the > + * list of reserved regions. > + * @new: new region to insert > + * @regions: list of regions > + * > + * The new element is sorted by address with respect to the other > + * regions of the same type. In case it overlaps with another > + * region of the same type, regions are merged. In case it > + * overlaps with another region of different type, regions are > + * not merged. > + */ > +static int iommu_insert_resv_region(struct iommu_resv_region *new, > + struct list_head *regions) > +{ > + struct iommu_resv_region *region; > + phys_addr_t start = new->start; > + phys_addr_t end = new->start + new->length - 1; > + struct list_head *pos = regions->next; > + > + while (pos != regions) { > + struct iommu_resv_region *entry = > + list_entry(pos, struct iommu_resv_region, list); > + phys_addr_t a = entry->start; > + phys_addr_t b = entry->start + entry->length - 1; > + int type = entry->type; > + > + if (end < a) { > + goto insert; > + } else if (start > b) { > + pos = pos->next; > + } else if ((start >= a) && (end <= b)) { > + if (new->type == type) > + goto done; > + else > + pos = pos->next; > + } else { > + if (new->type == type) { > + phys_addr_t new_start = min(a, start); > + phys_addr_t new_end = max(b, end); > + > + list_del(&entry->list); > + entry->start = new_start; > + entry->length = new_end - new_start + 1; > + iommu_insert_resv_region(entry, regions); > + } else { > + pos = pos->next; > + } > + } > + } > +insert: > + region = iommu_alloc_resv_region(new->start, new->length, > + new->prot, new->type); > + if (!region) > + return -ENOMEM; > + > + list_add_tail(®ion->list, pos); > +done: > + return 0; > +} > + > +static int > +iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, > + struct list_head *group_resv_regions) > +{ > + struct iommu_resv_region *entry; > + int ret; > + > + list_for_each_entry(entry, dev_resv_regions, list) { > + ret = iommu_insert_resv_region(entry, group_resv_regions); > + if (ret) > + break; > + } > + return ret; > +} > + > +int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + struct iommu_device *device; > + int ret = 0; > + > + mutex_lock(&group->mutex); > + list_for_each_entry(device, &group->devices, list) { > + struct list_head dev_resv_regions; > + > + INIT_LIST_HEAD(&dev_resv_regions); > + iommu_get_resv_regions(device->dev, &dev_resv_regions); > + ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); > + iommu_put_resv_regions(device->dev, &dev_resv_regions); > + if (ret) > + break; > + } > + mutex_unlock(&group->mutex); > + return ret; > +} > +EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); > + > static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); > > static void iommu_group_release(struct kobject *kobj) > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index f6bb55d3..bec3730 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -246,6 +246,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, > extern int iommu_request_dm_for_dev(struct device *dev); > extern struct iommu_resv_region * > iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); > +extern int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head); > > extern int iommu_attach_group(struct iommu_domain *domain, > struct iommu_group *group); > @@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev, > { > } > > +static inline int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + return -ENODEV; > +} > + > static inline int iommu_request_dm_for_dev(struct device *dev) > { > return -ENODEV; > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tomasz Nowicki Subject: Re: [PATCH v8 06/18] iommu: iommu_get_group_resv_regions Date: Tue, 17 Jan 2017 13:14:31 +0100 Message-ID: <15053a96-c3c2-69d4-760b-a213f4bff53f@caviumnetworks.com> References: <1484127714-3263-1-git-send-email-eric.auger@redhat.com> <1484127714-3263-7-git-send-email-eric.auger@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1484127714-3263-7-git-send-email-eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org To: Eric Auger , eric.auger.pro-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, christoffer.dall-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, marc.zyngier-5wv7dgnIgG8@public.gmane.org, robin.murphy-5wv7dgnIgG8@public.gmane.org, alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, will.deacon-5wv7dgnIgG8@public.gmane.org, joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org, tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org, jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org Cc: drjones-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, punit.agrawal-5wv7dgnIgG8@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, geethasowjanya.akula-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, pranav.sawargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, shankerd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, gpkulkarni-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org List-Id: iommu@lists.linux-foundation.org On 11.01.2017 10:41, Eric Auger wrote: > Introduce iommu_get_group_resv_regions whose role consists in > enumerating all devices from the group and collecting their > reserved regions. The list is sorted and overlaps between > regions of the same type are handled by merging the regions. > > Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Thanks, Tomasz > > --- > v6 -> v7: > - avoid merge of regions of different type > > v3 -> v4: > - take the iommu_group lock in iommu_get_group_resv_regions > - the list now is sorted and overlaps are checked > > NOTE: > - we do not move list elements from device to group list since > the iommu_put_resv_regions() could not be called. > - at the moment I did not introduce any iommu_put_group_resv_regions > since it simply consists in voiding/freeing the list > --- > drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/iommu.h | 8 +++++ > 2 files changed, 106 insertions(+) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 41c1906..640056b 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) > return sprintf(buf, "%s\n", group->name); > } > > +/** > + * iommu_insert_resv_region - Insert a new region in the > + * list of reserved regions. > + * @new: new region to insert > + * @regions: list of regions > + * > + * The new element is sorted by address with respect to the other > + * regions of the same type. In case it overlaps with another > + * region of the same type, regions are merged. In case it > + * overlaps with another region of different type, regions are > + * not merged. > + */ > +static int iommu_insert_resv_region(struct iommu_resv_region *new, > + struct list_head *regions) > +{ > + struct iommu_resv_region *region; > + phys_addr_t start = new->start; > + phys_addr_t end = new->start + new->length - 1; > + struct list_head *pos = regions->next; > + > + while (pos != regions) { > + struct iommu_resv_region *entry = > + list_entry(pos, struct iommu_resv_region, list); > + phys_addr_t a = entry->start; > + phys_addr_t b = entry->start + entry->length - 1; > + int type = entry->type; > + > + if (end < a) { > + goto insert; > + } else if (start > b) { > + pos = pos->next; > + } else if ((start >= a) && (end <= b)) { > + if (new->type == type) > + goto done; > + else > + pos = pos->next; > + } else { > + if (new->type == type) { > + phys_addr_t new_start = min(a, start); > + phys_addr_t new_end = max(b, end); > + > + list_del(&entry->list); > + entry->start = new_start; > + entry->length = new_end - new_start + 1; > + iommu_insert_resv_region(entry, regions); > + } else { > + pos = pos->next; > + } > + } > + } > +insert: > + region = iommu_alloc_resv_region(new->start, new->length, > + new->prot, new->type); > + if (!region) > + return -ENOMEM; > + > + list_add_tail(®ion->list, pos); > +done: > + return 0; > +} > + > +static int > +iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, > + struct list_head *group_resv_regions) > +{ > + struct iommu_resv_region *entry; > + int ret; > + > + list_for_each_entry(entry, dev_resv_regions, list) { > + ret = iommu_insert_resv_region(entry, group_resv_regions); > + if (ret) > + break; > + } > + return ret; > +} > + > +int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + struct iommu_device *device; > + int ret = 0; > + > + mutex_lock(&group->mutex); > + list_for_each_entry(device, &group->devices, list) { > + struct list_head dev_resv_regions; > + > + INIT_LIST_HEAD(&dev_resv_regions); > + iommu_get_resv_regions(device->dev, &dev_resv_regions); > + ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); > + iommu_put_resv_regions(device->dev, &dev_resv_regions); > + if (ret) > + break; > + } > + mutex_unlock(&group->mutex); > + return ret; > +} > +EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); > + > static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); > > static void iommu_group_release(struct kobject *kobj) > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index f6bb55d3..bec3730 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -246,6 +246,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, > extern int iommu_request_dm_for_dev(struct device *dev); > extern struct iommu_resv_region * > iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); > +extern int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head); > > extern int iommu_attach_group(struct iommu_domain *domain, > struct iommu_group *group); > @@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev, > { > } > > +static inline int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + return -ENODEV; > +} > + > static inline int iommu_request_dm_for_dev(struct device *dev) > { > return -ENODEV; > From mboxrd@z Thu Jan 1 00:00:00 1970 From: tnowicki@caviumnetworks.com (Tomasz Nowicki) Date: Tue, 17 Jan 2017 13:14:31 +0100 Subject: [PATCH v8 06/18] iommu: iommu_get_group_resv_regions In-Reply-To: <1484127714-3263-7-git-send-email-eric.auger@redhat.com> References: <1484127714-3263-1-git-send-email-eric.auger@redhat.com> <1484127714-3263-7-git-send-email-eric.auger@redhat.com> Message-ID: <15053a96-c3c2-69d4-760b-a213f4bff53f@caviumnetworks.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On 11.01.2017 10:41, Eric Auger wrote: > Introduce iommu_get_group_resv_regions whose role consists in > enumerating all devices from the group and collecting their > reserved regions. The list is sorted and overlaps between > regions of the same type are handled by merging the regions. > > Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Thanks, Tomasz > > --- > v6 -> v7: > - avoid merge of regions of different type > > v3 -> v4: > - take the iommu_group lock in iommu_get_group_resv_regions > - the list now is sorted and overlaps are checked > > NOTE: > - we do not move list elements from device to group list since > the iommu_put_resv_regions() could not be called. > - at the moment I did not introduce any iommu_put_group_resv_regions > since it simply consists in voiding/freeing the list > --- > drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/iommu.h | 8 +++++ > 2 files changed, 106 insertions(+) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 41c1906..640056b 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) > return sprintf(buf, "%s\n", group->name); > } > > +/** > + * iommu_insert_resv_region - Insert a new region in the > + * list of reserved regions. > + * @new: new region to insert > + * @regions: list of regions > + * > + * The new element is sorted by address with respect to the other > + * regions of the same type. In case it overlaps with another > + * region of the same type, regions are merged. In case it > + * overlaps with another region of different type, regions are > + * not merged. > + */ > +static int iommu_insert_resv_region(struct iommu_resv_region *new, > + struct list_head *regions) > +{ > + struct iommu_resv_region *region; > + phys_addr_t start = new->start; > + phys_addr_t end = new->start + new->length - 1; > + struct list_head *pos = regions->next; > + > + while (pos != regions) { > + struct iommu_resv_region *entry = > + list_entry(pos, struct iommu_resv_region, list); > + phys_addr_t a = entry->start; > + phys_addr_t b = entry->start + entry->length - 1; > + int type = entry->type; > + > + if (end < a) { > + goto insert; > + } else if (start > b) { > + pos = pos->next; > + } else if ((start >= a) && (end <= b)) { > + if (new->type == type) > + goto done; > + else > + pos = pos->next; > + } else { > + if (new->type == type) { > + phys_addr_t new_start = min(a, start); > + phys_addr_t new_end = max(b, end); > + > + list_del(&entry->list); > + entry->start = new_start; > + entry->length = new_end - new_start + 1; > + iommu_insert_resv_region(entry, regions); > + } else { > + pos = pos->next; > + } > + } > + } > +insert: > + region = iommu_alloc_resv_region(new->start, new->length, > + new->prot, new->type); > + if (!region) > + return -ENOMEM; > + > + list_add_tail(®ion->list, pos); > +done: > + return 0; > +} > + > +static int > +iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, > + struct list_head *group_resv_regions) > +{ > + struct iommu_resv_region *entry; > + int ret; > + > + list_for_each_entry(entry, dev_resv_regions, list) { > + ret = iommu_insert_resv_region(entry, group_resv_regions); > + if (ret) > + break; > + } > + return ret; > +} > + > +int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + struct iommu_device *device; > + int ret = 0; > + > + mutex_lock(&group->mutex); > + list_for_each_entry(device, &group->devices, list) { > + struct list_head dev_resv_regions; > + > + INIT_LIST_HEAD(&dev_resv_regions); > + iommu_get_resv_regions(device->dev, &dev_resv_regions); > + ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); > + iommu_put_resv_regions(device->dev, &dev_resv_regions); > + if (ret) > + break; > + } > + mutex_unlock(&group->mutex); > + return ret; > +} > +EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); > + > static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); > > static void iommu_group_release(struct kobject *kobj) > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index f6bb55d3..bec3730 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -246,6 +246,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, > extern int iommu_request_dm_for_dev(struct device *dev); > extern struct iommu_resv_region * > iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); > +extern int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head); > > extern int iommu_attach_group(struct iommu_domain *domain, > struct iommu_group *group); > @@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev, > { > } > > +static inline int iommu_get_group_resv_regions(struct iommu_group *group, > + struct list_head *head) > +{ > + return -ENODEV; > +} > + > static inline int iommu_request_dm_for_dev(struct device *dev) > { > return -ENODEV; >