Mark McLoughlin wrote:
> On Tue, 2008-12-02 at 22:22 +0800, Han, Weidong wrote:
> 
>> Separate add/remove domain device info functions for virtual machine
>> VT-d from natvie VT-d. 
>> 
>> Signed-off-by: Weidong Han <[EMAIL PROTECTED]>
>> ---
>>  drivers/pci/intel-iommu.c     |  164
>>  +++++++++++++++++++++++++++++++++++++++-
>>  include/linux/dma_remapping.h |    1 + 2 files changed, 160
>> insertions(+), 5 deletions(-) 
>> 
>> diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
>> index 09a5150..429aff4 100644
>> --- a/drivers/pci/intel-iommu.c
>> +++ b/drivers/pci/intel-iommu.c
>> @@ -200,6 +200,27 @@ static struct intel_iommu
>>  *domain_get_iommu(struct dmar_domain *domain)       return NULL; }
>> 
>> +static struct intel_iommu *device_find_matched_iommu(u8 bus, u8
>> devfn) 
> 
> That's quite an unwieldy name, how about device_to_iommu() ?

will rename it.

> 
>> +{
>> +    struct dmar_drhd_unit *drhd = NULL;
>> +    int i;
>> +
>> +    for_each_drhd_unit(drhd) {
>> +            if (drhd->ignored)
>> +                    continue;
>> +
>> +            for (i = 0; i < drhd->devices_cnt; i++)
>> +                    if (drhd->devices[i]->bus->number == bus &&
>> +                        drhd->devices[i]->devfn == devfn)
>> +                            return drhd->iommu;
>> +
>> +            if (drhd->include_all)
>> +                    return drhd->iommu;
>> +    }
>> +
>> +    return NULL;
>> +}
> ...
>> @@ -1269,9 +1292,12 @@ domain_page_mapping(struct dmar_domain
>>  *domain, dma_addr_t iova,   return 0; }
>> 
>> -static void detach_domain_for_dev(struct dmar_domain *domain, u8
>> bus, u8 devfn) +static void iommu_detach_dev(u8 bus, u8 devfn)
> 
> Would be nicer if this function took a struct intel_iommu pointer
> rather than bus/devfn. 

intel_iommu can be got by bus and devfn, so I didn't add the parameter. But 
your suggestion is reasonable. 

