vserver 1.9.5.x5
[linux-2.6.git] / drivers / acpi / pci_bind.c
index ec264c8..5d19b39 100644 (file)
@@ -67,6 +67,7 @@ acpi_pci_data_handler (
  * to resolve PCI information for ACPI-PCI devices defined in the namespace.
  * This typically occurs when resolving PCI operation region information.
  */
+#ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_os_get_pci_id (
        acpi_handle             handle,
@@ -114,6 +115,7 @@ acpi_os_get_pci_id (
 
        return_ACPI_STATUS(AE_OK);
 }
+#endif  /*  ACPI_FUTURE_USAGE  */
 
        
 int
@@ -124,8 +126,8 @@ acpi_pci_bind (
        acpi_status             status = AE_OK;
        struct acpi_pci_data    *data = NULL;
        struct acpi_pci_data    *pdata = NULL;
-       char                    pathname[ACPI_PATHNAME_MAX] = {0};
-       struct acpi_buffer      buffer = {ACPI_PATHNAME_MAX, pathname};
+       char                    *pathname = NULL;
+       struct acpi_buffer      buffer = {0, NULL};
        acpi_handle             handle = NULL;
 
        ACPI_FUNCTION_TRACE("acpi_pci_bind");
@@ -133,9 +135,18 @@ acpi_pci_bind (
        if (!device || !device->parent)
                return_VALUE(-EINVAL);
 
+       pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       if(!pathname)
+               return_VALUE(-ENOMEM);
+       memset(pathname, 0, ACPI_PATHNAME_MAX);
+       buffer.length = ACPI_PATHNAME_MAX;
+       buffer.pointer = pathname;
+
        data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
-       if (!data)
+       if (!data){
+               kfree (pathname);
                return_VALUE(-ENOMEM);
+       }
        memset(data, 0, sizeof(struct acpi_pci_data));
 
        acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
@@ -214,6 +225,7 @@ acpi_pci_bind (
                        data->id.device, data->id.function));
                data->bus = data->dev->subordinate;
                device->ops.bind = acpi_pci_bind;
+               device->ops.unbind = acpi_pci_unbind;
        }
 
        /*
@@ -251,12 +263,64 @@ acpi_pci_bind (
        }
 
 end:
+       kfree(pathname);
        if (result)
                kfree(data);
 
        return_VALUE(result);
 }
 
+int acpi_pci_unbind(
+       struct acpi_device      *device)
+{
+       int                     result = 0;
+       acpi_status             status = AE_OK;
+       struct acpi_pci_data    *data = NULL;
+       char                    *pathname = NULL;
+       struct acpi_buffer      buffer = {0, NULL};
+
+       ACPI_FUNCTION_TRACE("acpi_pci_unbind");
+
+       if (!device || !device->parent)
+               return_VALUE(-EINVAL);
+
+       pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       if(!pathname)
+               return_VALUE(-ENOMEM);
+       memset(pathname, 0, ACPI_PATHNAME_MAX);
+
+       buffer.length = ACPI_PATHNAME_MAX;
+       buffer.pointer = pathname;
+       acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
+               pathname));
+       kfree(pathname);
+
+       status = acpi_get_data(device->handle, acpi_pci_data_handler, (void**)&data);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                       "Unable to get data from device %s\n",
+                       acpi_device_bid(device)));
+               result = -ENODEV;
+               goto end;
+       }
+
+       status = acpi_detach_data(device->handle, acpi_pci_data_handler);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                       "Unable to detach data from device %s\n",
+                       acpi_device_bid(device)));
+               result = -ENODEV;
+               goto end;
+       }
+       if (data->dev->subordinate) {
+               acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
+       }
+       kfree(data);
+
+end:
+       return_VALUE(result);
+}
 
 int 
 acpi_pci_bind_root (
@@ -267,22 +331,35 @@ acpi_pci_bind_root (
        int                     result = 0;
        acpi_status             status = AE_OK;
        struct acpi_pci_data    *data = NULL;
-       char                    pathname[ACPI_PATHNAME_MAX] = {0};
-       struct acpi_buffer      buffer = {ACPI_PATHNAME_MAX, pathname};
+       char                    *pathname = NULL;
+       struct acpi_buffer      buffer = {0, NULL};
 
        ACPI_FUNCTION_TRACE("acpi_pci_bind_root");
 
-       if (!device || !id || !bus)
+       pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       if(!pathname)
+               return_VALUE(-ENOMEM);
+       memset(pathname, 0, ACPI_PATHNAME_MAX);
+
+       buffer.length = ACPI_PATHNAME_MAX;
+       buffer.pointer = pathname;
+
+       if (!device || !id || !bus){
+               kfree(pathname);
                return_VALUE(-EINVAL);
+       }
 
        data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
-       if (!data)
+       if (!data){
+               kfree(pathname);
                return_VALUE(-ENOMEM);
+       }
        memset(data, 0, sizeof(struct acpi_pci_data));
 
        data->id = *id;
        data->bus = bus;
        device->ops.bind = acpi_pci_bind;
+       device->ops.unbind = acpi_pci_unbind;
 
        acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
 
@@ -299,6 +376,7 @@ acpi_pci_bind_root (
        }
 
 end:
+       kfree(pathname);
        if (result != 0)
                kfree(data);