brintos

brintos / linux-shallow public Read only

0
0
Text · 30.8 KiB · 197997e Raw
1253 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * IBM Hot Plug Controller Driver4 *5 * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation6 *7 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)8 * Copyright (C) 2001-2003 IBM Corp.9 *10 * All rights reserved.11 *12 * Send feedback to <gregkh@us.ibm.com>13 *14 */15 16#include <linux/init.h>17#include <linux/module.h>18#include <linux/slab.h>19#include <linux/pci.h>20#include <linux/interrupt.h>21#include <linux/delay.h>22#include <linux/wait.h>23#include "../pci.h"24#include <asm/pci_x86.h>		/* for struct irq_routing_table */25#include <asm/io_apic.h>26#include "ibmphp.h"27 28#define attn_on(sl)  ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNON)29#define attn_off(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNOFF)30#define attn_LED_blink(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_BLINKLED)31#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot(sl, READ_REVLEVEL, rev)32#define get_hpc_options(sl, opt) ibmphp_hpc_readslot(sl, READ_HPCOPTIONS, opt)33 34#define DRIVER_VERSION	"0.6"35#define DRIVER_DESC	"IBM Hot Plug PCI Controller Driver"36 37int ibmphp_debug;38 39static bool debug;40module_param(debug, bool, S_IRUGO | S_IWUSR);41MODULE_PARM_DESC(debug, "Debugging mode enabled or not");42MODULE_LICENSE("GPL");43MODULE_DESCRIPTION(DRIVER_DESC);44 45struct pci_bus *ibmphp_pci_bus;46static int max_slots;47 48static int irqs[16];    /* PIC mode IRQs we're using so far (in case MPS49			 * tables don't provide default info for empty slots */50 51static int init_flag;52 53static inline int get_cur_bus_info(struct slot **sl)54{55	int rc = 1;56	struct slot *slot_cur = *sl;57 58	debug("options = %x\n", slot_cur->ctrl->options);59	debug("revision = %x\n", slot_cur->ctrl->revision);60 61	if (READ_BUS_STATUS(slot_cur->ctrl))62		rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL);63 64	if (rc)65		return rc;66 67	slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus);68	if (READ_BUS_MODE(slot_cur->ctrl))69		slot_cur->bus_on->current_bus_mode =70				CURRENT_BUS_MODE(slot_cur->busstatus);71	else72		slot_cur->bus_on->current_bus_mode = 0xFF;73 74	debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n",75			slot_cur->busstatus,76			slot_cur->bus_on->current_speed,77			slot_cur->bus_on->current_bus_mode);78 79	*sl = slot_cur;80	return 0;81}82 83static inline int slot_update(struct slot **sl)84{85	int rc;86	rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL);87	if (rc)88		return rc;89	if (!init_flag)90		rc = get_cur_bus_info(sl);91	return rc;92}93 94static int __init get_max_slots(void)95{96	struct slot *slot_cur;97	u8 slot_count = 0;98 99	list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {100		/* sometimes the hot-pluggable slots start with 4 (not always from 1) */101		slot_count = max(slot_count, slot_cur->number);102	}103	return slot_count;104}105 106/* This routine will put the correct slot->device information per slot.  It's107 * called from initialization of the slot structures. It will also assign108 * interrupt numbers per each slot.109 * Parameters: struct slot110 * Returns 0 or errors111 */112int ibmphp_init_devno(struct slot **cur_slot)113{114	struct irq_routing_table *rtable;115	int len;116	int loop;117	int i;118 119	rtable = pcibios_get_irq_routing_table();120	if (!rtable) {121		err("no BIOS routing table...\n");122		return -ENOMEM;123	}124 125	len = (rtable->size - sizeof(struct irq_routing_table)) /126			sizeof(struct irq_info);127 128	if (!len) {129		kfree(rtable);130		return -1;131	}132	for (loop = 0; loop < len; loop++) {133		if ((*cur_slot)->number == rtable->slots[loop].slot &&134		    (*cur_slot)->bus == rtable->slots[loop].bus) {135			(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);136			for (i = 0; i < 4; i++)137				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,138						(int) (*cur_slot)->device, i);139 140			debug("(*cur_slot)->irq[0] = %x\n",141					(*cur_slot)->irq[0]);142			debug("(*cur_slot)->irq[1] = %x\n",143					(*cur_slot)->irq[1]);144			debug("(*cur_slot)->irq[2] = %x\n",145					(*cur_slot)->irq[2]);146			debug("(*cur_slot)->irq[3] = %x\n",147					(*cur_slot)->irq[3]);148 149			debug("rtable->exclusive_irqs = %x\n",150					rtable->exclusive_irqs);151			debug("rtable->slots[loop].irq[0].bitmap = %x\n",152					rtable->slots[loop].irq[0].bitmap);153			debug("rtable->slots[loop].irq[1].bitmap = %x\n",154					rtable->slots[loop].irq[1].bitmap);155			debug("rtable->slots[loop].irq[2].bitmap = %x\n",156					rtable->slots[loop].irq[2].bitmap);157			debug("rtable->slots[loop].irq[3].bitmap = %x\n",158					rtable->slots[loop].irq[3].bitmap);159 160			debug("rtable->slots[loop].irq[0].link = %x\n",161					rtable->slots[loop].irq[0].link);162			debug("rtable->slots[loop].irq[1].link = %x\n",163					rtable->slots[loop].irq[1].link);164			debug("rtable->slots[loop].irq[2].link = %x\n",165					rtable->slots[loop].irq[2].link);166			debug("rtable->slots[loop].irq[3].link = %x\n",167					rtable->slots[loop].irq[3].link);168			debug("end of init_devno\n");169			kfree(rtable);170			return 0;171		}172	}173 174	kfree(rtable);175	return -1;176}177 178static inline int power_on(struct slot *slot_cur)179{180	u8 cmd = HPC_SLOT_ON;181	int retval;182 183	retval = ibmphp_hpc_writeslot(slot_cur, cmd);184	if (retval) {185		err("power on failed\n");186		return retval;187	}188	if (CTLR_RESULT(slot_cur->ctrl->status)) {189		err("command not completed successfully in power_on\n");190		return -EIO;191	}192	msleep(3000);	/* For ServeRAID cards, and some 66 PCI */193	return 0;194}195 196static inline int power_off(struct slot *slot_cur)197{198	u8 cmd = HPC_SLOT_OFF;199	int retval;200 201	retval = ibmphp_hpc_writeslot(slot_cur, cmd);202	if (retval) {203		err("power off failed\n");204		return retval;205	}206	if (CTLR_RESULT(slot_cur->ctrl->status)) {207		err("command not completed successfully in power_off\n");208		retval = -EIO;209	}210	return retval;211}212 213static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)214{215	int rc = 0;216	struct slot *pslot;217	u8 cmd = 0x00;     /* avoid compiler warning */218 219	debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",220			(ulong) hotplug_slot, value);221	ibmphp_lock_operations();222 223 224	if (hotplug_slot) {225		switch (value) {226		case HPC_SLOT_ATTN_OFF:227			cmd = HPC_SLOT_ATTNOFF;228			break;229		case HPC_SLOT_ATTN_ON:230			cmd = HPC_SLOT_ATTNON;231			break;232		case HPC_SLOT_ATTN_BLINK:233			cmd = HPC_SLOT_BLINKLED;234			break;235		default:236			rc = -ENODEV;237			err("set_attention_status - Error : invalid input [%x]\n",238					value);239			break;240		}241		if (rc == 0) {242			pslot = to_slot(hotplug_slot);243			rc = ibmphp_hpc_writeslot(pslot, cmd);244		}245	} else246		rc = -ENODEV;247 248	ibmphp_unlock_operations();249 250	debug("set_attention_status - Exit rc[%d]\n", rc);251	return rc;252}253 254static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)255{256	int rc = -ENODEV;257	struct slot *pslot;258	struct slot myslot;259 260	debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",261					(ulong) hotplug_slot, (ulong) value);262 263	ibmphp_lock_operations();264	if (hotplug_slot) {265		pslot = to_slot(hotplug_slot);266		memcpy(&myslot, pslot, sizeof(struct slot));267		rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,268					 &myslot.status);269		if (!rc)270			rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS,271						 &myslot.ext_status);272		if (!rc)273			*value = SLOT_ATTN(myslot.status, myslot.ext_status);274	}275 276	ibmphp_unlock_operations();277	debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value);278	return rc;279}280 281static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)282{283	int rc = -ENODEV;284	struct slot *pslot;285	struct slot myslot;286 287	debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",288					(ulong) hotplug_slot, (ulong) value);289	ibmphp_lock_operations();290	if (hotplug_slot) {291		pslot = to_slot(hotplug_slot);292		memcpy(&myslot, pslot, sizeof(struct slot));293		rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,294					 &myslot.status);295		if (!rc)296			*value = SLOT_LATCH(myslot.status);297	}298 299	ibmphp_unlock_operations();300	debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n",301			rc, rc, *value);302	return rc;303}304 305 306static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)307{308	int rc = -ENODEV;309	struct slot *pslot;310	struct slot myslot;311 312	debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",313					(ulong) hotplug_slot, (ulong) value);314	ibmphp_lock_operations();315	if (hotplug_slot) {316		pslot = to_slot(hotplug_slot);317		memcpy(&myslot, pslot, sizeof(struct slot));318		rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,319					 &myslot.status);320		if (!rc)321			*value = SLOT_PWRGD(myslot.status);322	}323 324	ibmphp_unlock_operations();325	debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n",326			rc, rc, *value);327	return rc;328}329 330static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 *value)331{332	int rc = -ENODEV;333	struct slot *pslot;334	u8 present;335	struct slot myslot;336 337	debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",338					(ulong) hotplug_slot, (ulong) value);339	ibmphp_lock_operations();340	if (hotplug_slot) {341		pslot = to_slot(hotplug_slot);342		memcpy(&myslot, pslot, sizeof(struct slot));343		rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,344					 &myslot.status);345		if (!rc) {346			present = SLOT_PRESENT(myslot.status);347			if (present == HPC_SLOT_EMPTY)348				*value = 0;349			else350				*value = 1;351		}352	}353 354	ibmphp_unlock_operations();355	debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value);356	return rc;357}358 359static int get_max_bus_speed(struct slot *slot)360{361	int rc = 0;362	u8 mode = 0;363	enum pci_bus_speed speed;364	struct pci_bus *bus = slot->hotplug_slot.pci_slot->bus;365 366	debug("%s - Entry slot[%p]\n", __func__, slot);367 368	ibmphp_lock_operations();369	mode = slot->supported_bus_mode;370	speed = slot->supported_speed;371	ibmphp_unlock_operations();372 373	switch (speed) {374	case BUS_SPEED_33:375		break;376	case BUS_SPEED_66:377		if (mode == BUS_MODE_PCIX)378			speed += 0x01;379		break;380	case BUS_SPEED_100:381	case BUS_SPEED_133:382		speed += 0x01;383		break;384	default:385		/* Note (will need to change): there would be soon 256, 512 also */386		rc = -ENODEV;387	}388 389	if (!rc)390		bus->max_bus_speed = speed;391 392	debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed);393	return rc;394}395 396/****************************************************************************397 * This routine will initialize the ops data structure used in the validate398 * function. It will also power off empty slots that are powered on since BIOS399 * leaves those on, albeit disconnected400 ****************************************************************************/401static int __init init_ops(void)402{403	struct slot *slot_cur;404	int retval;405	int rc;406 407	list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {408		debug("BEFORE GETTING SLOT STATUS, slot # %x\n",409							slot_cur->number);410		if (slot_cur->ctrl->revision == 0xFF)411			if (get_ctrl_revision(slot_cur,412						&slot_cur->ctrl->revision))413				return -1;414 415		if (slot_cur->bus_on->current_speed == 0xFF)416			if (get_cur_bus_info(&slot_cur))417				return -1;418		get_max_bus_speed(slot_cur);419 420		if (slot_cur->ctrl->options == 0xFF)421			if (get_hpc_options(slot_cur, &slot_cur->ctrl->options))422				return -1;423 424		retval = slot_update(&slot_cur);425		if (retval)426			return retval;427 428		debug("status = %x\n", slot_cur->status);429		debug("ext_status = %x\n", slot_cur->ext_status);430		debug("SLOT_POWER = %x\n", SLOT_POWER(slot_cur->status));431		debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status));432		debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status));433 434		if ((SLOT_PWRGD(slot_cur->status)) &&435		    !(SLOT_PRESENT(slot_cur->status)) &&436		    !(SLOT_LATCH(slot_cur->status))) {437			debug("BEFORE POWER OFF COMMAND\n");438				rc = power_off(slot_cur);439				if (rc)440					return rc;441 442	/*		retval = slot_update(&slot_cur);443	 *		if (retval)444	 *			return retval;445	 *		ibmphp_update_slot_info(slot_cur);446	 */447		}448	}449	init_flag = 0;450	return 0;451}452 453/* This operation will check whether the slot is within the bounds and454 * the operation is valid to perform on that slot455 * Parameters: slot, operation456 * Returns: 0 or error codes457 */458static int validate(struct slot *slot_cur, int opn)459{460	int number;461	int retval;462 463	if (!slot_cur)464		return -ENODEV;465	number = slot_cur->number;466	if ((number > max_slots) || (number < 0))467		return -EBADSLT;468	debug("slot_number in validate is %d\n", slot_cur->number);469 470	retval = slot_update(&slot_cur);471	if (retval)472		return retval;473 474	switch (opn) {475		case ENABLE:476			if (!(SLOT_PWRGD(slot_cur->status)) &&477			     (SLOT_PRESENT(slot_cur->status)) &&478			     !(SLOT_LATCH(slot_cur->status)))479				return 0;480			break;481		case DISABLE:482			if ((SLOT_PWRGD(slot_cur->status)) &&483			    (SLOT_PRESENT(slot_cur->status)) &&484			    !(SLOT_LATCH(slot_cur->status)))485				return 0;486			break;487		default:488			break;489	}490	err("validate failed....\n");491	return -EINVAL;492}493 494/****************************************************************************495 * This routine is for updating the data structures in the hotplug core496 * Parameters: struct slot497 * Returns: 0 or error498 ****************************************************************************/499int ibmphp_update_slot_info(struct slot *slot_cur)500{501	struct pci_bus *bus = slot_cur->hotplug_slot.pci_slot->bus;502	u8 bus_speed;503	u8 mode;504 505	bus_speed = slot_cur->bus_on->current_speed;506	mode = slot_cur->bus_on->current_bus_mode;507 508	switch (bus_speed) {509		case BUS_SPEED_33:510			break;511		case BUS_SPEED_66:512			if (mode == BUS_MODE_PCIX)513				bus_speed += 0x01;514			else if (mode == BUS_MODE_PCI)515				;516			else517				bus_speed = PCI_SPEED_UNKNOWN;518			break;519		case BUS_SPEED_100:520		case BUS_SPEED_133:521			bus_speed += 0x01;522			break;523		default:524			bus_speed = PCI_SPEED_UNKNOWN;525	}526 527	bus->cur_bus_speed = bus_speed;528	// To do: bus_names529 530	return 0;531}532 533 534/******************************************************************************535 * This function will return the pci_func, given bus and devfunc, or NULL.  It536 * is called from visit routines537 ******************************************************************************/538 539static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)540{541	struct pci_func *func_cur;542	struct slot *slot_cur;543	list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {544		if (slot_cur->func) {545			func_cur = slot_cur->func;546			while (func_cur) {547				if ((func_cur->busno == busno) &&548						(func_cur->device == device) &&549						(func_cur->function == function))550					return func_cur;551				func_cur = func_cur->next;552			}553		}554	}555	return NULL;556}557 558/*************************************************************559 * This routine frees up memory used by struct slot, including560 * the pointers to pci_func, bus, hotplug_slot, controller,561 * and deregistering from the hotplug core562 *************************************************************/563static void free_slots(void)564{565	struct slot *slot_cur, *next;566 567	debug("%s -- enter\n", __func__);568 569	list_for_each_entry_safe(slot_cur, next, &ibmphp_slot_head,570				 ibm_slot_list) {571		pci_hp_del(&slot_cur->hotplug_slot);572		slot_cur->ctrl = NULL;573		slot_cur->bus_on = NULL;574 575		/*576		 * We don't want to actually remove the resources,577		 * since ibmphp_free_resources() will do just that.578		 */579		ibmphp_unconfigure_card(&slot_cur, -1);580 581		pci_hp_destroy(&slot_cur->hotplug_slot);582		kfree(slot_cur);583	}584	debug("%s -- exit\n", __func__);585}586 587static void ibm_unconfigure_device(struct pci_func *func)588{589	struct pci_dev *temp;590	u8 j;591 592	debug("inside %s\n", __func__);593	debug("func->device = %x, func->function = %x\n",594					func->device, func->function);595	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);596 597	pci_lock_rescan_remove();598 599	for (j = 0; j < 0x08; j++) {600		temp = pci_get_domain_bus_and_slot(0, func->busno,601						   (func->device << 3) | j);602		if (temp) {603			pci_stop_and_remove_bus_device(temp);604			pci_dev_put(temp);605		}606	}607 608	pci_dev_put(func->dev);609 610	pci_unlock_rescan_remove();611}612 613/*614 * The following function is to fix kernel bug regarding615 * getting bus entries, here we manually add those primary616 * bus entries to kernel bus structure whenever apply617 */618static u8 bus_structure_fixup(u8 busno)619{620	struct pci_bus *bus, *b;621	struct pci_dev *dev;622	u16 l;623 624	if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num(busno)))625		return 1;626 627	bus = kmalloc(sizeof(*bus), GFP_KERNEL);628	if (!bus)629		return 1;630 631	dev = kmalloc(sizeof(*dev), GFP_KERNEL);632	if (!dev) {633		kfree(bus);634		return 1;635	}636 637	bus->number = busno;638	bus->ops = ibmphp_pci_bus->ops;639	dev->bus = bus;640	for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {641		if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&642					(l != 0x0000) && (l != 0xffff)) {643			debug("%s - Inside bus_structure_fixup()\n",644							__func__);645			b = pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);646			if (!b)647				continue;648 649			pci_bus_add_devices(b);650			break;651		}652	}653 654	kfree(dev);655	kfree(bus);656 657	return 0;658}659 660static int ibm_configure_device(struct pci_func *func)661{662	struct pci_bus *child;663	int num;664	int flag = 0;	/* this is to make sure we don't double scan the bus,665					for bridged devices primarily */666 667	pci_lock_rescan_remove();668 669	if (!(bus_structure_fixup(func->busno)))670		flag = 1;671	if (func->dev == NULL)672		func->dev = pci_get_domain_bus_and_slot(0, func->busno,673				PCI_DEVFN(func->device, func->function));674 675	if (func->dev == NULL) {676		struct pci_bus *bus = pci_find_bus(0, func->busno);677		if (!bus)678			goto out;679 680		num = pci_scan_slot(bus,681				PCI_DEVFN(func->device, func->function));682		if (num)683			pci_bus_add_devices(bus);684 685		func->dev = pci_get_domain_bus_and_slot(0, func->busno,686				PCI_DEVFN(func->device, func->function));687		if (func->dev == NULL) {688			err("ERROR... : pci_dev still NULL\n");689			goto out;690		}691	}692	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {693		pci_hp_add_bridge(func->dev);694		child = func->dev->subordinate;695		if (child)696			pci_bus_add_devices(child);697	}698 699 out:700	pci_unlock_rescan_remove();701	return 0;702}703 704/*******************************************************705 * Returns whether the bus is empty or not706 *******************************************************/707static int is_bus_empty(struct slot *slot_cur)708{709	int rc;710	struct slot *tmp_slot;711	u8 i = slot_cur->bus_on->slot_min;712 713	while (i <= slot_cur->bus_on->slot_max) {714		if (i == slot_cur->number) {715			i++;716			continue;717		}718		tmp_slot = ibmphp_get_slot_from_physical_num(i);719		if (!tmp_slot)720			return 0;721		rc = slot_update(&tmp_slot);722		if (rc)723			return 0;724		if (SLOT_PRESENT(tmp_slot->status) &&725					SLOT_PWRGD(tmp_slot->status))726			return 0;727		i++;728	}729	return 1;730}731 732/***********************************************************733 * If the HPC permits and the bus currently empty, tries to set the734 * bus speed and mode at the maximum card and bus capability735 * Parameters: slot736 * Returns: bus is set (0) or error code737 ***********************************************************/738static int set_bus(struct slot *slot_cur)739{740	int rc;741	u8 speed;742	u8 cmd = 0x0;743	int retval;744	static const struct pci_device_id ciobx[] = {745		{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) },746		{ },747	};748 749	debug("%s - entry slot # %d\n", __func__, slot_cur->number);750	if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) {751		rc = slot_update(&slot_cur);752		if (rc)753			return rc;754		speed = SLOT_SPEED(slot_cur->ext_status);755		debug("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);756		switch (speed) {757		case HPC_SLOT_SPEED_33:758			cmd = HPC_BUS_33CONVMODE;759			break;760		case HPC_SLOT_SPEED_66:761			if (SLOT_PCIX(slot_cur->ext_status)) {762				if ((slot_cur->supported_speed >= BUS_SPEED_66) &&763						(slot_cur->supported_bus_mode == BUS_MODE_PCIX))764					cmd = HPC_BUS_66PCIXMODE;765				else if (!SLOT_BUS_MODE(slot_cur->ext_status))766					/* if max slot/bus capability is 66 pci767					and there's no bus mode mismatch, then768					the adapter supports 66 pci */769					cmd = HPC_BUS_66CONVMODE;770				else771					cmd = HPC_BUS_33CONVMODE;772			} else {773				if (slot_cur->supported_speed >= BUS_SPEED_66)774					cmd = HPC_BUS_66CONVMODE;775				else776					cmd = HPC_BUS_33CONVMODE;777			}778			break;779		case HPC_SLOT_SPEED_133:780			switch (slot_cur->supported_speed) {781			case BUS_SPEED_33:782				cmd = HPC_BUS_33CONVMODE;783				break;784			case BUS_SPEED_66:785				if (slot_cur->supported_bus_mode == BUS_MODE_PCIX)786					cmd = HPC_BUS_66PCIXMODE;787				else788					cmd = HPC_BUS_66CONVMODE;789				break;790			case BUS_SPEED_100:791				cmd = HPC_BUS_100PCIXMODE;792				break;793			case BUS_SPEED_133:794				/* This is to take care of the bug in CIOBX chip */795				if (pci_dev_present(ciobx))796					ibmphp_hpc_writeslot(slot_cur,797							HPC_BUS_100PCIXMODE);798				cmd = HPC_BUS_133PCIXMODE;799				break;800			default:801				err("Wrong bus speed\n");802				return -ENODEV;803			}804			break;805		default:806			err("wrong slot speed\n");807			return -ENODEV;808		}809		debug("setting bus speed for slot %d, cmd %x\n",810						slot_cur->number, cmd);811		retval = ibmphp_hpc_writeslot(slot_cur, cmd);812		if (retval) {813			err("setting bus speed failed\n");814			return retval;815		}816		if (CTLR_RESULT(slot_cur->ctrl->status)) {817			err("command not completed successfully in set_bus\n");818			return -EIO;819		}820	}821	/* This is for x440, once Brandon fixes the firmware,822	will not need this delay */823	msleep(1000);824	debug("%s -Exit\n", __func__);825	return 0;826}827 828/* This routine checks the bus limitations that the slot is on from the BIOS.829 * This is used in deciding whether or not to power up the slot.830 * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on831 * same bus)832 * Parameters: slot833 * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus834 */835static int check_limitations(struct slot *slot_cur)836{837	u8 i;838	struct slot *tmp_slot;839	u8 count = 0;840	u8 limitation = 0;841 842	for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {843		tmp_slot = ibmphp_get_slot_from_physical_num(i);844		if (!tmp_slot)845			return -ENODEV;846		if ((SLOT_PWRGD(tmp_slot->status)) &&847					!(SLOT_CONNECT(tmp_slot->status)))848			count++;849	}850	get_cur_bus_info(&slot_cur);851	switch (slot_cur->bus_on->current_speed) {852	case BUS_SPEED_33:853		limitation = slot_cur->bus_on->slots_at_33_conv;854		break;855	case BUS_SPEED_66:856		if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX)857			limitation = slot_cur->bus_on->slots_at_66_pcix;858		else859			limitation = slot_cur->bus_on->slots_at_66_conv;860		break;861	case BUS_SPEED_100:862		limitation = slot_cur->bus_on->slots_at_100_pcix;863		break;864	case BUS_SPEED_133:865		limitation = slot_cur->bus_on->slots_at_133_pcix;866		break;867	}868 869	if ((count + 1) > limitation)870		return -EINVAL;871	return 0;872}873 874static inline void print_card_capability(struct slot *slot_cur)875{876	info("capability of the card is ");877	if ((slot_cur->ext_status & CARD_INFO) == PCIX133)878		info("   133 MHz PCI-X\n");879	else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)880		info("    66 MHz PCI-X\n");881	else if ((slot_cur->ext_status & CARD_INFO) == PCI66)882		info("    66 MHz PCI\n");883	else884		info("    33 MHz PCI\n");885 886}887 888/* This routine will power on the slot, configure the device(s) and find the889 * drivers for them.890 * Parameters: hotplug_slot891 * Returns: 0 or failure codes892 */893static int enable_slot(struct hotplug_slot *hs)894{895	int rc, i, rcpr;896	struct slot *slot_cur;897	u8 function;898	struct pci_func *tmp_func;899 900	ibmphp_lock_operations();901 902	debug("ENABLING SLOT........\n");903	slot_cur = to_slot(hs);904 905	rc = validate(slot_cur, ENABLE);906	if (rc) {907		err("validate function failed\n");908		goto error_nopower;909	}910 911	attn_LED_blink(slot_cur);912 913	rc = set_bus(slot_cur);914	if (rc) {915		err("was not able to set the bus\n");916		goto error_nopower;917	}918 919	/*-----------------debugging------------------------------*/920	get_cur_bus_info(&slot_cur);921	debug("the current bus speed right after set_bus = %x\n",922					slot_cur->bus_on->current_speed);923	/*----------------------------------------------------------*/924 925	rc = check_limitations(slot_cur);926	if (rc) {927		err("Adding this card exceeds the limitations of this bus.\n");928		err("(i.e., >1 133MHz cards running on same bus, or >2 66 PCI cards running on same bus.\n");929		err("Try hot-adding into another bus\n");930		rc = -EINVAL;931		goto error_nopower;932	}933 934	rc = power_on(slot_cur);935 936	if (rc) {937		err("something wrong when powering up... please see below for details\n");938		/* need to turn off before on, otherwise, blinking overwrites */939		attn_off(slot_cur);940		attn_on(slot_cur);941		if (slot_update(&slot_cur)) {942			attn_off(slot_cur);943			attn_on(slot_cur);944			rc = -ENODEV;945			goto exit;946		}947		/* Check to see the error of why it failed */948		if ((SLOT_POWER(slot_cur->status)) &&949					!(SLOT_PWRGD(slot_cur->status)))950			err("power fault occurred trying to power up\n");951		else if (SLOT_BUS_SPEED(slot_cur->status)) {952			err("bus speed mismatch occurred.  please check current bus speed and card capability\n");953			print_card_capability(slot_cur);954		} else if (SLOT_BUS_MODE(slot_cur->ext_status)) {955			err("bus mode mismatch occurred.  please check current bus mode and card capability\n");956			print_card_capability(slot_cur);957		}958		ibmphp_update_slot_info(slot_cur);959		goto exit;960	}961	debug("after power_on\n");962	/*-----------------------debugging---------------------------*/963	get_cur_bus_info(&slot_cur);964	debug("the current bus speed right after power_on = %x\n",965					slot_cur->bus_on->current_speed);966	/*----------------------------------------------------------*/967 968	rc = slot_update(&slot_cur);969	if (rc)970		goto error_power;971 972	rc = -EINVAL;973	if (SLOT_POWER(slot_cur->status) && !(SLOT_PWRGD(slot_cur->status))) {974		err("power fault occurred trying to power up...\n");975		goto error_power;976	}977	if (SLOT_POWER(slot_cur->status) && (SLOT_BUS_SPEED(slot_cur->status))) {978		err("bus speed mismatch occurred.  please check current bus speed and card capability\n");979		print_card_capability(slot_cur);980		goto error_power;981	}982	/* Don't think this case will happen after above checks...983	 * but just in case, for paranoia sake */984	if (!(SLOT_POWER(slot_cur->status))) {985		err("power on failed...\n");986		goto error_power;987	}988 989	slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);990	if (!slot_cur->func) {991		/* do update_slot_info here? */992		rc = -ENOMEM;993		goto error_power;994	}995	slot_cur->func->busno = slot_cur->bus;996	slot_cur->func->device = slot_cur->device;997	for (i = 0; i < 4; i++)998		slot_cur->func->irq[i] = slot_cur->irq[i];999 1000	debug("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n",1001					slot_cur->bus, slot_cur->device);1002 1003	if (ibmphp_configure_card(slot_cur->func, slot_cur->number)) {1004		err("configure_card was unsuccessful...\n");1005		/* true because don't need to actually deallocate resources,1006		 * just remove references */1007		ibmphp_unconfigure_card(&slot_cur, 1);1008		debug("after unconfigure_card\n");1009		slot_cur->func = NULL;1010		rc = -ENOMEM;1011		goto error_power;1012	}1013 1014	function = 0x00;1015	do {1016		tmp_func = ibm_slot_find(slot_cur->bus, slot_cur->func->device,1017							function++);1018		if (tmp_func && !(tmp_func->dev))1019			ibm_configure_device(tmp_func);1020	} while (tmp_func);1021 1022	attn_off(slot_cur);1023	if (slot_update(&slot_cur)) {1024		rc = -EFAULT;1025		goto exit;1026	}1027	ibmphp_print_test();1028	rc = ibmphp_update_slot_info(slot_cur);1029exit:1030	ibmphp_unlock_operations();1031	return rc;1032 1033error_nopower:1034	attn_off(slot_cur);	/* need to turn off if was blinking b4 */1035	attn_on(slot_cur);1036error_cont:1037	rcpr = slot_update(&slot_cur);1038	if (rcpr) {1039		rc = rcpr;1040		goto exit;1041	}1042	ibmphp_update_slot_info(slot_cur);1043	goto exit;1044 1045error_power:1046	attn_off(slot_cur);	/* need to turn off if was blinking b4 */1047	attn_on(slot_cur);1048	rcpr = power_off(slot_cur);1049	if (rcpr) {1050		rc = rcpr;1051		goto exit;1052	}1053	goto error_cont;1054}1055 1056/**************************************************************1057* HOT REMOVING ADAPTER CARD                                   *1058* INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE                *1059* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE         *1060*		DISABLE POWER ,                               *1061**************************************************************/1062static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot)1063{1064	struct slot *slot = to_slot(hotplug_slot);1065	int rc;1066 1067	ibmphp_lock_operations();1068	rc = ibmphp_do_disable_slot(slot);1069	ibmphp_unlock_operations();1070	return rc;1071}1072 1073int ibmphp_do_disable_slot(struct slot *slot_cur)1074{1075	int rc;1076	u8 flag;1077 1078	debug("DISABLING SLOT...\n");1079 1080	if ((slot_cur == NULL) || (slot_cur->ctrl == NULL))1081		return -ENODEV;1082 1083	flag = slot_cur->flag;1084	slot_cur->flag = 1;1085 1086	if (flag == 1) {1087		rc = validate(slot_cur, DISABLE);1088			/* checking if powered off already & valid slot # */1089		if (rc)1090			goto error;1091	}1092	attn_LED_blink(slot_cur);1093 1094	if (slot_cur->func == NULL) {1095		/* We need this for functions that were there on bootup */1096		slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);1097		if (!slot_cur->func) {1098			rc = -ENOMEM;1099			goto error;1100		}1101		slot_cur->func->busno = slot_cur->bus;1102		slot_cur->func->device = slot_cur->device;1103	}1104 1105	ibm_unconfigure_device(slot_cur->func);1106 1107	/*1108	 * If we got here from latch suddenly opening on operating card or1109	 * a power fault, there's no power to the card, so cannot1110	 * read from it to determine what resources it occupied.  This operation1111	 * is forbidden anyhow.  The best we can do is remove it from kernel1112	 * lists at least */1113 1114	if (!flag) {1115		attn_off(slot_cur);1116		return 0;1117	}1118 1119	rc = ibmphp_unconfigure_card(&slot_cur, 0);1120	slot_cur->func = NULL;1121	debug("in disable_slot. after unconfigure_card\n");1122	if (rc) {1123		err("could not unconfigure card.\n");1124		goto error;1125	}1126 1127	rc = ibmphp_hpc_writeslot(slot_cur, HPC_SLOT_OFF);1128	if (rc)1129		goto error;1130 1131	attn_off(slot_cur);1132	rc = slot_update(&slot_cur);1133	if (rc)1134		goto exit;1135 1136	rc = ibmphp_update_slot_info(slot_cur);1137	ibmphp_print_test();1138exit:1139	return rc;1140 1141error:1142	/*  Need to turn off if was blinking b4 */1143	attn_off(slot_cur);1144	attn_on(slot_cur);1145	if (slot_update(&slot_cur)) {1146		rc = -EFAULT;1147		goto exit;1148	}1149	if (flag)1150		ibmphp_update_slot_info(slot_cur);1151	goto exit;1152}1153 1154const struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {1155	.set_attention_status =		set_attention_status,1156	.enable_slot =			enable_slot,1157	.disable_slot =			ibmphp_disable_slot,1158	.hardware_test =		NULL,1159	.get_power_status =		get_power_status,1160	.get_attention_status =		get_attention_status,1161	.get_latch_status =		get_latch_status,1162	.get_adapter_status =		get_adapter_present,1163};1164 1165static void ibmphp_unload(void)1166{1167	free_slots();1168	debug("after slots\n");1169	ibmphp_free_resources();1170	debug("after resources\n");1171	ibmphp_free_bus_info_queue();1172	debug("after bus info\n");1173	ibmphp_free_ebda_hpc_queue();1174	debug("after ebda hpc\n");1175	ibmphp_free_ebda_pci_rsrc_queue();1176	debug("after ebda pci rsrc\n");1177	kfree(ibmphp_pci_bus);1178}1179 1180static int __init ibmphp_init(void)1181{1182	struct pci_bus *bus;1183	int i = 0;1184	int rc = 0;1185 1186	init_flag = 1;1187 1188	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");1189 1190	ibmphp_pci_bus = kmalloc(sizeof(*ibmphp_pci_bus), GFP_KERNEL);1191	if (!ibmphp_pci_bus) {1192		rc = -ENOMEM;1193		goto exit;1194	}1195 1196	bus = pci_find_bus(0, 0);1197	if (!bus) {1198		err("Can't find the root pci bus, can not continue\n");1199		rc = -ENODEV;1200		goto error;1201	}1202	memcpy(ibmphp_pci_bus, bus, sizeof(*ibmphp_pci_bus));1203 1204	ibmphp_debug = debug;1205 1206	for (i = 0; i < 16; i++)1207		irqs[i] = 0;1208 1209	rc = ibmphp_access_ebda();1210	if (rc)1211		goto error;1212	debug("after ibmphp_access_ebda()\n");1213 1214	rc = ibmphp_rsrc_init();1215	if (rc)1216		goto error;1217	debug("AFTER Resource & EBDA INITIALIZATIONS\n");1218 1219	max_slots = get_max_slots();1220 1221	rc = ibmphp_register_pci();1222	if (rc)1223		goto error;1224 1225	if (init_ops()) {1226		rc = -ENODEV;1227		goto error;1228	}1229 1230	ibmphp_print_test();1231	rc = ibmphp_hpc_start_poll_thread();1232	if (rc)1233		goto error;1234 1235exit:1236	return rc;1237 1238error:1239	ibmphp_unload();1240	goto exit;1241}1242 1243static void __exit ibmphp_exit(void)1244{1245	ibmphp_hpc_stop_poll_thread();1246	debug("after polling\n");1247	ibmphp_unload();1248	debug("done\n");1249}1250 1251module_init(ibmphp_init);1252module_exit(ibmphp_exit);1253