> 
>>  {
>> -    struct intel_iommu *iommu = domain_get_iommu(domain);
>> +    struct intel_iommu *iommu = device_find_matched_iommu(bus, devfn);
>> + +  if (!iommu)
>> +            return;
>> 
>>      clear_context_table(iommu, bus, devfn);
>>      iommu->flush.flush_context(iommu, 0, 0, 0, ...
>> +/* "Coherency" capability may be different across iommus */
>> +static void domain_update_iommu_coherency(struct dmar_domain
>> *domain) +{ +        struct dmar_drhd_unit *drhd;
>> +
>> +    domain->iommu_coherency = 1;
>> +
>> +    for_each_drhd_unit(drhd) {
>> +            if (drhd->ignored)
>> +                    continue;
>> +            if (test_bit(drhd->iommu->seq_id, &domain->iommu_bmp)) {
>> +                    if (!ecap_coherent(drhd->iommu->ecap)) {
>> +                            domain->iommu_coherency = 0;
>> +                            break;
>> +                    }
>> +            }
>> +    }
>> +}
> 
> As I said, this belongs in the patch where you added the
> iommu_coherency 
> flag.
> 
>> +
>> +static int vm_domain_add_dev_info(struct dmar_domain *domain, +             
>>                 
>> struct pci_dev *pdev) +{
>> +    struct device_domain_info *info;
>> +    unsigned long flags;
>> +
>> +    info = alloc_devinfo_mem();
>> +    if (!info)
>> +            return -ENOMEM;
>> +
>> +    info->bus = pdev->bus->number;
>> +    info->devfn = pdev->devfn;
>> +    info->dev = pdev;
>> +    info->domain = domain;
>> +
>> +    spin_lock_irqsave(&device_domain_lock, flags);
>> +    list_add(&info->link, &domain->devices);
>> +    list_add(&info->global, &device_domain_list);
>> +    pdev->dev.archdata.iommu = info;
>> +    spin_unlock_irqrestore(&device_domain_lock, flags); +
>> +    return 0;
>> +}
>> +
>> +static void vm_domain_remove_one_dev_info(struct dmar_domain
>> *domain, +                                     struct pci_dev *pdev) +{
>> +    struct device_domain_info *info;
>> +    struct intel_iommu *iommu;
>> +    unsigned long flags;
>> +    int found = 0;
>> +
>> +    iommu = device_find_matched_iommu(pdev->bus->number, pdev->devfn);
>> + +  spin_lock_irqsave(&device_domain_lock, flags);
>> +    while (!list_empty(&domain->devices)) {
>> +            info = list_entry(domain->devices.next,
>> +                    struct device_domain_info, link);
>> +            if (info->bus == pdev->bus->number &&
>> +                info->devfn == pdev->devfn) {
>> +                    list_del(&info->link);
>> +                    list_del(&info->global);
>> +                    if (info->dev)
>> +                            info->dev->dev.archdata.iommu = NULL;
>> +                    spin_unlock_irqrestore(&device_domain_lock, flags); +
>> +                    iommu_detach_dev(info->bus, info->devfn);
>> +                    free_devinfo_mem(info);
>> +
>> +                    spin_lock_irqsave(&device_domain_lock, flags);
>> +
>> +                    if (found)
>> +                            break;
>> +                    else
>> +                            continue;
>> +            }
>> +
>> +            /* if there is no other devices under the same iommu
>> +             * owned by this domain, clear this iommu in iommu_bmp +        
>>          */
>> +            if (device_find_matched_iommu(info->bus, info->devfn) == iommu)
>> +                    found = 1; +    }
>> +
>> +    if (found == 0) {
>> +            spin_lock_irqsave(&iommu->lock, flags);
>> +            clear_bit(iommu->seq_id, &domain->iommu_bmp);
>> +            domain->iommu_count--;
>> +            domain_update_iommu_coherency(domain);
>> +            spin_unlock_irqrestore(&iommu->lock, flags);
>> +    }
>> +
>> +    spin_unlock_irqrestore(&device_domain_lock, flags); +}
>> +
>> +static void vm_domain_remove_all_dev_info(struct dmar_domain
>> *domain) +{ +        struct device_domain_info *info;
>> +    struct intel_iommu *iommu;
>> +    unsigned long flags;
>> +
>> +    spin_lock_irqsave(&device_domain_lock, flags);
>> +    while (!list_empty(&domain->devices)) {
>> +            info = list_entry(domain->devices.next,
>> +                    struct device_domain_info, link);
>> +            list_del(&info->link);
>> +            list_del(&info->global);
>> +            if (info->dev)
>> +                    info->dev->dev.archdata.iommu = NULL;
>> +
>> +            spin_unlock_irqrestore(&device_domain_lock, flags);
>> +            iommu_detach_dev(info->bus, info->devfn);
>> +
>> +            /* clear this iommu in iommu_bmp */
>> +            iommu = device_find_matched_iommu(info->bus, info->devfn);
>> +            spin_lock_irqsave(&iommu->lock, flags);
>> +            if (test_and_clear_bit(iommu->seq_id,
>> +                                   &domain->iommu_bmp)) {
>> +                    domain->iommu_count--;
>> +                    domain_update_iommu_coherency(domain);
>> +            }
>> +            spin_unlock_irqrestore(&iommu->lock, flags);
>> +
>> +            free_devinfo_mem(info);
>> +            spin_lock_irqsave(&device_domain_lock, flags);
>> +    }
>> +    spin_unlock_irqrestore(&device_domain_lock, flags);
>> +}
> 
> You're adding three functions here which are essentially copies of
> code 
> that already exists, with some minor changes. You need to refactor the
> existing code and modify it to handle these cases.

Adding these functions is to remove domain flag judgment in many functions. 
domain flag judgment seems brittle. So it's a balance. I will clean up it again.

Regards,
Weidong


> 
> Cheers,
> Mark.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to