mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
misc: mods: update MODS driver from Perforce
Change-Id: Ic63f4f9c86c4575926ac33d8872199a59e9224ce Signed-off-by: Chris Dragan <kdragan@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1944110 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
5a7a662974
commit
bf8bcb968d
@@ -25,7 +25,7 @@
|
||||
|
||||
/* Driver version */
|
||||
#define MODS_DRIVER_VERSION_MAJOR 3
|
||||
#define MODS_DRIVER_VERSION_MINOR 88
|
||||
#define MODS_DRIVER_VERSION_MINOR 89
|
||||
#define MODS_DRIVER_VERSION ((MODS_DRIVER_VERSION_MAJOR << 8) | \
|
||||
((MODS_DRIVER_VERSION_MINOR/10) << 4) | \
|
||||
(MODS_DRIVER_VERSION_MINOR%10))
|
||||
@@ -125,6 +125,21 @@ struct MODS_GET_PHYSICAL_ADDRESS_3 {
|
||||
__u64 physical_address;
|
||||
};
|
||||
|
||||
#define MAX_PA_ENTRIES 64
|
||||
|
||||
/* MODS_ESC_GET_PHYSICAL_ADDRESS_RANGE, MODS_ESC_GET_DMA_ADDRESS_RANGE */
|
||||
struct MODS_GET_ADDRESS_RANGE {
|
||||
/* IN */
|
||||
__u64 memory_handle;
|
||||
__u64 offset;
|
||||
__u32 stride;
|
||||
__u32 num_entries;
|
||||
struct mods_pci_dev_2 pci_device;
|
||||
|
||||
/* OUT */
|
||||
__u64 physical_addresses[MAX_PA_ENTRIES];
|
||||
};
|
||||
|
||||
/* MODS_ESC_VIRTUAL_TO_PHYSICAL */
|
||||
struct MODS_VIRTUAL_TO_PHYSICAL {
|
||||
/* IN */
|
||||
@@ -1356,4 +1371,10 @@ struct MODS_MSR {
|
||||
_IOWR(MODS_IOC_MAGIC, 120, struct MODS_MSR)
|
||||
#define MODS_ESC_WRITE_MSR \
|
||||
_IOW(MODS_IOC_MAGIC, 121, struct MODS_MSR)
|
||||
#define MODS_ESC_GET_PHYSICAL_ADDRESS_RANGE \
|
||||
_IOWR(MODS_IOC_MAGIC, 122, \
|
||||
struct MODS_GET_ADDRESS_RANGE)
|
||||
#define MODS_ESC_GET_DMA_ADDRESS_RANGE \
|
||||
_IOWR(MODS_IOC_MAGIC, 123, \
|
||||
struct MODS_GET_ADDRESS_RANGE)
|
||||
#endif /* _MODS_H_ */
|
||||
|
||||
@@ -73,54 +73,49 @@ static int mods_extract_acpi_object(
|
||||
u8 *buf_end
|
||||
)
|
||||
{
|
||||
int ret = OK;
|
||||
int err = OK;
|
||||
|
||||
switch (obj->type) {
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
if (obj->buffer.length == 0) {
|
||||
mods_error_printk(
|
||||
"empty ACPI output buffer from ACPI method %s\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("empty ACPI output buffer from ACPI method %s\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
} else if (obj->buffer.length <= buf_end-*buf) {
|
||||
u32 size = obj->buffer.length;
|
||||
|
||||
memcpy(*buf, obj->buffer.pointer, size);
|
||||
*buf += size;
|
||||
} else {
|
||||
mods_error_printk(
|
||||
"output buffer too small for ACPI method %s\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("output buffer too small for ACPI method %s\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
if (buf_end - *buf >= 4) {
|
||||
if (obj->integer.value > 0xFFFFFFFFU) {
|
||||
mods_error_printk(
|
||||
"integer value from ACPI method %s out of range\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("integer value from ACPI method %s out of range\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
memcpy(*buf, &obj->integer.value, 4);
|
||||
*buf += 4;
|
||||
}
|
||||
} else {
|
||||
mods_error_printk(
|
||||
"output buffer too small for ACPI method %s\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("output buffer too small for ACPI method %s\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
if (obj->package.count == 0) {
|
||||
mods_error_printk(
|
||||
"empty ACPI output package from ACPI method %s\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("empty ACPI output package from ACPI method %s\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
union acpi_object *elements = obj->package.elements;
|
||||
u32 size = 0;
|
||||
@@ -128,44 +123,43 @@ static int mods_extract_acpi_object(
|
||||
|
||||
for (i = 0; i < obj->package.count; i++) {
|
||||
u8 *old_buf = *buf;
|
||||
u32 new_size;
|
||||
|
||||
ret = mods_extract_acpi_object(method,
|
||||
err = mods_extract_acpi_object(method,
|
||||
&elements[i],
|
||||
buf,
|
||||
buf_end);
|
||||
if (ret == OK) {
|
||||
u32 new_size = *buf - old_buf;
|
||||
|
||||
if (size == 0) {
|
||||
size = new_size;
|
||||
} else if (size != new_size) {
|
||||
mods_error_printk(
|
||||
"ambiguous package element size from ACPI method %s\n",
|
||||
method);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else
|
||||
if (err)
|
||||
break;
|
||||
|
||||
new_size = *buf - old_buf;
|
||||
|
||||
if (size == 0) {
|
||||
size = new_size;
|
||||
} else if (size != new_size) {
|
||||
mods_error_printk("ambiguous package element size from ACPI method %s\n",
|
||||
method);
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mods_error_printk(
|
||||
"unsupported ACPI output type 0x%02x from method %s\n",
|
||||
(unsigned int)obj->type, method);
|
||||
ret = -EINVAL;
|
||||
mods_error_printk("unsupported ACPI output type 0x%02x from method %s\n",
|
||||
(unsigned int)obj->type, method);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
|
||||
}
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mods_eval_acpi_method(struct file *pfile,
|
||||
struct MODS_EVAL_ACPI_METHOD *p,
|
||||
struct mods_pci_dev_2 *pdevice)
|
||||
{
|
||||
int ret = OK;
|
||||
int err = OK;
|
||||
int i;
|
||||
acpi_status status;
|
||||
struct acpi_object_list input;
|
||||
@@ -173,24 +167,35 @@ static int mods_eval_acpi_method(struct file *pfile,
|
||||
union acpi_object *acpi_method = NULL;
|
||||
union acpi_object acpi_params[ACPI_MAX_ARGUMENT_NUMBER];
|
||||
acpi_handle acpi_method_handler = NULL;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
if (p->argument_count >= ACPI_MAX_ARGUMENT_NUMBER) {
|
||||
mods_error_printk("invalid argument count for ACPI call\n");
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdevice) {
|
||||
unsigned int devfn;
|
||||
struct pci_dev *dev;
|
||||
|
||||
mods_debug_printk(DEBUG_ACPI,
|
||||
"ACPI %s for device %04x:%02x:%02x.%x\n",
|
||||
p->method_name,
|
||||
(unsigned int)pdevice->domain,
|
||||
(unsigned int)pdevice->bus,
|
||||
(unsigned int)pdevice->device,
|
||||
(unsigned int)pdevice->function);
|
||||
pdevice->domain,
|
||||
pdevice->bus,
|
||||
pdevice->device,
|
||||
pdevice->function);
|
||||
|
||||
devfn = PCI_DEVFN(pdevice->device, pdevice->function);
|
||||
dev = MODS_PCI_GET_SLOT(pdevice->domain, pdevice->bus, devfn);
|
||||
if (!dev) {
|
||||
mods_error_printk("ACPI: PCI device not found\n");
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, pdevice, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("ACPI: PCI device %04x:%02x:%02x.%x not found\n",
|
||||
pdevice->domain,
|
||||
pdevice->bus,
|
||||
pdevice->device,
|
||||
pdevice->function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
acpi_method_handler = MODS_ACPI_HANDLE(&dev->dev);
|
||||
} else {
|
||||
@@ -201,11 +206,8 @@ static int mods_eval_acpi_method(struct file *pfile,
|
||||
if (!acpi_method_handler) {
|
||||
mods_debug_printk(DEBUG_ACPI, "ACPI: handle for %s not found\n",
|
||||
p->method_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (p->argument_count >= ACPI_MAX_ARGUMENT_NUMBER) {
|
||||
mods_error_printk("invalid argument count for ACPI call\n");
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -227,6 +229,8 @@ static int mods_eval_acpi_method(struct file *pfile,
|
||||
}
|
||||
default: {
|
||||
mods_error_printk("unsupported ACPI argument type\n");
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -242,6 +246,8 @@ static int mods_eval_acpi_method(struct file *pfile,
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
mods_error_printk("ACPI method %s failed\n", p->method_name);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -249,63 +255,76 @@ static int mods_eval_acpi_method(struct file *pfile,
|
||||
if (!acpi_method) {
|
||||
mods_error_printk("missing output from ACPI method %s\n",
|
||||
p->method_name);
|
||||
ret = -EINVAL;
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
u8 *buf = p->out_buffer;
|
||||
|
||||
ret = mods_extract_acpi_object(p->method_name,
|
||||
err = mods_extract_acpi_object(p->method_name,
|
||||
acpi_method,
|
||||
&buf,
|
||||
buf+sizeof(p->out_buffer));
|
||||
p->out_data_size = (ret == OK) ? (buf - p->out_buffer) : 0;
|
||||
p->out_data_size = err ? 0 : (buf - p->out_buffer);
|
||||
}
|
||||
|
||||
kfree(output.pointer);
|
||||
return ret;
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mods_acpi_get_ddc(struct file *pfile,
|
||||
struct MODS_ACPI_GET_DDC_2 *p,
|
||||
struct mods_pci_dev_2 *pci_device)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *ddc;
|
||||
union acpi_object ddc_arg0 = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list input = { 1, &ddc_arg0 };
|
||||
struct list_head *node, *next;
|
||||
u32 i;
|
||||
acpi_handle dev_handle = NULL;
|
||||
acpi_handle lcd_dev_handle = NULL;
|
||||
int err;
|
||||
acpi_status status;
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *ddc;
|
||||
union acpi_object ddc_arg0 = { ACPI_TYPE_INTEGER };
|
||||
struct acpi_object_list input = { 1, &ddc_arg0 };
|
||||
struct list_head *node;
|
||||
struct list_head *next;
|
||||
u32 i;
|
||||
acpi_handle dev_handle = NULL;
|
||||
acpi_handle lcd_dev_handle = NULL;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_ACPI,
|
||||
"ACPI _DDC (EDID) for device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)pci_device->domain,
|
||||
(unsigned int)pci_device->bus,
|
||||
(unsigned int)pci_device->device,
|
||||
(unsigned int)pci_device->function);
|
||||
pci_device->domain,
|
||||
pci_device->bus,
|
||||
pci_device->device,
|
||||
pci_device->function);
|
||||
|
||||
{
|
||||
unsigned int devfn = PCI_DEVFN(pci_device->device,
|
||||
pci_device->function);
|
||||
struct pci_dev *dev = MODS_PCI_GET_SLOT(pci_device->domain,
|
||||
pci_device->bus, devfn);
|
||||
if (!dev) {
|
||||
mods_error_printk("ACPI: PCI device not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_handle = MODS_ACPI_HANDLE(&dev->dev);
|
||||
err = mods_find_pci_dev(pfile, pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("ACPI: PCI device %04x:%02x:%02x.%x not found\n",
|
||||
pci_device->domain,
|
||||
pci_device->bus,
|
||||
pci_device->device,
|
||||
pci_device->function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_handle = MODS_ACPI_HANDLE(&dev->dev);
|
||||
if (!dev_handle) {
|
||||
mods_debug_printk(DEBUG_ACPI,
|
||||
"ACPI: handle for _DDC not found\n");
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
status = acpi_bus_get_device(dev_handle, &device);
|
||||
|
||||
status = acpi_bus_get_device(dev_handle, &device);
|
||||
if (ACPI_FAILURE(status) || !device) {
|
||||
mods_error_printk("ACPI: device for _DDC not found\n");
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -341,10 +360,10 @@ static int mods_acpi_get_ddc(struct file *pfile,
|
||||
mods_debug_printk(DEBUG_ACPI,
|
||||
"ACPI: Found LCD 0x%x on device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)device_id,
|
||||
(unsigned int)p->device.domain,
|
||||
(unsigned int)p->device.bus,
|
||||
(unsigned int)p->device.device,
|
||||
(unsigned int)p->device.function);
|
||||
p->device.domain,
|
||||
p->device.bus,
|
||||
p->device.device,
|
||||
p->device.function);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -353,10 +372,12 @@ static int mods_acpi_get_ddc(struct file *pfile,
|
||||
if (lcd_dev_handle == NULL) {
|
||||
mods_error_printk(
|
||||
"ACPI: LCD not found for device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->device.domain,
|
||||
(unsigned int)p->device.bus,
|
||||
(unsigned int)p->device.device,
|
||||
(unsigned int)p->device.function);
|
||||
p->device.domain,
|
||||
p->device.bus,
|
||||
p->device.device,
|
||||
p->device.function);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -377,6 +398,8 @@ static int mods_acpi_get_ddc(struct file *pfile,
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
mods_error_printk("ACPI method _DDC (EDID) failed\n");
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -389,20 +412,21 @@ static int mods_acpi_get_ddc(struct file *pfile,
|
||||
memcpy(p->out_buffer,
|
||||
ddc->buffer.pointer,
|
||||
p->out_data_size);
|
||||
err = OK;
|
||||
} else {
|
||||
mods_error_printk(
|
||||
"output buffer too small for ACPI method _DDC (EDID)\n");
|
||||
kfree(output.pointer);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
mods_error_printk("unsupported ACPI output type\n");
|
||||
kfree(output.pointer);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
kfree(output.pointer);
|
||||
return OK;
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
/*************************
|
||||
|
||||
@@ -97,6 +97,9 @@ struct mods_client {
|
||||
spinlock_t irq_lock;
|
||||
struct en_dev_entry *enabled_devices;
|
||||
struct mem_type mem_type;
|
||||
#if defined(CONFIG_PCI)
|
||||
struct pci_dev *cached_dev;
|
||||
#endif
|
||||
struct mutex mtx;
|
||||
int mods_fb_suspended[FB_MAX];
|
||||
u32 access_token;
|
||||
@@ -121,34 +124,35 @@ struct MODS_PHYS_CHUNK {
|
||||
u64 dma_addr:58; /* phys addr (or machine addr on XEN) */
|
||||
u32 order:5; /* 1<<order = number of contig pages */
|
||||
int allocated:1;
|
||||
u64 dev_addr; /* DMA map addr for default device */
|
||||
struct page *p_page;
|
||||
};
|
||||
|
||||
struct MODS_MAP_CHUNK {
|
||||
struct MODS_PHYS_CHUNK *pt;
|
||||
u64 map_addr;
|
||||
};
|
||||
|
||||
struct MODS_DMA_MAP {
|
||||
struct pci_dev *dev; /* pci_dev to map the page to */
|
||||
struct list_head list;
|
||||
struct MODS_MAP_CHUNK mapping[1];
|
||||
struct pci_dev *dev; /* pci_dev these mappings are for */
|
||||
u64 dev_addr[1]; /* each entry corresponds to phys chunk
|
||||
* in the pages array at the same index
|
||||
*/
|
||||
};
|
||||
|
||||
/* system memory allocation tracking */
|
||||
struct MODS_MEM_INFO {
|
||||
u64 logical_addr; /* kernel logical address */
|
||||
u32 num_pages; /* number of allocated pages */
|
||||
u8 alloc_type : 2; /* MODS_ALLOC_TYPE_* */
|
||||
u8 cache_type : 3; /* MODS_MEMORY_* */
|
||||
u8 addr_bits : 7; /* phys addr size requested */
|
||||
u32 length; /* actual number of bytes allocated */
|
||||
u32 max_chunks; /* max number of contig chunks */
|
||||
int numa_node; /* numa node for the allocation */
|
||||
struct pci_dev *dev; /* backwards compatibility : pci_dev that the
|
||||
* memory was allocated on
|
||||
*/
|
||||
u64 logical_addr; /* kernel logical address */
|
||||
u32 num_pages; /* number of allocated pages */
|
||||
u8 alloc_type : 2; /* MODS_ALLOC_TYPE_* */
|
||||
u8 cache_type : 3; /* MODS_MEMORY_* */
|
||||
u8 addr_bits : 7; /* phys addr size requested */
|
||||
u32 length; /* actual number of bytes allocated */
|
||||
u32 num_chunks; /* max number of contig chunks */
|
||||
int numa_node; /* numa node for the allocation */
|
||||
struct pci_dev *dev; /* (optional) pci_dev this allocation
|
||||
* is for.
|
||||
*/
|
||||
|
||||
/* List of DMA mappings for devices other than the default
|
||||
* device specified by the dev field above.
|
||||
*/
|
||||
struct list_head dma_map_list;
|
||||
|
||||
struct list_head list;
|
||||
@@ -194,8 +198,10 @@ struct PPC_TCE_BYPASS {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int has_npu_dev(struct pci_dev *dev, int index);
|
||||
|
||||
int mods_is_nvlink_sysmem_trained(struct file *fp,
|
||||
struct pci_dev *dev);
|
||||
struct pci_dev *dev);
|
||||
|
||||
/* NvLink Trained tracking */
|
||||
struct NVL_TRAINED {
|
||||
@@ -335,19 +341,6 @@ struct mods_priv {
|
||||
#define MODS_DMA_TO_PHYS(dma_addr) (dma_addr)
|
||||
#endif
|
||||
|
||||
/* PCI */
|
||||
#define MODS_PCI_GET_SLOT(mydomain, mybus, devfn) \
|
||||
({ \
|
||||
struct pci_dev *__dev = NULL; \
|
||||
while ((__dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, __dev))) { \
|
||||
if (pci_domain_nr(__dev->bus) == mydomain \
|
||||
&& __dev->bus->number == mybus \
|
||||
&& __dev->devfn == devfn) \
|
||||
break; \
|
||||
} \
|
||||
__dev; \
|
||||
})
|
||||
|
||||
/* ACPI */
|
||||
#ifdef MODS_HAS_NEW_ACPI_WALK
|
||||
#define MODS_ACPI_WALK_NAMESPACE(type, start_object, max_depth, user_function, \
|
||||
@@ -398,12 +391,24 @@ int mods_unregister_all_ppc_tce_bypass(struct file *fp);
|
||||
int mods_unregister_all_nvlink_sysmem_trained(struct file *fp);
|
||||
#endif
|
||||
|
||||
/* pci */
|
||||
#ifdef CONFIG_PCI
|
||||
struct en_dev_entry *mods_enable_device(struct mods_client *client,
|
||||
struct pci_dev *dev);
|
||||
void mods_disable_device(struct pci_dev *pdev);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
int mods_is_pci_dev(struct pci_dev *dev,
|
||||
struct mods_pci_dev_2 *pcidev);
|
||||
int mods_find_pci_dev(struct file *fp,
|
||||
struct mods_pci_dev_2 *pcidev,
|
||||
struct pci_dev **retdev);
|
||||
#else
|
||||
#define mods_is_pci_dev(a, b) 0
|
||||
#define mods_find_pci_dev(a, b, c) (-ENODEV)
|
||||
#endif
|
||||
|
||||
/* clock */
|
||||
#ifdef MODS_TEGRA
|
||||
void mods_init_clock_api(void);
|
||||
@@ -424,12 +429,16 @@ int esc_mods_get_phys_addr(struct file *fp,
|
||||
struct MODS_GET_PHYSICAL_ADDRESS *p);
|
||||
int esc_mods_get_phys_addr_2(struct file *fp,
|
||||
struct MODS_GET_PHYSICAL_ADDRESS_3 *p);
|
||||
int esc_mods_get_phys_addr_range(struct file *fp,
|
||||
struct MODS_GET_ADDRESS_RANGE *p);
|
||||
int esc_mods_get_mapped_phys_addr(struct file *fp,
|
||||
struct MODS_GET_PHYSICAL_ADDRESS *p);
|
||||
int esc_mods_get_mapped_phys_addr_2(struct file *fp,
|
||||
struct MODS_GET_PHYSICAL_ADDRESS_2 *p);
|
||||
int esc_mods_get_mapped_phys_addr_3(struct file *fp,
|
||||
struct MODS_GET_PHYSICAL_ADDRESS_3 *p);
|
||||
int esc_mods_get_dma_addr_range(struct file *fp,
|
||||
struct MODS_GET_ADDRESS_RANGE *p);
|
||||
int esc_mods_virtual_to_phys(struct file *fp,
|
||||
struct MODS_VIRTUAL_TO_PHYSICAL *p);
|
||||
int esc_mods_phys_to_virtual(struct file *fp,
|
||||
|
||||
@@ -59,30 +59,18 @@ struct mutex *mods_get_irq_mutex(void)
|
||||
struct en_dev_entry *mods_enable_device(struct mods_client *client,
|
||||
struct pci_dev *dev)
|
||||
{
|
||||
int ret = -1;
|
||||
int err = OK;
|
||||
struct en_dev_entry *dpriv = client->enabled_devices;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&mp.mtx));
|
||||
|
||||
dpriv = pci_get_drvdata(dev);
|
||||
|
||||
if (dpriv) {
|
||||
if (unlikely(dpriv)) {
|
||||
if (dpriv->client_id == client->client_id)
|
||||
return dpriv;
|
||||
|
||||
mods_error_printk("invalid client %u for device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)client->client_id,
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(dev);
|
||||
|
||||
if (ret != 0) {
|
||||
mods_error_printk("failed to enable device %04x:%02x:%02x.%x\n",
|
||||
client->client_id,
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
@@ -93,9 +81,21 @@ struct en_dev_entry *mods_enable_device(struct mods_client *client,
|
||||
dpriv = kzalloc(sizeof(*dpriv), GFP_KERNEL | __GFP_NORETRY);
|
||||
if (unlikely(!dpriv))
|
||||
return 0;
|
||||
dpriv->client_id = client->client_id;
|
||||
dpriv->dev = dev;
|
||||
dpriv->next = client->enabled_devices;
|
||||
|
||||
err = pci_enable_device(dev);
|
||||
if (unlikely(err)) {
|
||||
mods_error_printk("failed to enable device %04x:%02x:%02x.%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
kfree(dpriv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dpriv->client_id = client->client_id;
|
||||
dpriv->dev = pci_dev_get(dev);
|
||||
dpriv->next = client->enabled_devices;
|
||||
client->enabled_devices = dpriv;
|
||||
pci_set_drvdata(dev, dpriv);
|
||||
|
||||
@@ -108,8 +108,10 @@ void mods_disable_device(struct pci_dev *dev)
|
||||
|
||||
BUG_ON(!mutex_is_locked(&mp.mtx));
|
||||
|
||||
if (dpriv)
|
||||
if (dpriv) {
|
||||
pci_set_drvdata(dev, NULL);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_disable_device(dev);
|
||||
}
|
||||
@@ -245,14 +247,14 @@ static int rec_irq_done(struct dev_irq_map *t,
|
||||
#ifdef CONFIG_PCI
|
||||
if (t->dev) {
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
"%04x:%02x:%02x.%x %s IRQ 0x%x time=%uus\n",
|
||||
(unsigned int)(pci_domain_nr(t->dev->bus)),
|
||||
(unsigned int)(t->dev->bus->number),
|
||||
(unsigned int)PCI_SLOT(t->dev->devfn),
|
||||
(unsigned int)PCI_FUNC(t->dev->devfn),
|
||||
mods_irq_type_name(t->type),
|
||||
t->apic_irq,
|
||||
irq_time);
|
||||
"%04x:%02x:%02x.%x %s IRQ 0x%x time=%uus\n",
|
||||
pci_domain_nr(t->dev->bus),
|
||||
t->dev->bus->number,
|
||||
PCI_SLOT(t->dev->devfn),
|
||||
PCI_FUNC(t->dev->devfn),
|
||||
mods_irq_type_name(t->type),
|
||||
t->apic_irq,
|
||||
irq_time);
|
||||
} else
|
||||
#endif
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
@@ -363,13 +365,13 @@ static int is_nvidia_gpu(struct pci_dev *dev)
|
||||
#ifdef CONFIG_PCI
|
||||
static void setup_mask_info(struct dev_irq_map *newmap,
|
||||
struct MODS_REGISTER_IRQ_4 *p,
|
||||
struct pci_dev *pdev)
|
||||
struct pci_dev *dev)
|
||||
{
|
||||
/* account for legacy adapters */
|
||||
char *bar = newmap->dev_irq_aperture;
|
||||
u32 ii = 0;
|
||||
|
||||
if ((p->mask_info_cnt == 0) && is_nvidia_gpu(pdev)) {
|
||||
if ((p->mask_info_cnt == 0) && is_nvidia_gpu(dev)) {
|
||||
newmap->mask_info_cnt = 1;
|
||||
newmap->mask_info[0].dev_irq_mask_reg = (u32 *)(bar+0x140);
|
||||
newmap->mask_info[0].dev_irq_disable_reg = (u32 *)(bar+0x140);
|
||||
@@ -394,12 +396,14 @@ static void setup_mask_info(struct dev_irq_map *newmap,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_irq_map(u8 client_id,
|
||||
struct pci_dev *pdev,
|
||||
struct MODS_REGISTER_IRQ_4 *p, u32 irq, u32 entry)
|
||||
static int add_irq_map(u8 client_id,
|
||||
struct pci_dev *dev,
|
||||
struct MODS_REGISTER_IRQ_4 *p,
|
||||
u32 irq,
|
||||
u32 entry)
|
||||
{
|
||||
u32 irq_type = MODS_IRQ_TYPE_FROM_FLAGS(p->irq_flags);
|
||||
struct dev_irq_map *newmap = NULL;
|
||||
u32 irq_type = MODS_IRQ_TYPE_FROM_FLAGS(p->irq_flags);
|
||||
struct dev_irq_map *newmap = NULL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -412,7 +416,7 @@ static int add_irq_map(u8 client_id,
|
||||
|
||||
/* Fill out the new entry */
|
||||
newmap->apic_irq = irq;
|
||||
newmap->dev = pdev;
|
||||
newmap->dev = dev;
|
||||
newmap->client_id = client_id;
|
||||
newmap->dev_irq_aperture = 0;
|
||||
newmap->mask_info_cnt = 0;
|
||||
@@ -451,8 +455,11 @@ static int add_irq_map(u8 client_id,
|
||||
}
|
||||
|
||||
newmap->dev_irq_aperture = bar;
|
||||
setup_mask_info(newmap, p, pdev);
|
||||
setup_mask_info(newmap, p, dev);
|
||||
}
|
||||
|
||||
if (dev)
|
||||
pci_dev_get(dev);
|
||||
#endif
|
||||
|
||||
/* Print out successful registration string */
|
||||
@@ -463,46 +470,46 @@ static int add_irq_map(u8 client_id,
|
||||
(irq_type == MODS_IRQ_TYPE_MSI) ||
|
||||
(irq_type == MODS_IRQ_TYPE_MSIX)) {
|
||||
mods_debug_printk(DEBUG_ISR,
|
||||
"%04x:%02x:%02x.%x registered %s IRQ 0x%x\n",
|
||||
(unsigned int)(pci_domain_nr(pdev->bus)),
|
||||
(unsigned int)(pdev->bus->number),
|
||||
(unsigned int)PCI_SLOT(pdev->devfn),
|
||||
(unsigned int)PCI_FUNC(pdev->devfn),
|
||||
mods_irq_type_name(irq_type),
|
||||
irq);
|
||||
"%04x:%02x:%02x.%x registered %s IRQ 0x%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
mods_irq_type_name(irq_type),
|
||||
irq);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
else if (irq_type == MODS_IRQ_TYPE_MSI) {
|
||||
u16 control;
|
||||
u16 data;
|
||||
int cap_pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
|
||||
int cap_pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
|
||||
pci_read_config_word(pdev, MSI_CONTROL_REG(cap_pos), &control);
|
||||
pci_read_config_word(dev, MSI_CONTROL_REG(cap_pos), &control);
|
||||
if (IS_64BIT_ADDRESS(control))
|
||||
pci_read_config_word(pdev,
|
||||
pci_read_config_word(dev,
|
||||
MSI_DATA_REG(cap_pos, 1),
|
||||
&data);
|
||||
else
|
||||
pci_read_config_word(pdev,
|
||||
pci_read_config_word(dev,
|
||||
MSI_DATA_REG(cap_pos, 0),
|
||||
&data);
|
||||
mods_debug_printk(DEBUG_ISR,
|
||||
"%04x:%02x:%02x.%x registered MSI IRQ 0x%x data:0x%02x\n",
|
||||
(unsigned int)(pci_domain_nr(pdev->bus)),
|
||||
(unsigned int)(pdev->bus->number),
|
||||
(unsigned int)PCI_SLOT(pdev->devfn),
|
||||
(unsigned int)PCI_FUNC(pdev->devfn),
|
||||
irq,
|
||||
(unsigned int)data);
|
||||
"%04x:%02x:%02x.%x registered MSI IRQ 0x%x data:0x%02x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
irq,
|
||||
data);
|
||||
} else if (irq_type == MODS_IRQ_TYPE_MSIX) {
|
||||
mods_debug_printk(DEBUG_ISR,
|
||||
"%04x:%02x:%02x.%x registered MSI-X IRQ 0x%x\n",
|
||||
(unsigned int)(pci_domain_nr(pdev->bus)),
|
||||
(unsigned int)(pdev->bus->number),
|
||||
(unsigned int)PCI_SLOT(pdev->devfn),
|
||||
(unsigned int)PCI_FUNC(pdev->devfn),
|
||||
irq);
|
||||
"%04x:%02x:%02x.%x registered MSI-X IRQ 0x%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
irq);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -529,6 +536,10 @@ static void mods_free_map(struct dev_irq_map *del)
|
||||
if (del->dev_irq_aperture)
|
||||
iounmap(del->dev_irq_aperture);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
pci_dev_put(del->dev);
|
||||
#endif
|
||||
|
||||
/* Free memory */
|
||||
kfree(del);
|
||||
|
||||
@@ -641,7 +652,7 @@ static int mods_free_irqs(u8 client_id, struct pci_dev *dev)
|
||||
|
||||
if (dpriv->client_id != client_id) {
|
||||
mods_error_printk("invalid client %u for device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)client_id,
|
||||
client_id,
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
@@ -652,14 +663,13 @@ static int mods_free_irqs(u8 client_id, struct pci_dev *dev)
|
||||
}
|
||||
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
"(dev=%04x:%02x:%02x.%x) irq_flags=0x%x nvecs=%d\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
dpriv->irq_flags,
|
||||
dpriv->nvecs
|
||||
);
|
||||
"(dev=%04x:%02x:%02x.%x) irq_flags=0x%x nvecs=%d\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
dpriv->irq_flags,
|
||||
dpriv->nvecs);
|
||||
|
||||
/* Delete device interrupts from the list */
|
||||
list_for_each_entry_safe(del, next, &client->irq_list, list) {
|
||||
@@ -668,13 +678,13 @@ static int mods_free_irqs(u8 client_id, struct pci_dev *dev)
|
||||
|
||||
list_del(&del->list);
|
||||
mods_debug_printk(DEBUG_ISR,
|
||||
"%04x:%02x:%02x.%x unregistered %s IRQ 0x%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
mods_irq_type_name(type),
|
||||
del->apic_irq);
|
||||
"%04x:%02x:%02x.%x unregistered %s IRQ 0x%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
mods_irq_type_name(type),
|
||||
del->apic_irq);
|
||||
mods_free_map(del);
|
||||
|
||||
BUG_ON(type !=
|
||||
@@ -748,24 +758,23 @@ static int mods_allocate_irqs(u8 client_id, struct file *pfile,
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
"(dev=%04x:%02x:%02x.%x, flags=0x%x, nvecs=%d)\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
flags,
|
||||
nvecs);
|
||||
"(dev=%04x:%02x:%02x.%x, flags=0x%x, nvecs=%d)\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn),
|
||||
flags,
|
||||
nvecs);
|
||||
|
||||
/* Determine if the device supports requested interrupt type */
|
||||
if (irq_type == MODS_IRQ_TYPE_MSI) {
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (pci_find_capability(dev, PCI_CAP_ID_MSI) == 0) {
|
||||
mods_error_printk(
|
||||
"dev %04x:%02x:%02x.%x does not support MSI\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
mods_error_printk("dev %04x:%02x:%02x.%x does not support MSI\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -776,12 +785,11 @@ static int mods_allocate_irqs(u8 client_id, struct file *pfile,
|
||||
} else if (irq_type == MODS_IRQ_TYPE_MSIX) {
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (pci_find_capability(dev, PCI_CAP_ID_MSIX) == 0) {
|
||||
mods_error_printk(
|
||||
"dev %04x:%02x:%02x.%x does not support MSI-X\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
mods_error_printk("dev %04x:%02x:%02x.%x does not support MSI-X\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -818,12 +826,11 @@ static int mods_allocate_irqs(u8 client_id, struct file *pfile,
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pci_enable_msi(dev) != 0) {
|
||||
mods_error_printk(
|
||||
"unable to enable MSI on dev %04x:%02x:%02x.%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
mods_error_printk("unable to enable MSI on dev %04x:%02x:%02x.%x\n",
|
||||
pci_domain_nr(dev->bus),
|
||||
dev->bus->number,
|
||||
PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -911,45 +918,44 @@ static int mods_allocate_irqs(u8 client_id, struct file *pfile,
|
||||
static int mods_register_pci_irq(struct file *pfile,
|
||||
struct MODS_REGISTER_IRQ_4 *p)
|
||||
{
|
||||
int rc = OK;
|
||||
unsigned int irq_type = MODS_IRQ_TYPE_FROM_FLAGS(p->irq_flags);
|
||||
struct pci_dev *dev;
|
||||
int err = OK;
|
||||
unsigned int irq_type = MODS_IRQ_TYPE_FROM_FLAGS(p->irq_flags);
|
||||
struct pci_dev *dev;
|
||||
struct en_dev_entry *dpriv;
|
||||
unsigned int devfn;
|
||||
u8 client_id;
|
||||
int i;
|
||||
u8 client_id;
|
||||
int i;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the PCI device structure for the specified device from kernel */
|
||||
devfn = PCI_DEVFN(p->dev.device, p->dev.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->dev.domain, p->dev.bus, devfn);
|
||||
if (!dev) {
|
||||
mods_error_printk(
|
||||
"unknown dev %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->dev.domain,
|
||||
(unsigned int)p->dev.bus,
|
||||
(unsigned int)p->dev.device,
|
||||
(unsigned int)p->dev.function);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!p->irq_count) {
|
||||
if (unlikely(!p->irq_count)) {
|
||||
mods_error_printk("no irq's requested!\n");
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the PCI device structure for the specified device from kernel */
|
||||
err = mods_find_pci_dev(pfile, &p->dev, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->dev.domain,
|
||||
p->dev.bus,
|
||||
p->dev.device,
|
||||
p->dev.function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
if (unlikely(mutex_lock_interruptible(&mp.mtx))) {
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINTR;
|
||||
}
|
||||
@@ -958,22 +964,24 @@ static int mods_register_pci_irq(struct file *pfile,
|
||||
if (dpriv) {
|
||||
if (dpriv->client_id != client_id) {
|
||||
mods_error_printk("dev %04x:%02x:%02x.%x already owned by client %u\n",
|
||||
(unsigned int)p->dev.domain,
|
||||
(unsigned int)p->dev.bus,
|
||||
(unsigned int)p->dev.device,
|
||||
(unsigned int)p->dev.function,
|
||||
(unsigned int)dpriv->client_id);
|
||||
p->dev.domain,
|
||||
p->dev.bus,
|
||||
p->dev.device,
|
||||
p->dev.function,
|
||||
dpriv->client_id);
|
||||
mutex_unlock(&mp.mtx);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
if (dpriv->nvecs) {
|
||||
mods_error_printk("interrupt for dev %04x:%02x:%02x.%x already registered\n",
|
||||
(unsigned int)p->dev.domain,
|
||||
(unsigned int)p->dev.bus,
|
||||
(unsigned int)p->dev.device,
|
||||
(unsigned int)p->dev.function);
|
||||
p->dev.domain,
|
||||
p->dev.bus,
|
||||
p->dev.device,
|
||||
p->dev.function);
|
||||
mutex_unlock(&mp.mtx);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -984,6 +992,7 @@ static int mods_register_pci_irq(struct file *pfile,
|
||||
mods_error_printk("could not allocate irqs for irq_type %d\n",
|
||||
irq_type);
|
||||
mutex_unlock(&mp.mtx);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -995,37 +1004,38 @@ static int mods_register_pci_irq(struct file *pfile,
|
||||
(irq_type == MODS_IRQ_TYPE_MSI)) ? dev->irq :
|
||||
dpriv->msix_entries[i].vector;
|
||||
|
||||
if (add_irq_map(client_id, dev, p, irq, i) != OK) {
|
||||
err = add_irq_map(client_id, dev, p, irq, i);
|
||||
if (unlikely(err)) {
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
if (irq_type == MODS_IRQ_TYPE_MSI)
|
||||
pci_disable_msi(dev);
|
||||
else if (irq_type == MODS_IRQ_TYPE_MSIX)
|
||||
pci_disable_msix(dev);
|
||||
#endif
|
||||
mutex_unlock(&mp.mtx);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mp.mtx);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
static int mods_register_cpu_irq(struct file *pfile,
|
||||
struct MODS_REGISTER_IRQ_4 *p)
|
||||
{
|
||||
u8 client_id;
|
||||
u8 client_id;
|
||||
u32 irq = p->dev.bus;
|
||||
int err;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1045,14 +1055,11 @@ static int mods_register_cpu_irq(struct file *pfile,
|
||||
}
|
||||
|
||||
/* Register interrupt */
|
||||
if (add_irq_map(client_id, 0, p, irq, 0) != OK) {
|
||||
mutex_unlock(&mp.mtx);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
err = add_irq_map(client_id, 0, p, irq, 0);
|
||||
|
||||
mutex_unlock(&mp.mtx);
|
||||
return OK;
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
@@ -1060,32 +1067,31 @@ static int mods_unregister_pci_irq(struct file *pfile,
|
||||
struct MODS_REGISTER_IRQ_2 *p)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
u8 client_id;
|
||||
int rv = OK;
|
||||
u8 client_id;
|
||||
int err = OK;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the PCI device structure for the specified device from kernel */
|
||||
devfn = PCI_DEVFN(p->dev.device, p->dev.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->dev.domain, p->dev.bus, devfn);
|
||||
if (!dev) {
|
||||
err = mods_find_pci_dev(pfile, &p->dev, &dev);
|
||||
if (unlikely(err)) {
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
rv = mods_free_irqs(client_id, dev);
|
||||
err = mods_free_irqs(client_id, dev);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return rv;
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1104,8 +1110,8 @@ static int mods_unregister_cpu_irq(struct file *pfile,
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1211,17 +1217,17 @@ int esc_mods_register_irq_2(struct file *pfile,
|
||||
#ifdef CONFIG_PCI
|
||||
{
|
||||
/* Get the PCI device structure */
|
||||
unsigned int devfn;
|
||||
struct pci_dev *dev;
|
||||
int err;
|
||||
|
||||
err = mods_find_pci_dev(pfile, &p->dev, &dev);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
devfn = PCI_DEVFN(p->dev.device, p->dev.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->dev.domain, p->dev.bus, devfn);
|
||||
if (!dev) {
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
irq_data.aperture_addr = pci_resource_start(dev, 0);
|
||||
irq_data.aperture_size = pci_resource_len(dev, 0);
|
||||
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1243,7 +1249,7 @@ int esc_mods_register_irq(struct file *pfile,
|
||||
}
|
||||
|
||||
int esc_mods_unregister_irq_2(struct file *pfile,
|
||||
struct MODS_REGISTER_IRQ_2 *p)
|
||||
struct MODS_REGISTER_IRQ_2 *p)
|
||||
{
|
||||
if (p->type == MODS_IRQ_TYPE_CPU)
|
||||
return mods_unregister_cpu_irq(pfile, p);
|
||||
@@ -1255,7 +1261,7 @@ int esc_mods_unregister_irq_2(struct file *pfile,
|
||||
}
|
||||
|
||||
int esc_mods_unregister_irq(struct file *pfile,
|
||||
struct MODS_REGISTER_IRQ *p)
|
||||
struct MODS_REGISTER_IRQ *p)
|
||||
{
|
||||
struct MODS_REGISTER_IRQ_2 register_irq = { {0} };
|
||||
|
||||
@@ -1281,8 +1287,8 @@ int esc_mods_query_irq_3(struct file *pfile, struct MODS_QUERY_IRQ_3 *p)
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1320,14 +1326,14 @@ int esc_mods_query_irq_3(struct file *pfile, struct MODS_QUERY_IRQ_3 *p)
|
||||
/* Print info about IRQ status returned */
|
||||
if (dev) {
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
"retrieved IRQ index=%d dev %04x:%02x:%02x.%x, time=%uus, delay=%uus\n",
|
||||
p->irq_list[i].irq_index,
|
||||
(unsigned int)p->irq_list[i].dev.domain,
|
||||
(unsigned int)p->irq_list[i].dev.bus,
|
||||
(unsigned int)p->irq_list[i].dev.device,
|
||||
(unsigned int)p->irq_list[i].dev.function,
|
||||
q->data[index].time,
|
||||
p->irq_list[i].delay);
|
||||
"retrieved IRQ index=%d dev %04x:%02x:%02x.%x, time=%uus, delay=%uus\n",
|
||||
p->irq_list[i].irq_index,
|
||||
p->irq_list[i].dev.domain,
|
||||
p->irq_list[i].dev.bus,
|
||||
p->irq_list[i].dev.device,
|
||||
p->irq_list[i].dev.function,
|
||||
q->data[index].time,
|
||||
p->irq_list[i].delay);
|
||||
} else {
|
||||
mods_debug_printk(DEBUG_ISR_DETAILED,
|
||||
"retrieved IRQ 0x%x, time=%uus, delay=%uus\n",
|
||||
@@ -1366,7 +1372,7 @@ int esc_mods_query_irq_2(struct file *pfile, struct MODS_QUERY_IRQ_2 *p)
|
||||
}
|
||||
|
||||
int esc_mods_query_irq(struct file *pfile,
|
||||
struct MODS_QUERY_IRQ *p)
|
||||
struct MODS_QUERY_IRQ *p)
|
||||
{
|
||||
int retval, i;
|
||||
struct MODS_QUERY_IRQ_3 query_irq = { { { { 0 } } } };
|
||||
@@ -1395,7 +1401,7 @@ int esc_mods_irq_handled_2(struct file *pfile,
|
||||
u32 irq = p->dev.bus;
|
||||
struct dev_irq_map *t = NULL;
|
||||
struct dev_irq_map *next = NULL;
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (p->type != MODS_IRQ_TYPE_CPU)
|
||||
return -EINVAL;
|
||||
@@ -1404,8 +1410,8 @@ int esc_mods_irq_handled_2(struct file *pfile,
|
||||
|
||||
/* Identify the caller */
|
||||
client_id = get_client_id(pfile);
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
if (!is_client_id_valid(client_id)) {
|
||||
if (unlikely(!is_client_id_valid(client_id))) {
|
||||
WARN_ON(!is_client_id_valid(client_id));
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1425,7 +1431,7 @@ int esc_mods_irq_handled_2(struct file *pfile,
|
||||
"IRQ type doesn't match registered IRQ\n");
|
||||
} else {
|
||||
enable_irq(irq);
|
||||
ret = OK;
|
||||
err = OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1435,7 +1441,7 @@ int esc_mods_irq_handled_2(struct file *pfile,
|
||||
spin_unlock_irqrestore(&client->irq_lock, flags);
|
||||
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_irq_handled(struct file *pfile,
|
||||
@@ -1454,9 +1460,9 @@ int esc_mods_irq_handled(struct file *pfile,
|
||||
|
||||
#if defined(MODS_TEGRA) && defined(CONFIG_OF_IRQ) && defined(CONFIG_OF)
|
||||
int esc_mods_map_irq(struct file *pfile,
|
||||
struct MODS_DT_INFO *p)
|
||||
struct MODS_DT_INFO *p)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
/* the physical irq */
|
||||
int hwirq;
|
||||
/* platform device handle */
|
||||
@@ -1474,10 +1480,10 @@ int esc_mods_map_irq(struct file *pfile,
|
||||
np = of_find_node_by_name(np, p->dt_name);
|
||||
|
||||
p->irq = irq_of_parse_and_map(np, p->index);
|
||||
ret = of_irq_parse_one(np, p->index, &oirq);
|
||||
if (ret) {
|
||||
err = of_irq_parse_one(np, p->index, &oirq);
|
||||
if (err) {
|
||||
mods_error_printk("Could not parse IRQ\n");
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
hwirq = oirq.args[1];
|
||||
@@ -1499,7 +1505,6 @@ int esc_mods_map_irq(struct file *pfile,
|
||||
}
|
||||
|
||||
/* enable the interrupt */
|
||||
return 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -103,7 +103,7 @@ static const struct pci_device_id mods_pci_table[] = {
|
||||
.class = (PCI_CLASS_DISPLAY_3D << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{ }
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int mods_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
@@ -137,8 +137,6 @@ static u32 access_token = MODS_ACCESS_TOKEN_NONE;
|
||||
#ifdef MODS_HAS_SRIOV
|
||||
static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
@@ -148,57 +146,53 @@ static int mods_pci_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
dev->is_physfn);
|
||||
|
||||
if (numvfs > 0) {
|
||||
rv = pci_enable_sriov(dev, numvfs);
|
||||
if (rv) {
|
||||
mods_error_printk(
|
||||
"pci_enable_sriov failed error %d\n", rv);
|
||||
return rv;
|
||||
}
|
||||
int err = pci_enable_sriov(dev, numvfs);
|
||||
|
||||
rv = numvfs;
|
||||
if (err) {
|
||||
mods_error_printk("pci_enable_sriov failed with %d\n",
|
||||
err);
|
||||
numvfs = 0;
|
||||
}
|
||||
} else {
|
||||
pci_disable_sriov(dev);
|
||||
rv = 0;
|
||||
numvfs = 0;
|
||||
}
|
||||
|
||||
LOG_EXT();
|
||||
return rv;
|
||||
return numvfs;
|
||||
}
|
||||
|
||||
static int esc_mods_set_num_vf(struct file *pfile, struct MODS_SET_NUM_VF *p)
|
||||
{
|
||||
int rv = 0;
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int err;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
/* Get the PCI device structure for the specified device from kernel */
|
||||
devfn = PCI_DEVFN(p->dev.device, p->dev.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->dev.domain, p->dev.bus, devfn);
|
||||
if (!dev) {
|
||||
mods_error_printk(
|
||||
"unknown dev %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->dev.domain,
|
||||
(unsigned int)p->dev.bus,
|
||||
(unsigned int)p->dev.device,
|
||||
(unsigned int)p->dev.function);
|
||||
err = mods_find_pci_dev(pfile, &p->dev, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->dev.domain,
|
||||
p->dev.bus,
|
||||
p->dev.device,
|
||||
p->dev.function);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
rv = mods_pci_sriov_configure(dev, p->numvfs);
|
||||
err = mods_pci_sriov_configure(dev, p->numvfs);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
|
||||
return rv;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_set_total_vf(struct file *pfile, struct MODS_SET_NUM_VF *p)
|
||||
{
|
||||
int rv = 0;
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int err;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -206,30 +200,26 @@ static int esc_mods_set_total_vf(struct file *pfile, struct MODS_SET_NUM_VF *p)
|
||||
"pci_sriov_set_totalvfs(totalvfs=%d)\n", p->numvfs);
|
||||
|
||||
/* Get the PCI device structure for the specified device from kernel */
|
||||
devfn = PCI_DEVFN(p->dev.device, p->dev.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->dev.domain, p->dev.bus, devfn);
|
||||
if (!dev) {
|
||||
mods_error_printk(
|
||||
"unknown dev %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->dev.domain,
|
||||
(unsigned int)p->dev.bus,
|
||||
(unsigned int)p->dev.device,
|
||||
(unsigned int)p->dev.function);
|
||||
err = mods_find_pci_dev(pfile, &p->dev, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->dev.domain,
|
||||
p->dev.bus,
|
||||
p->dev.device,
|
||||
p->dev.function);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rv = pci_sriov_set_totalvfs(dev, p->numvfs);
|
||||
|
||||
if (rv) {
|
||||
mods_error_printk(
|
||||
"pci_sriov_set_totalvfs failed error %d\n", rv);
|
||||
return rv;
|
||||
}
|
||||
err = pci_sriov_set_totalvfs(dev, p->numvfs);
|
||||
if (err)
|
||||
mods_error_printk("pci_sriov_set_totalvfs failed with %d\n",
|
||||
err);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
|
||||
return rv;
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -412,7 +402,7 @@ static void mods_disable_all_devices(struct mods_client *client)
|
||||
if (unlikely(mutex_lock_interruptible(mods_get_irq_mutex())))
|
||||
return;
|
||||
|
||||
while (client->enabled_devices != 0) {
|
||||
while (client->enabled_devices != NULL) {
|
||||
struct en_dev_entry *old = client->enabled_devices;
|
||||
|
||||
mods_disable_device(old->dev);
|
||||
@@ -421,8 +411,13 @@ static void mods_disable_all_devices(struct mods_client *client)
|
||||
}
|
||||
|
||||
mutex_unlock(mods_get_irq_mutex());
|
||||
|
||||
if (client->cached_dev) {
|
||||
pci_dev_put(client->cached_dev);
|
||||
client->cached_dev = NULL;
|
||||
}
|
||||
#else
|
||||
WARN_ON(client->enabled_devices != 0);
|
||||
WARN_ON(client->enabled_devices != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -690,7 +685,7 @@ static int mods_krnl_close(struct inode *ip, struct file *fp)
|
||||
{
|
||||
struct mods_client *client = fp->private_data;
|
||||
u8 client_id = client->client_id;
|
||||
int ret = OK;
|
||||
int err = OK;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -705,17 +700,17 @@ static int mods_krnl_close(struct inode *ip, struct file *fp)
|
||||
mods_resume_console(fp);
|
||||
|
||||
mods_unregister_all_mappings(fp);
|
||||
ret = mods_unregister_all_alloc(fp);
|
||||
if (ret)
|
||||
err = mods_unregister_all_alloc(fp);
|
||||
if (err)
|
||||
mods_error_printk("failed to free all memory\n");
|
||||
|
||||
#if defined(CONFIG_PPC64)
|
||||
ret = mods_unregister_all_ppc_tce_bypass(fp);
|
||||
if (ret)
|
||||
err = mods_unregister_all_ppc_tce_bypass(fp);
|
||||
if (err)
|
||||
mods_error_printk("failed to restore dma bypass\n");
|
||||
|
||||
ret = mods_unregister_all_nvlink_sysmem_trained(fp);
|
||||
if (ret)
|
||||
err = mods_unregister_all_nvlink_sysmem_trained(fp);
|
||||
if (err)
|
||||
mods_error_printk("failed to free nvlink trained\n");
|
||||
#endif
|
||||
|
||||
@@ -725,7 +720,7 @@ static int mods_krnl_close(struct inode *ip, struct file *fp)
|
||||
|
||||
mods_info_printk("driver closed\n");
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static unsigned int mods_krnl_poll(struct file *fp, poll_table *wait)
|
||||
@@ -781,17 +776,17 @@ static int mods_krnl_mmap(struct file *fp, struct vm_area_struct *vma)
|
||||
mods_krnl_vma_open(vma);
|
||||
|
||||
{
|
||||
int ret = OK;
|
||||
int err = OK;
|
||||
struct mods_client *client = fp->private_data;
|
||||
|
||||
if (unlikely(mutex_lock_interruptible(&client->mtx)))
|
||||
ret = -EINTR;
|
||||
err = -EINTR;
|
||||
else {
|
||||
ret = mods_krnl_map_inner(fp, vma);
|
||||
err = mods_krnl_map_inner(fp, vma);
|
||||
mutex_unlock(&client->mtx);
|
||||
}
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,41 +805,37 @@ static int mods_krnl_map_inner(struct file *fp, struct vm_area_struct *vma)
|
||||
/* system memory */
|
||||
if (p_mem_info) {
|
||||
u32 first, i;
|
||||
struct MODS_PHYS_CHUNK *pt = p_mem_info->pages;
|
||||
struct MODS_PHYS_CHUNK *chunks = p_mem_info->pages;
|
||||
u32 have_pages = 0;
|
||||
unsigned long map_va = 0;
|
||||
const pgprot_t prot =
|
||||
mods_get_prot(p_mem_info->cache_type, vma->vm_page_prot);
|
||||
|
||||
/* Find the beginning of the requested range */
|
||||
for (first = 0; first < p_mem_info->max_chunks; first++) {
|
||||
u64 dma_addr;
|
||||
for (first = 0; first < p_mem_info->num_chunks; first++) {
|
||||
u64 dma_addr = chunks[first].dma_addr;
|
||||
u32 size = PAGE_SIZE << chunks[first].order;
|
||||
|
||||
if (!pt[first].allocated)
|
||||
continue;
|
||||
dma_addr = pt[first].dma_addr;
|
||||
if ((req_pa >= dma_addr) &&
|
||||
(req_pa < dma_addr + (PAGE_SIZE << pt->order))) {
|
||||
(req_pa < dma_addr + size)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first == p_mem_info->max_chunks) {
|
||||
if (first == p_mem_info->num_chunks) {
|
||||
mods_error_printk("can't satisfy requested mapping\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Count how many remaining pages we have in the allocation */
|
||||
for (i = first; i < p_mem_info->max_chunks; i++) {
|
||||
if (!pt[i].allocated)
|
||||
break;
|
||||
for (i = first; i < p_mem_info->num_chunks; i++) {
|
||||
if (i == first) {
|
||||
u64 aoffs = req_pa - pt[i].dma_addr;
|
||||
u64 aoffs = req_pa - chunks[i].dma_addr;
|
||||
u32 skip_pages = aoffs >> PAGE_SHIFT;
|
||||
|
||||
have_pages -= skip_pages;
|
||||
}
|
||||
have_pages += 1U << pt[i].order;
|
||||
have_pages += 1U << chunks[i].order;
|
||||
}
|
||||
|
||||
if (have_pages < req_pages) {
|
||||
@@ -856,15 +847,12 @@ static int mods_krnl_map_inner(struct file *fp, struct vm_area_struct *vma)
|
||||
map_va = vma->vm_start;
|
||||
have_pages = req_pages;
|
||||
for (i = first; have_pages > 0; i++) {
|
||||
u64 map_pa = MODS_DMA_TO_PHYS(pt[i].dma_addr);
|
||||
u32 map_size = PAGE_SIZE << pt[i].order;
|
||||
u32 map_pages = 1U << pt[i].order;
|
||||
|
||||
if (!pt[i].allocated)
|
||||
break;
|
||||
u64 map_pa = MODS_DMA_TO_PHYS(chunks[i].dma_addr);
|
||||
u32 map_size = PAGE_SIZE << chunks[i].order;
|
||||
u32 map_pages = 1U << chunks[i].order;
|
||||
|
||||
if (i == first) {
|
||||
u64 aoffs = req_pa - pt[i].dma_addr;
|
||||
u64 aoffs = req_pa - chunks[i].dma_addr;
|
||||
|
||||
map_pa += aoffs;
|
||||
map_size -= aoffs;
|
||||
@@ -899,7 +887,7 @@ static int mods_krnl_map_inner(struct file *fp, struct vm_area_struct *vma)
|
||||
*/
|
||||
mods_register_mapping(fp,
|
||||
p_mem_info,
|
||||
pt[first].dma_addr,
|
||||
chunks[first].dma_addr,
|
||||
vma->vm_start,
|
||||
MODS_VMA_SIZE(vma));
|
||||
|
||||
@@ -1034,7 +1022,7 @@ static int esc_mods_unlock_console(struct file *pfile)
|
||||
|
||||
static int esc_mods_suspend_console(struct file *pfile)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -1052,7 +1040,7 @@ static int esc_mods_suspend_console(struct file *pfile)
|
||||
}
|
||||
console_unlock();
|
||||
}
|
||||
ret = OK;
|
||||
err = OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1064,13 +1052,13 @@ static int esc_mods_suspend_console(struct file *pfile)
|
||||
console_lock();
|
||||
do_take_over_console(&dummy_con, 0, 0, 0);
|
||||
console_unlock();
|
||||
ret = OK;
|
||||
err = OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_resume_console(struct file *pfile)
|
||||
@@ -1080,7 +1068,7 @@ static int esc_mods_resume_console(struct file *pfile)
|
||||
|
||||
static int mods_resume_console(struct file *pfile)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -1097,7 +1085,7 @@ static int mods_resume_console(struct file *pfile)
|
||||
}
|
||||
console_unlock();
|
||||
}
|
||||
ret = OK;
|
||||
err = OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1109,19 +1097,19 @@ static int mods_resume_console(struct file *pfile)
|
||||
console_lock();
|
||||
do_unbind_con_driver(vc_cons[fg_console].d->vc_sw, 0, 0, 0);
|
||||
console_unlock();
|
||||
ret = OK;
|
||||
err = OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_acquire_access_token(struct file *pfile,
|
||||
struct MODS_ACCESS_TOKEN *ptoken)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -1129,14 +1117,14 @@ static int esc_mods_acquire_access_token(struct file *pfile,
|
||||
LOG_EXT();
|
||||
mods_error_printk(
|
||||
"access token ops not supported with multi_instance=1!\n");
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
get_random_bytes(&ptoken->token, sizeof(ptoken->token));
|
||||
ret = mods_set_access_token(ptoken->token);
|
||||
if (ret < 0) {
|
||||
err = mods_set_access_token(ptoken->token);
|
||||
if (err)
|
||||
mods_error_printk("unable to set access token!\n");
|
||||
} else {
|
||||
else {
|
||||
struct mods_client *client = pfile->private_data;
|
||||
|
||||
client->access_token = ptoken->token;
|
||||
@@ -1144,13 +1132,13 @@ static int esc_mods_acquire_access_token(struct file *pfile,
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_release_access_token(struct file *pfile,
|
||||
struct MODS_ACCESS_TOKEN *ptoken)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -1158,13 +1146,13 @@ static int esc_mods_release_access_token(struct file *pfile,
|
||||
LOG_EXT();
|
||||
mods_error_printk(
|
||||
"access token ops not supported with multi_instance=1!\n");
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
ret = mods_set_access_token(MODS_ACCESS_TOKEN_NONE);
|
||||
if (ret < 0) {
|
||||
err = mods_set_access_token(MODS_ACCESS_TOKEN_NONE);
|
||||
if (err)
|
||||
mods_error_printk("unable to clear access token!\n");
|
||||
} else {
|
||||
else {
|
||||
struct mods_client *client = pfile->private_data;
|
||||
|
||||
client->access_token = MODS_ACCESS_TOKEN_NONE;
|
||||
@@ -1172,13 +1160,13 @@ static int esc_mods_release_access_token(struct file *pfile,
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_verify_access_token(struct file *pfile,
|
||||
struct MODS_ACCESS_TOKEN *ptoken)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
@@ -1186,19 +1174,19 @@ static int esc_mods_verify_access_token(struct file *pfile,
|
||||
struct mods_client *client = pfile->private_data;
|
||||
|
||||
client->access_token = ptoken->token;
|
||||
ret = OK;
|
||||
err = OK;
|
||||
} else
|
||||
mods_error_printk("invalid access token\n");
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
struct mods_sysfs_work {
|
||||
struct work_struct work;
|
||||
struct MODS_SYSFS_NODE *pdata;
|
||||
int ret;
|
||||
int err;
|
||||
};
|
||||
|
||||
#ifdef MODS_OLD_INIT_WORK
|
||||
@@ -1215,18 +1203,18 @@ static void sysfs_write_task(struct work_struct *w)
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
task->ret = -EINVAL;
|
||||
task->err = -EINVAL;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
f = filp_open(task->pdata->path, O_WRONLY, 0);
|
||||
if (IS_ERR(f))
|
||||
task->ret = PTR_ERR(f);
|
||||
task->err = PTR_ERR(f);
|
||||
else {
|
||||
f->f_pos = 0;
|
||||
if (task->pdata->size <= MODS_MAX_SYSFS_FILE_SIZE)
|
||||
task->ret = f->f_op->write(f,
|
||||
task->err = f->f_op->write(f,
|
||||
task->pdata->contents,
|
||||
task->pdata->size,
|
||||
&f->f_pos);
|
||||
@@ -1241,7 +1229,7 @@ static void sysfs_write_task(struct work_struct *w)
|
||||
static int esc_mods_write_sysfs_node(struct file *pfile,
|
||||
struct MODS_SYSFS_NODE *pdata)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
struct mods_sysfs_work task;
|
||||
struct workqueue_struct *wq;
|
||||
|
||||
@@ -1256,7 +1244,7 @@ static int esc_mods_write_sysfs_node(struct file *pfile,
|
||||
wq = create_singlethread_workqueue("mods_sysfs_write");
|
||||
if (!wq) {
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef MODS_OLD_INIT_WORK
|
||||
@@ -1268,41 +1256,41 @@ static int esc_mods_write_sysfs_node(struct file *pfile,
|
||||
flush_workqueue(wq);
|
||||
destroy_workqueue(wq);
|
||||
|
||||
ret = task.ret;
|
||||
if (ret > 0)
|
||||
ret = OK;
|
||||
err = task.err;
|
||||
if (err > 0)
|
||||
err = OK;
|
||||
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef MODS_HAS_MSR
|
||||
static int esc_mods_read_msr(struct file *pfile, struct MODS_MSR *p)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
ret = rdmsr_safe_on_cpu(p->cpu_num, p->reg, &p->low, &p->high);
|
||||
if (ret < 0)
|
||||
err = rdmsr_safe_on_cpu(p->cpu_num, p->reg, &p->low, &p->high);
|
||||
if (err)
|
||||
mods_error_printk("Could not read MSR %u\n", p->reg);
|
||||
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esc_mods_write_msr(struct file *pfile, struct MODS_MSR *p)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
ret = wrmsr_safe_on_cpu(p->cpu_num, p->reg, p->low, p->high);
|
||||
if (ret < 0)
|
||||
err = wrmsr_safe_on_cpu(p->cpu_num, p->reg, p->low, p->high);
|
||||
if (err)
|
||||
mods_error_printk("Could not write MSR %u\n", p->reg);
|
||||
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1314,7 +1302,7 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
unsigned int cmd,
|
||||
unsigned long i_arg)
|
||||
{
|
||||
int ret = 0;
|
||||
int err = 0;
|
||||
void *arg_copy = 0;
|
||||
void *arg = (void *) i_arg;
|
||||
int arg_size;
|
||||
@@ -1324,10 +1312,10 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
|
||||
if ((cmd != MODS_ESC_VERIFY_ACCESS_TOKEN) &&
|
||||
(cmd != MODS_ESC_GET_API_VERSION)) {
|
||||
ret = mods_check_access_token(fp);
|
||||
if (ret < 0) {
|
||||
err = mods_check_access_token(fp);
|
||||
if (err) {
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1354,15 +1342,15 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
do {\
|
||||
mods_debug_printk(DEBUG_IOCTL, "ioctl(" #code ")\n");\
|
||||
if (arg_size != sizeof(struct argtype)) {\
|
||||
ret = -EINVAL;\
|
||||
err = -EINVAL;\
|
||||
mods_error_printk( \
|
||||
"invalid parameter passed to ioctl " #code \
|
||||
"\n");\
|
||||
} else {\
|
||||
ret = function(fp, (struct argtype *)arg_copy);\
|
||||
if ((ret == OK) && \
|
||||
err = function(fp, (struct argtype *)arg_copy);\
|
||||
if ((err == OK) && \
|
||||
copy_to_user(arg, arg_copy, arg_size)) {\
|
||||
ret = -EFAULT;\
|
||||
err = -EFAULT;\
|
||||
mods_error_printk( \
|
||||
"copying return value for ioctl " \
|
||||
#code " to user space failed\n");\
|
||||
@@ -1376,12 +1364,12 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
do {\
|
||||
mods_debug_printk(DEBUG_IOCTL, "ioctl(" #code ")\n");\
|
||||
if (arg_size != sizeof(struct argtype)) {\
|
||||
ret = -EINVAL;\
|
||||
err = -EINVAL;\
|
||||
mods_error_printk( \
|
||||
"invalid parameter passed to ioctl " #code \
|
||||
"\n");\
|
||||
} else {\
|
||||
ret = function(fp, (struct argtype *)arg_copy);\
|
||||
err = function(fp, (struct argtype *)arg_copy);\
|
||||
} \
|
||||
} while (0);\
|
||||
})
|
||||
@@ -1391,12 +1379,12 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
do {\
|
||||
mods_debug_printk(DEBUG_IOCTL, "ioctl(" #code ")\n");\
|
||||
if (arg_size != 0) {\
|
||||
ret = -EINVAL;\
|
||||
err = -EINVAL;\
|
||||
mods_error_printk( \
|
||||
"invalid parameter passed to ioctl " #code \
|
||||
"\n");\
|
||||
} else {\
|
||||
ret = function(fp);\
|
||||
err = function(fp);\
|
||||
} \
|
||||
} while (0);\
|
||||
})
|
||||
@@ -1558,6 +1546,12 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
MODS_GET_PHYSICAL_ADDRESS_3);
|
||||
break;
|
||||
|
||||
case MODS_ESC_GET_PHYSICAL_ADDRESS_RANGE:
|
||||
MODS_IOCTL(MODS_ESC_GET_PHYSICAL_ADDRESS_RANGE,
|
||||
esc_mods_get_phys_addr_range,
|
||||
MODS_GET_ADDRESS_RANGE);
|
||||
break;
|
||||
|
||||
case MODS_ESC_GET_MAPPED_PHYSICAL_ADDRESS:
|
||||
MODS_IOCTL(MODS_ESC_GET_MAPPED_PHYSICAL_ADDRESS,
|
||||
esc_mods_get_mapped_phys_addr,
|
||||
@@ -1576,6 +1570,12 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
MODS_GET_PHYSICAL_ADDRESS_3);
|
||||
break;
|
||||
|
||||
case MODS_ESC_GET_DMA_ADDRESS_RANGE:
|
||||
MODS_IOCTL(MODS_ESC_GET_DMA_ADDRESS_RANGE,
|
||||
esc_mods_get_dma_addr_range,
|
||||
MODS_GET_ADDRESS_RANGE);
|
||||
break;
|
||||
|
||||
case MODS_ESC_SET_MEMORY_TYPE:
|
||||
MODS_IOCTL_NORETVAL(MODS_ESC_SET_MEMORY_TYPE,
|
||||
esc_mods_set_mem_type,
|
||||
@@ -1617,6 +1617,7 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
case MODS_ESC_DMA_MAP_MEMORY:
|
||||
MODS_IOCTL(MODS_ESC_DMA_MAP_MEMORY,
|
||||
esc_mods_dma_map_memory,
|
||||
@@ -1628,10 +1629,11 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
esc_mods_dma_unmap_memory,
|
||||
MODS_DMA_MAP_MEMORY);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case MODS_ESC_IRQ_REGISTER:
|
||||
case MODS_ESC_MSI_REGISTER:
|
||||
ret = -EINVAL;
|
||||
err = -EINVAL;
|
||||
break;
|
||||
|
||||
case MODS_ESC_MAP_INTERRUPT:
|
||||
@@ -1727,7 +1729,7 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
/* fallthrough */
|
||||
case MODS_ESC_ACPI_GET_DDC_2:
|
||||
/* Silent failure to avoid clogging kernel log */
|
||||
ret = -EINVAL;
|
||||
err = -EINVAL;
|
||||
break;
|
||||
#endif
|
||||
case MODS_ESC_GET_API_VERSION:
|
||||
@@ -2036,7 +2038,7 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
mods_error_printk("unrecognized ioctl (0x%x) dir(0x%x) type (0x%x) nr (0x%x) size (0x%x)\n",
|
||||
cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd),
|
||||
_IOC_NR(cmd), _IOC_SIZE(cmd));
|
||||
ret = -EINVAL;
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2044,5 +2046,5 @@ static long mods_krnl_ioctl(struct file *fp,
|
||||
kfree(arg_copy);
|
||||
|
||||
LOG_EXT();
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,17 +26,81 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#endif
|
||||
|
||||
/************************
|
||||
* PCI ESCAPE FUNCTIONS *
|
||||
************************/
|
||||
int mods_is_pci_dev(struct pci_dev *dev,
|
||||
struct mods_pci_dev_2 *pcidev)
|
||||
{
|
||||
unsigned int devfn = PCI_DEVFN(pcidev->device, pcidev->function);
|
||||
|
||||
static int mods_find_pci_dev(struct file *pfile,
|
||||
return dev &&
|
||||
pci_domain_nr(dev->bus) == pcidev->domain &&
|
||||
dev->bus->number == pcidev->bus &&
|
||||
dev->devfn == devfn;
|
||||
}
|
||||
|
||||
int mods_find_pci_dev(struct file *fp,
|
||||
struct mods_pci_dev_2 *pcidev,
|
||||
struct pci_dev **retdev)
|
||||
{
|
||||
struct mods_client *client = fp->private_data;
|
||||
struct pci_dev *dev;
|
||||
int err;
|
||||
|
||||
if (unlikely(mutex_lock_interruptible(&client->mtx)))
|
||||
return -EINTR;
|
||||
|
||||
dev = client->cached_dev;
|
||||
|
||||
if (mods_is_pci_dev(dev, pcidev)) {
|
||||
*retdev = pci_dev_get(dev);
|
||||
mutex_unlock(&client->mtx);
|
||||
return OK;
|
||||
}
|
||||
|
||||
mutex_unlock(&client->mtx);
|
||||
|
||||
dev = NULL;
|
||||
|
||||
#ifdef MODS_HAS_NEW_ACPI_WALK
|
||||
dev = pci_get_domain_bus_and_slot(pcidev->domain,
|
||||
pcidev->bus,
|
||||
PCI_DEVFN(pcidev->device,
|
||||
pcidev->function));
|
||||
#else
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
|
||||
if (mods_is_pci_dev(dev, pcidev))
|
||||
break;
|
||||
#endif
|
||||
|
||||
if (dev) {
|
||||
if (unlikely(mutex_lock_interruptible(&client->mtx))) {
|
||||
pci_dev_put(dev);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (dev != client->cached_dev) {
|
||||
pci_dev_put(client->cached_dev);
|
||||
client->cached_dev = pci_dev_get(dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&client->mtx);
|
||||
|
||||
err = OK;
|
||||
} else
|
||||
err = -ENODEV;
|
||||
|
||||
*retdev = dev;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int find_pci_dev_impl(struct file *pfile,
|
||||
struct MODS_FIND_PCI_DEVICE_2 *p,
|
||||
int enum_non_zero_dom)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
int index = -1;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"find pci dev %04x:%04x, index %d\n",
|
||||
(int) p->vendor_id,
|
||||
@@ -45,8 +109,10 @@ static int mods_find_pci_dev(struct file *pfile,
|
||||
|
||||
do {
|
||||
dev = pci_get_device(p->vendor_id, p->device_id, dev);
|
||||
if (!dev)
|
||||
if (!dev) {
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (enum_non_zero_dom || !pci_domain_nr(dev->bus))
|
||||
++index;
|
||||
@@ -57,34 +123,36 @@ static int mods_find_pci_dev(struct file *pfile,
|
||||
p->pci_device.device = PCI_SLOT(dev->devfn);
|
||||
p->pci_device.function = PCI_FUNC(dev->devfn);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int esc_mods_find_pci_dev_2(struct file *pfile,
|
||||
struct MODS_FIND_PCI_DEVICE_2 *p)
|
||||
{
|
||||
return mods_find_pci_dev(pfile, p, 1);
|
||||
return find_pci_dev_impl(pfile, p, 1);
|
||||
}
|
||||
|
||||
int esc_mods_find_pci_dev(struct file *pfile,
|
||||
struct MODS_FIND_PCI_DEVICE *p)
|
||||
{
|
||||
struct MODS_FIND_PCI_DEVICE_2 p2;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
p2.device_id = p->device_id;
|
||||
p2.vendor_id = p->vendor_id;
|
||||
p2.index = p->index;
|
||||
|
||||
ret = mods_find_pci_dev(pfile, &p2, 0);
|
||||
err = find_pci_dev_impl(pfile, &p2, 0);
|
||||
|
||||
if (!ret) {
|
||||
if (!err) {
|
||||
p->bus_number = p2.pci_device.bus;
|
||||
p->device_number = p2.pci_device.device;
|
||||
p->function_number = p2.pci_device.function;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mods_find_pci_class_code(struct file *pfile,
|
||||
@@ -94,13 +162,17 @@ static int mods_find_pci_class_code(struct file *pfile,
|
||||
struct pci_dev *dev = NULL;
|
||||
int index = -1;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_PCI, "find pci class code %04x, index %d\n",
|
||||
(int) p->class_code, (int) p->index);
|
||||
(unsigned int)p->class_code, (int)p->index);
|
||||
|
||||
do {
|
||||
dev = pci_get_class(p->class_code, dev);
|
||||
if (!dev)
|
||||
if (!dev) {
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (enum_non_zero_dom || !pci_domain_nr(dev->bus))
|
||||
++index;
|
||||
@@ -111,6 +183,8 @@ static int mods_find_pci_class_code(struct file *pfile,
|
||||
p->pci_device.device = PCI_SLOT(dev->devfn);
|
||||
p->pci_device.function = PCI_FUNC(dev->devfn);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -124,58 +198,66 @@ int esc_mods_find_pci_class_code(struct file *pfile,
|
||||
struct MODS_FIND_PCI_CLASS_CODE *p)
|
||||
{
|
||||
struct MODS_FIND_PCI_CLASS_CODE_2 p2;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
p2.class_code = p->class_code;
|
||||
p2.index = p->index;
|
||||
|
||||
ret = mods_find_pci_class_code(pfile, &p2, 0);
|
||||
err = mods_find_pci_class_code(pfile, &p2, 0);
|
||||
|
||||
if (!ret) {
|
||||
if (!err) {
|
||||
p->bus_number = p2.pci_device.bus;
|
||||
p->device_number = p2.pci_device.device;
|
||||
p->function_number = p2.pci_device.function;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_get_bar_info_2(struct file *pfile,
|
||||
struct MODS_PCI_GET_BAR_INFO_2 *p)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn, bar_resource_offset, i;
|
||||
unsigned int bar_resource_offset;
|
||||
unsigned int i;
|
||||
int err;
|
||||
#if !defined(MODS_HAS_IORESOURCE_MEM_64)
|
||||
__u32 temp;
|
||||
#endif
|
||||
|
||||
devfn = PCI_DEVFN(p->pci_device.device, p->pci_device.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->pci_device.domain, p->pci_device.bus, devfn);
|
||||
LOG_ENT();
|
||||
|
||||
if (dev == NULL)
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"pci get bar info %04x:%02x:%02x:%x, bar index %d\n",
|
||||
(int) p->pci_device.domain,
|
||||
(int) p->pci_device.bus, (int) p->pci_device.device,
|
||||
(int) p->pci_device.function, (int) p->bar_index);
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function,
|
||||
p->bar_index);
|
||||
|
||||
#if defined(CONFIG_PPC64)
|
||||
if (unlikely(mutex_lock_interruptible(mods_get_irq_mutex()))) {
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
/* Enable device on the PCI bus */
|
||||
if (mods_enable_device(pfile->private_data, dev) == 0) {
|
||||
mods_error_printk(
|
||||
"unable to enable dev %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->pci_device.domain,
|
||||
(unsigned int)p->pci_device.bus,
|
||||
(unsigned int)p->pci_device.device,
|
||||
(unsigned int)p->pci_device.function);
|
||||
mods_error_printk("unable to enable dev %04x:%02x:%02x.%x\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
mutex_unlock(mods_get_irq_mutex());
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -202,89 +284,102 @@ int esc_mods_pci_get_bar_info_2(struct file *pfile,
|
||||
p->base_address = pci_resource_start(dev, bar_resource_offset);
|
||||
p->bar_size = pci_resource_len(dev, bar_resource_offset);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int esc_mods_pci_get_bar_info(struct file *pfile,
|
||||
struct MODS_PCI_GET_BAR_INFO *p)
|
||||
{
|
||||
int retval;
|
||||
int err;
|
||||
struct MODS_PCI_GET_BAR_INFO_2 get_bar_info = { {0} };
|
||||
|
||||
get_bar_info.pci_device.domain = 0;
|
||||
get_bar_info.pci_device.bus = p->pci_device.bus;
|
||||
get_bar_info.pci_device.device = p->pci_device.device;
|
||||
get_bar_info.pci_device.function = p->pci_device.function;
|
||||
get_bar_info.bar_index = p->bar_index;
|
||||
get_bar_info.pci_device.domain = 0;
|
||||
get_bar_info.pci_device.bus = p->pci_device.bus;
|
||||
get_bar_info.pci_device.device = p->pci_device.device;
|
||||
get_bar_info.pci_device.function = p->pci_device.function;
|
||||
get_bar_info.bar_index = p->bar_index;
|
||||
|
||||
retval = esc_mods_pci_get_bar_info_2(pfile, &get_bar_info);
|
||||
if (retval)
|
||||
return retval;
|
||||
err = esc_mods_pci_get_bar_info_2(pfile, &get_bar_info);
|
||||
|
||||
p->base_address = get_bar_info.base_address;
|
||||
p->bar_size = get_bar_info.bar_size;
|
||||
return OK;
|
||||
if (likely(!err)) {
|
||||
p->base_address = get_bar_info.base_address;
|
||||
p->bar_size = get_bar_info.bar_size;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_get_irq_2(struct file *pfile,
|
||||
struct MODS_PCI_GET_IRQ_2 *p)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int err;
|
||||
|
||||
devfn = PCI_DEVFN(p->pci_device.device, p->pci_device.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->pci_device.domain, p->pci_device.bus, devfn);
|
||||
LOG_ENT();
|
||||
|
||||
if (dev == NULL)
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"pci get irq %04x:%02x:%02x:%x\n",
|
||||
(int) p->pci_device.domain,
|
||||
(int) p->pci_device.bus, (int) p->pci_device.device,
|
||||
(int) p->pci_device.function);
|
||||
"pci get irq %04x:%02x:%02x:%x irq=%u\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function,
|
||||
dev->irq);
|
||||
|
||||
p->irq = dev->irq;
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int esc_mods_pci_get_irq(struct file *pfile,
|
||||
struct MODS_PCI_GET_IRQ *p)
|
||||
{
|
||||
int retval;
|
||||
int err;
|
||||
struct MODS_PCI_GET_IRQ_2 get_irq = { {0} };
|
||||
|
||||
get_irq.pci_device.domain = 0;
|
||||
get_irq.pci_device.bus = p->pci_device.bus;
|
||||
get_irq.pci_device.device = p->pci_device.device;
|
||||
get_irq.pci_device.function = p->pci_device.function;
|
||||
get_irq.pci_device.domain = 0;
|
||||
get_irq.pci_device.bus = p->pci_device.bus;
|
||||
get_irq.pci_device.device = p->pci_device.device;
|
||||
get_irq.pci_device.function = p->pci_device.function;
|
||||
|
||||
retval = esc_mods_pci_get_irq_2(pfile, &get_irq);
|
||||
if (retval)
|
||||
return retval;
|
||||
err = esc_mods_pci_get_irq_2(pfile, &get_irq);
|
||||
|
||||
p->irq = get_irq.irq;
|
||||
return OK;
|
||||
if (likely(!err))
|
||||
p->irq = get_irq.irq;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_read_2(struct file *pfile, struct MODS_PCI_READ_2 *p)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int err;
|
||||
|
||||
devfn = PCI_DEVFN(p->pci_device.device, p->pci_device.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->pci_device.domain, p->pci_device.bus, devfn);
|
||||
LOG_ENT();
|
||||
|
||||
if (dev == NULL)
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"pci read %04x:%02x:%02x.%x, addr 0x%04x, size %d\n",
|
||||
(int) p->pci_device.domain,
|
||||
(int) p->pci_device.bus, (int) p->pci_device.device,
|
||||
(int) p->pci_device.function, (int) p->address,
|
||||
(int) p->data_size);
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function,
|
||||
p->address,
|
||||
p->data_size);
|
||||
|
||||
p->data = 0;
|
||||
switch (p->data_size) {
|
||||
@@ -306,14 +401,18 @@ int esc_mods_pci_read_2(struct file *pfile, struct MODS_PCI_READ_2 *p)
|
||||
pci_read_config_dword(dev, p->address, (u32 *) &p->data);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return OK;
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_read(struct file *pfile, struct MODS_PCI_READ *p)
|
||||
{
|
||||
int retval;
|
||||
int err;
|
||||
struct MODS_PCI_READ_2 pci_read = { {0} };
|
||||
|
||||
pci_read.pci_device.domain = 0;
|
||||
@@ -323,39 +422,41 @@ int esc_mods_pci_read(struct file *pfile, struct MODS_PCI_READ *p)
|
||||
pci_read.address = p->address;
|
||||
pci_read.data_size = p->data_size;
|
||||
|
||||
retval = esc_mods_pci_read_2(pfile, &pci_read);
|
||||
if (retval)
|
||||
return retval;
|
||||
err = esc_mods_pci_read_2(pfile, &pci_read);
|
||||
|
||||
p->data = pci_read.data;
|
||||
return OK;
|
||||
if (likely(!err))
|
||||
p->data = pci_read.data;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_write_2(struct file *pfile, struct MODS_PCI_WRITE_2 *p)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int err;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"pci write %04x:%02x:%02x.%x, addr 0x%04x, size %d, data 0x%x\n",
|
||||
(int) p->pci_device.domain,
|
||||
(int) p->pci_device.bus, (int) p->pci_device.device,
|
||||
(int) p->pci_device.function,
|
||||
(int) p->address, (int) p->data_size, (int) p->data);
|
||||
"pci write %04x:%02x:%02x.%x, addr 0x%04x, size %d, data 0x%x\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function,
|
||||
p->address,
|
||||
p->data_size,
|
||||
p->data);
|
||||
|
||||
devfn = PCI_DEVFN(p->pci_device.device, p->pci_device.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->pci_device.domain, p->pci_device.bus, devfn);
|
||||
|
||||
if (dev == NULL) {
|
||||
mods_error_printk(
|
||||
"pci write to %04x:%02x:%02x.%x, addr 0x%04x, size %d failed\n",
|
||||
(unsigned int)p->pci_device.domain,
|
||||
(unsigned int)p->pci_device.bus,
|
||||
(unsigned int)p->pci_device.device,
|
||||
(unsigned int)p->pci_device.function,
|
||||
(unsigned int)p->address,
|
||||
(int)p->data_size);
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (p->data_size) {
|
||||
@@ -369,9 +470,13 @@ int esc_mods_pci_write_2(struct file *pfile, struct MODS_PCI_WRITE_2 *p)
|
||||
pci_write_config_dword(dev, p->address, p->data);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return OK;
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_write(struct file *pfile,
|
||||
@@ -393,19 +498,32 @@ int esc_mods_pci_write(struct file *pfile,
|
||||
int esc_mods_pci_bus_add_dev(struct file *pfile,
|
||||
struct MODS_PCI_BUS_ADD_DEVICES *scan)
|
||||
{
|
||||
#if defined(CONFIG_PCI)
|
||||
mods_info_printk("scanning pci bus %x\n", scan->bus);
|
||||
struct pci_bus *bus;
|
||||
int err = OK;
|
||||
|
||||
/* initiate a PCI bus scan to find hotplugged PCI devices in domain 0 */
|
||||
pci_scan_child_bus(pci_find_bus(0, scan->bus));
|
||||
LOG_ENT();
|
||||
|
||||
/* add newly found devices */
|
||||
pci_bus_add_devices(pci_find_bus(0, scan->bus));
|
||||
mods_info_printk("scanning pci bus %02x\n", scan->bus);
|
||||
|
||||
return OK;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
bus = pci_find_bus(0, scan->bus);
|
||||
|
||||
if (likely(bus)) {
|
||||
|
||||
/* initiate a PCI bus scan to find hotplugged PCI devices
|
||||
* in domain 0
|
||||
*/
|
||||
pci_scan_child_bus(bus);
|
||||
|
||||
/* add newly found devices */
|
||||
pci_bus_add_devices(bus);
|
||||
} else {
|
||||
mods_error_printk("bus %02x not found\n", scan->bus);
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
LOG_EXT();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_pci_hot_reset(struct file *pfile,
|
||||
@@ -413,52 +531,50 @@ int esc_mods_pci_hot_reset(struct file *pfile,
|
||||
{
|
||||
#if defined(CONFIG_PPC64)
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn;
|
||||
int retval;
|
||||
int err;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_PCI,
|
||||
"pci_hot_reset %04x:%02x:%02x.%x\n",
|
||||
(int) p->pci_device.domain,
|
||||
(int) p->pci_device.bus,
|
||||
(int) p->pci_device.device,
|
||||
(int) p->pci_device.function);
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
|
||||
devfn = PCI_DEVFN(p->pci_device.device, p->pci_device.function);
|
||||
dev = MODS_PCI_GET_SLOT(p->pci_device.domain, p->pci_device.bus, devfn);
|
||||
|
||||
if (dev == NULL) {
|
||||
mods_error_printk(
|
||||
"pci_hot_reset cannot find pci device %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->pci_device.domain,
|
||||
(unsigned int)p->pci_device.bus,
|
||||
(unsigned int)p->pci_device.device,
|
||||
(unsigned int)p->pci_device.function);
|
||||
return -EINVAL;
|
||||
err = mods_find_pci_dev(pfile, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("pci_hot_reset cannot find pci device %04x:%02x:%02x.%x\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
retval = pci_set_pcie_reset_state(dev, pcie_hot_reset);
|
||||
if (retval) {
|
||||
mods_error_printk(
|
||||
"pci_hot_reset failed on %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->pci_device.domain,
|
||||
(unsigned int)p->pci_device.bus,
|
||||
(unsigned int)p->pci_device.device,
|
||||
(unsigned int)p->pci_device.function);
|
||||
return retval;
|
||||
err = pci_set_pcie_reset_state(dev, pcie_hot_reset);
|
||||
if (unlikely(err))
|
||||
mods_error_printk("pci_hot_reset failed on %04x:%02x:%02x.%x\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
else {
|
||||
|
||||
err = pci_set_pcie_reset_state(dev, pcie_deassert_reset);
|
||||
if (unlikely(err))
|
||||
mods_error_printk("pci_hot_reset deassert failed on %04x:%02x:%02x.%x\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
}
|
||||
|
||||
retval = pci_set_pcie_reset_state(dev, pcie_deassert_reset);
|
||||
if (retval) {
|
||||
mods_error_printk(
|
||||
"pci_hot_reset deassert failed on %04x:%02x:%02x.%x\n",
|
||||
(unsigned int)p->pci_device.domain,
|
||||
(unsigned int)p->pci_device.bus,
|
||||
(unsigned int)p->pci_device.device,
|
||||
(unsigned int)p->pci_device.function);
|
||||
return retval;
|
||||
}
|
||||
|
||||
return OK;
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
@@ -512,24 +628,25 @@ int esc_mods_device_numa_info_2(struct file *fp,
|
||||
struct MODS_DEVICE_NUMA_INFO_2 *p)
|
||||
{
|
||||
#ifdef MODS_HAS_DEV_TO_NUMA_NODE
|
||||
unsigned int devfn = PCI_DEVFN(p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
struct pci_dev *dev = MODS_PCI_GET_SLOT(p->pci_device.domain,
|
||||
p->pci_device.bus, devfn);
|
||||
struct pci_dev *dev;
|
||||
int err;
|
||||
|
||||
LOG_ENT();
|
||||
|
||||
if (dev == NULL) {
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus, p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
err = mods_find_pci_dev(fp, &p->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
p->pci_device.domain,
|
||||
p->pci_device.bus,
|
||||
p->pci_device.device,
|
||||
p->pci_device.function);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
return err;
|
||||
}
|
||||
|
||||
p->node = dev_to_node(&dev->dev);
|
||||
if (-1 != p->node) {
|
||||
if (p->node != -1) {
|
||||
const unsigned long *maskp
|
||||
= cpumask_bits(cpumask_of_node(p->node));
|
||||
unsigned int i, word, bit, maskidx;
|
||||
@@ -537,6 +654,7 @@ int esc_mods_device_numa_info_2(struct file *fp,
|
||||
if (((nr_cpumask_bits + 31) / 32) > MAX_CPU_MASKS) {
|
||||
mods_error_printk("too many CPUs (%d) for mask bits\n",
|
||||
nr_cpumask_bits);
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -553,6 +671,7 @@ int esc_mods_device_numa_info_2(struct file *fp,
|
||||
p->node_count = num_possible_nodes();
|
||||
p->cpu_count = num_possible_cpus();
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return OK;
|
||||
#else
|
||||
@@ -563,7 +682,8 @@ int esc_mods_device_numa_info_2(struct file *fp,
|
||||
int esc_mods_device_numa_info(struct file *fp,
|
||||
struct MODS_DEVICE_NUMA_INFO *p)
|
||||
{
|
||||
int retval, i;
|
||||
int err;
|
||||
int i;
|
||||
struct MODS_DEVICE_NUMA_INFO_2 numa_info = { {0} };
|
||||
|
||||
numa_info.pci_device.domain = 0;
|
||||
@@ -571,16 +691,17 @@ int esc_mods_device_numa_info(struct file *fp,
|
||||
numa_info.pci_device.device = p->pci_device.device;
|
||||
numa_info.pci_device.function = p->pci_device.function;
|
||||
|
||||
retval = esc_mods_device_numa_info_2(fp, &numa_info);
|
||||
if (retval)
|
||||
return retval;
|
||||
err = esc_mods_device_numa_info_2(fp, &numa_info);
|
||||
|
||||
p->node = numa_info.node;
|
||||
p->node_count = numa_info.node_count;
|
||||
for (i = 0; i < MAX_CPU_MASKS; i++)
|
||||
p->node_cpu_mask[i] = numa_info.node_cpu_mask[i];
|
||||
p->cpu_count = numa_info.cpu_count;
|
||||
return OK;
|
||||
if (likely(!err)) {
|
||||
p->node = numa_info.node;
|
||||
p->node_count = numa_info.node_count;
|
||||
p->cpu_count = numa_info.cpu_count;
|
||||
for (i = 0; i < MAX_CPU_MASKS; i++)
|
||||
p->node_cpu_mask[i] = numa_info.node_cpu_mask[i];
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int esc_mods_get_iommu_state(struct file *pfile,
|
||||
@@ -602,13 +723,19 @@ int esc_mods_get_iommu_state_2(struct file *pfile,
|
||||
#elif defined(MODS_HAS_DMA_OPS) && \
|
||||
(defined(MODS_HAS_NONCOH_DMA_OPS) || defined(MODS_HAS_MAP_SG_ATTRS))
|
||||
|
||||
unsigned int devfn = PCI_DEVFN(state->pci_device.device,
|
||||
state->pci_device.function);
|
||||
struct pci_dev *dev = MODS_PCI_GET_SLOT(state->pci_device.domain,
|
||||
state->pci_device.bus,
|
||||
devfn);
|
||||
const struct dma_map_ops *ops;
|
||||
struct pci_dev *dev;
|
||||
int err;
|
||||
|
||||
const struct dma_map_ops *ops = get_dma_ops(&dev->dev);
|
||||
LOG_ENT();
|
||||
|
||||
err = mods_find_pci_dev(pfile, &state->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
ops = get_dma_ops(&dev->dev);
|
||||
|
||||
#if defined(MODS_HAS_NONCOH_DMA_OPS)
|
||||
state->state = (ops != &noncoherent_swiotlb_dma_ops &&
|
||||
@@ -618,6 +745,9 @@ int esc_mods_get_iommu_state_2(struct file *pfile,
|
||||
state->state = ops->map_sg != swiotlb_map_sg_attrs
|
||||
? MODS_SWIOTLB_DISABLED : MODS_SWIOTLB_ACTIVE;
|
||||
#endif
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
|
||||
#elif defined(CONFIG_PPC64) || defined(CONFIG_ARM64)
|
||||
/* No way to detect, assume SW I/O TLB is disabled on ppc64/arm64 */
|
||||
state->state = MODS_SWIOTLB_DISABLED;
|
||||
@@ -632,25 +762,40 @@ int esc_mods_pci_set_dma_mask(struct file *file,
|
||||
struct MODS_PCI_DMA_MASK *dma_mask)
|
||||
{
|
||||
int err;
|
||||
unsigned int devfn = PCI_DEVFN(dma_mask->pci_device.device,
|
||||
dma_mask->pci_device.function);
|
||||
struct pci_dev *dev = MODS_PCI_GET_SLOT(dma_mask->pci_device.domain,
|
||||
dma_mask->pci_device.bus,
|
||||
devfn);
|
||||
struct pci_dev *dev;
|
||||
u64 mask;
|
||||
|
||||
if (dma_mask->num_bits > 64)
|
||||
LOG_ENT();
|
||||
|
||||
if (unlikely(dma_mask->num_bits > 64)) {
|
||||
mods_error_printk("num_bits=%u exceeds 64\n",
|
||||
dma_mask->num_bits);
|
||||
LOG_EXT();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = mods_find_pci_dev(file, &dma_mask->pci_device, &dev);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
mods_error_printk("PCI device %04x:%02x:%02x.%x not found\n",
|
||||
dma_mask->pci_device.domain,
|
||||
dma_mask->pci_device.bus,
|
||||
dma_mask->pci_device.device,
|
||||
dma_mask->pci_device.function);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
mask = dma_mask->num_bits == 64 ? ~0ULL : (1ULL<<dma_mask->num_bits)-1;
|
||||
|
||||
err = pci_set_dma_mask(dev, mask);
|
||||
if (err) {
|
||||
mods_error_printk("failed to set dma mask 0x%llx for dev %04x:%02x:%02x.%x\n",
|
||||
mask,
|
||||
(unsigned int)dma_mask->pci_device.domain,
|
||||
(unsigned int)dma_mask->pci_device.bus,
|
||||
(unsigned int)dma_mask->pci_device.device,
|
||||
(unsigned int)dma_mask->pci_device.function);
|
||||
dma_mask->pci_device.domain,
|
||||
dma_mask->pci_device.bus,
|
||||
dma_mask->pci_device.device,
|
||||
dma_mask->pci_device.function);
|
||||
#if defined(CONFIG_PPC64)
|
||||
/* Ignore error if TCE bypass is on */
|
||||
if (dev->dma_mask == ~0ULL)
|
||||
@@ -659,5 +804,7 @@ int esc_mods_pci_set_dma_mask(struct file *file,
|
||||
} else
|
||||
err = pci_set_consistent_dma_mask(dev, mask);
|
||||
|
||||
pci_dev_put(dev);
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user