public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: Len Brown <lenb@kernel.org>
To: akpm@osdl.org
Cc: linux-acpi@vger.kernel.org, jpk@sgi.com, ayoung@sgi.com,
	greg@kroah.com, tony.luck@intel.com
Subject: Re: [patch 16/19] Altix: Add ACPI SSDT PCI device support (hotplug)
Date: Wed, 20 Dec 2006 01:56:09 -0500	[thread overview]
Message-ID: <200612200156.09612.lenb@kernel.org> (raw)
In-Reply-To: <200612192056.kBJKuMD8010059@shell0.pdx.osdl.net>

Acked-By: Len Brown <len.brown@intel.com>

Tony,
This should probably be sent via your tree.

thanks,
-Len

On Tuesday 19 December 2006 15:56, akpm@osdl.org wrote:
> From: John Keller <jpk@sgi.com>
> 
> Support for dynamic loading and unloading of ACPI SSDT tables upon slot
> hotplugs and unplugs.
> 
> On SN platforms, we now represent every populated root bus slot with a single
> ACPI SSDT table containing info for every device and PPB attached to the slot.
>  These SSDTs are generated by the prom at initial boot and hotplug time.  The
> info in these SSDT tables is used by the SN kernel IO "fixup" code (which is
> called at boot and hotplug time).
> 
> On hotplugs (i.e.  enable_slot()), if running with an ACPI capable prom,
> attempt to obtain a new ACPI SSDT table for the slot being hotplugged.  If
> successful, add the table to the ACPI namespace (acpi_load_table()) and then
> walk the new devices and add them to the ACPI infrastructure (acpi_bus_add()).
> 
> On hot unplugs (i.e.  disable_slot()), if running with an ACPI capable prom,
> attempt to remove the SSDT table associated with the slot from the ACPI
> namespace (acpi_unload_table_id()) and infastructure (acpi_bus_trim()).
> 
> From: John Keller <jpk@sgi.com>
> 
>  A bug was fixed where the sgi hotplug driver was removing
>  the slot's SSDT table from the ACPI namespace a bit too early in
>  disable_slot(). Also, we now call acpi_bus_start() subsequent
>  to acpi_bus_add().
> 
> Signed-off-by: Aaron Young <ayoung@sgi.com>
> Cc: "Brown, Len" <len.brown@intel.com>
> Cc: Greg KH <greg@kroah.com>
> Cc: "Luck, Tony" <tony.luck@intel.com>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
> ---
> 
>  drivers/pci/hotplug/sgi_hotplug.c |  155 ++++++++++++++++++++++++++--
>  1 files changed, 148 insertions(+), 7 deletions(-)
> 
> diff -puN drivers/pci/hotplug/sgi_hotplug.c~altix-add-acpi-ssdt-pci-device-support-hotplug drivers/pci/hotplug/sgi_hotplug.c
> --- a/drivers/pci/hotplug/sgi_hotplug.c~altix-add-acpi-ssdt-pci-device-support-hotplug
> +++ a/drivers/pci/hotplug/sgi_hotplug.c
> @@ -28,6 +28,8 @@
>  #include <asm/sn/sn_feature_sets.h>
>  #include <asm/sn/sn_sal.h>
>  #include <asm/sn/types.h>
> +#include <linux/acpi.h>
> +#include <asm/sn/acpi.h>
>  
>  #include "../pci.h"
>  
> @@ -35,14 +37,17 @@ MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
>  MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
>  
> -#define PCIIO_ASIC_TYPE_TIOCA		4
> +
> +/* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */
>  #define PCI_SLOT_ALREADY_UP		2	/* slot already up */
>  #define PCI_SLOT_ALREADY_DOWN		3	/* slot already down */
>  #define PCI_L1_ERR			7	/* L1 console command error */
>  #define PCI_EMPTY_33MHZ			15	/* empty 33 MHz bus */
> +
> +
> +#define PCIIO_ASIC_TYPE_TIOCA		4
>  #define PCI_L1_QSIZE			128	/* our L1 message buffer size */
>  #define SN_MAX_HP_SLOTS			32	/* max hotplug slots */
> -#define SGI_HOTPLUG_PROM_REV		0x0430	/* Min. required PROM version */
>  #define SN_SLOT_NAME_SIZE		33	/* size of name string */
>  
>  /* internal list head */
> @@ -227,7 +232,7 @@ static void sn_bus_free_data(struct pci_
>  }
>  
>  static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
> -			  int device_num)
> +			  int device_num, char **ssdt)
>  {
>  	struct slot *slot = bss_hotplug_slot->private;
>  	struct pcibus_info *pcibus_info;
> @@ -240,7 +245,8 @@ static int sn_slot_enable(struct hotplug
>  	 * Power-on and initialize the slot in the SN
>  	 * PCI infrastructure.
>  	 */
> -	rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
> +	rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp, ssdt);
> +
>  
>  	if (rc == PCI_SLOT_ALREADY_UP) {
>  		dev_dbg(slot->pci_bus->self, "is already active\n");
> @@ -335,6 +341,7 @@ static int enable_slot(struct hotplug_sl
>  	int func, num_funcs;
>  	int new_ppb = 0;
>  	int rc;
> +	char *ssdt = NULL;
>  	void pcibios_fixup_device_resources(struct pci_dev *);
>  
>  	/* Serialize the Linux PCI infrastructure */
> @@ -342,14 +349,29 @@ static int enable_slot(struct hotplug_sl
>  
>  	/*
>  	 * Power-on and initialize the slot in the SN
> -	 * PCI infrastructure.
> +	 * PCI infrastructure. Also, retrieve the ACPI SSDT
> +	 * table for the slot (if ACPI capable PROM).
>  	 */
> -	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
> +	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt);
>  	if (rc) {
>  		mutex_unlock(&sn_hotplug_mutex);
>  		return rc;
>  	}
>  
> +	if (ssdt)
> +		ssdt = __va(ssdt);
> +	/* Add the new SSDT for the slot to the ACPI namespace */
> +	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
> +		acpi_status ret;
> +
> +		ret = acpi_load_table((struct acpi_table_header *)ssdt);
> +		if (ACPI_FAILURE(ret)) {
> +			printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
> +			       __FUNCTION__, ret);
> +			/* try to continue on */
> +		}
> +	}
> +
>  	num_funcs = pci_scan_slot(slot->pci_bus,
>  				  PCI_DEVFN(slot->device_num + 1, 0));
>  	if (!num_funcs) {
> @@ -374,7 +396,10 @@ static int enable_slot(struct hotplug_sl
>  			 * pdi_host_pcidev_info).
>  			 */
>  			pcibios_fixup_device_resources(dev);
> -			sn_pci_fixup_slot(dev);
> +			if (SN_ACPI_BASE_SUPPORT())
> +				sn_acpi_slot_fixup(dev);
> +			else
> +				sn_io_slot_fixup(dev);
>  			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
>  				unsigned char sec_bus;
>  				pci_read_config_byte(dev, PCI_SECONDARY_BUS,
> @@ -388,6 +413,63 @@ static int enable_slot(struct hotplug_sl
>  		}
>  	}
>  
> +	/*
> +	 * Add the slot's devices to the ACPI infrastructure */
> +	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
> +		unsigned long adr;
> +		struct acpi_device *pdevice;
> +		struct acpi_device *device;
> +		acpi_handle phandle;
> +		acpi_handle chandle = NULL;
> +		acpi_handle rethandle;
> +		acpi_status ret;
> +
> +		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
> +
> +		if (acpi_bus_get_device(phandle, &pdevice)) {
> +			dev_dbg(slot->pci_bus->self,
> +				"no parent device, assuming NULL\n");
> +			pdevice = NULL;
> +		}
> +
> +		/*
> +		 * Walk the rootbus node's immediate children looking for
> +		 * the slot's device node(s). There can be more than
> +		 * one for multifunction devices.
> +		 */
> +		for (;;) {
> +			rethandle = NULL;
> +			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
> +						   phandle, chandle,
> +						   &rethandle);
> +
> +			if (ret == AE_NOT_FOUND || rethandle == NULL)
> +				break;
> +
> +			chandle = rethandle;
> +
> +			ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR,
> +						    NULL, &adr);
> +
> +			if (ACPI_SUCCESS(ret) &&
> +			    (adr>>16) == (slot->device_num + 1)) {
> +
> +				ret = acpi_bus_add(&device, pdevice, chandle,
> +						   ACPI_BUS_TYPE_DEVICE);
> +				if (ACPI_FAILURE(ret)) {
> +					printk(KERN_ERR "%s: acpi_bus_add "
> +					       "failed (0x%x) for slot %d "
> +					       "func %d\n", __FUNCTION__,
> +					       ret, (int)(adr>>16),
> +					       (int)(adr&0xffff));
> +					/* try to continue on */
> +				} else {
> +					acpi_bus_start(device);
> +				}
> +			}
> +		}
> +	}
> +
>  	/* Call the driver for the new device */
>  	pci_bus_add_devices(slot->pci_bus);
>  	/* Call the drivers for the new devices subordinate to PPB */
> @@ -412,6 +494,7 @@ static int disable_slot(struct hotplug_s
>  	struct pci_dev *dev;
>  	int func;
>  	int rc;
> +	acpi_owner_id ssdt_id = 0;
>  
>  	/* Acquire update access to the bus */
>  	mutex_lock(&sn_hotplug_mutex);
> @@ -422,6 +505,52 @@ static int disable_slot(struct hotplug_s
>  	if (rc)
>  		goto leaving;
>  
> +	/* free the ACPI resources for the slot */
> +	if (SN_ACPI_BASE_SUPPORT() &&
> +            PCI_CONTROLLER(slot->pci_bus)->acpi_handle) {
> +		unsigned long adr;
> +		struct acpi_device *device;
> +		acpi_handle phandle;
> +		acpi_handle chandle = NULL;
> +		acpi_handle rethandle;
> +		acpi_status ret;
> +
> +		/* Get the rootbus node pointer */
> +		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
> +
> +		/*
> +		 * Walk the rootbus node's immediate children looking for
> +		 * the slot's device node(s). There can be more than
> +		 * one for multifunction devices.
> +		 */
> +		for (;;) {
> +			rethandle = NULL;
> +			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
> +						   phandle, chandle,
> +						   &rethandle);
> +
> +			if (ret == AE_NOT_FOUND || rethandle == NULL)
> +				break;
> +
> +			chandle = rethandle;
> +
> +			ret = acpi_evaluate_integer(chandle,
> +						    METHOD_NAME__ADR,
> +						    NULL, &adr);
> +			if (ACPI_SUCCESS(ret) &&
> +			    (adr>>16) == (slot->device_num + 1)) {
> +				/* retain the owner id */
> +				acpi_get_id(chandle, &ssdt_id);
> +
> +				ret = acpi_bus_get_device(chandle,
> +							  &device);
> +				if (ACPI_SUCCESS(ret))
> +					acpi_bus_trim(device, 1);
> +			}
> +		}
> +
> +	}
> +
>  	/* Free the SN resources assigned to the Linux device.*/
>  	for (func = 0; func < 8;  func++) {
>  		dev = pci_get_slot(slot->pci_bus,
> @@ -434,6 +563,18 @@ static int disable_slot(struct hotplug_s
>  		}
>  	}
>  
> +	/* Remove the SSDT for the slot from the ACPI namespace */
> +	if (SN_ACPI_BASE_SUPPORT() && ssdt_id) {
> +		acpi_status ret;
> +		ret = acpi_unload_table_id(ACPI_TABLE_ID_SSDT, ssdt_id);
> +		if (ACPI_FAILURE(ret)) {
> +			printk(KERN_ERR "%s: acpi_unload_table_id "
> +			       "failed (0x%x) for id %d\n",
> +			       __FUNCTION__, ret, ssdt_id);
> +			/* try to continue on */
> +		}
> +	}
> +
>  	/* free the collected sysdata pointers */
>  	sn_bus_free_sysdata();
>  
> _
> -
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

  reply	other threads:[~2006-12-20  6:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-19 20:56 [patch 16/19] Altix: Add ACPI SSDT PCI device support (hotplug) akpm
2006-12-20  6:56 ` Len Brown [this message]
2006-12-20  8:39   ` Andrew Morton
2006-12-20 14:27     ` John Keller
2006-12-28 17:06   ` John Keller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200612200156.09612.lenb@kernel.org \
    --to=lenb@kernel.org \
    --cc=akpm@osdl.org \
    --cc=ayoung@sgi.com \
    --cc=greg@kroah.com \
    --cc=jpk@sgi.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox