diff mbox

[v2,SCSI] dpt_i2o: use proper pci driver

Message ID 1455711614-5185-1-git-send-email-sudipm.mukherjee@gmail.com (mailing list archive)
State Rejected, archived
Headers show

Commit Message

Sudip Mukherjee Feb. 17, 2016, 12:20 p.m. UTC
This is a pci device but was not done in the usual way a pci driver is
done. Convert the driver into a proper pci driver.

Signed-off-by: Sudip Mukherjee <sudip@vectorindia.org>
---

v1: only build warning related to "dptids defined but not used" was
fixed using #ifdef

 drivers/scsi/dpt_i2o.c | 269 ++++++++++++++++++++++---------------------------
 drivers/scsi/dpti.h    |   5 +-
 2 files changed, 120 insertions(+), 154 deletions(-)

Comments

Alan Cox Feb. 17, 2016, 2:27 p.m. UTC | #1
On Wed, 17 Feb 2016 17:50:14 +0530
Sudip Mukherjee <sudipm.mukherjee@gmail.com> wrote:

> This is a pci device but was not done in the usual way a pci driver is
> done. Convert the driver into a proper pci driver.

This looks completely wrong. Please read the I2O 1.5 specification
document before playing with that code. You can't simply convert it to a
standard PCI driver as all the IOPs are supposed to be detected and then
the correct initialization sequence executed across the set of IOPs. IOPs
are allowed to talk to one another and the system table binds it all
together.

If you do hot plug then you need to follow the specification and do
all the extra notifications. Unless you've got multiple FC909/FC920
fibechannel cards or similar to test with I would just leave this well
alone. Your original simple patch is *MUCH* safer in this specific case.

So NAK

Alan


> 
> Signed-off-by: Sudip Mukherjee <sudip@vectorindia.org>
> ---
> 
> v1: only build warning related to "dptids defined but not used" was
> fixed using #ifdef
> 
>  drivers/scsi/dpt_i2o.c | 269 ++++++++++++++++++++++---------------------------
>  drivers/scsi/dpti.h    |   5 +-
>  2 files changed, 120 insertions(+), 154 deletions(-)
> 
> diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
> index d4cda5e..9f50d1ae 100644
> --- a/drivers/scsi/dpt_i2o.c
> +++ b/drivers/scsi/dpt_i2o.c
> @@ -111,6 +111,7 @@ static int sys_tbl_len;
>  
>  static adpt_hba* hba_chain = NULL;
>  static int hba_count = 0;
> +static bool control_reg;
>  
>  static struct class *adpt_sysfs_class;
>  
> @@ -187,118 +188,6 @@ static struct pci_device_id dptids[] = {
>  };
>  MODULE_DEVICE_TABLE(pci,dptids);
>  
> -static int adpt_detect(struct scsi_host_template* sht)
> -{
> -	struct pci_dev *pDev = NULL;
> -	adpt_hba *pHba;
> -	adpt_hba *next;
> -
> -	PINFO("Detecting Adaptec I2O RAID controllers...\n");
> -
> -        /* search for all Adatpec I2O RAID cards */
> -	while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {
> -		if(pDev->device == PCI_DPT_DEVICE_ID ||
> -		   pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){
> -			if(adpt_install_hba(sht, pDev) ){
> -				PERROR("Could not Init an I2O RAID device\n");
> -				PERROR("Will not try to detect others.\n");
> -				return hba_count-1;
> -			}
> -			pci_dev_get(pDev);
> -		}
> -	}
> -
> -	/* In INIT state, Activate IOPs */
> -	for (pHba = hba_chain; pHba; pHba = next) {
> -		next = pHba->next;
> -		// Activate does get status , init outbound, and get hrt
> -		if (adpt_i2o_activate_hba(pHba) < 0) {
> -			adpt_i2o_delete_hba(pHba);
> -		}
> -	}
> -
> -
> -	/* Active IOPs in HOLD state */
> -
> -rebuild_sys_tab:
> -	if (hba_chain == NULL) 
> -		return 0;
> -
> -	/*
> -	 * If build_sys_table fails, we kill everything and bail
> -	 * as we can't init the IOPs w/o a system table
> -	 */	
> -	if (adpt_i2o_build_sys_table() < 0) {
> -		adpt_i2o_sys_shutdown();
> -		return 0;
> -	}
> -
> -	PDEBUG("HBA's in HOLD state\n");
> -
> -	/* If IOP don't get online, we need to rebuild the System table */
> -	for (pHba = hba_chain; pHba; pHba = pHba->next) {
> -		if (adpt_i2o_online_hba(pHba) < 0) {
> -			adpt_i2o_delete_hba(pHba);	
> -			goto rebuild_sys_tab;
> -		}
> -	}
> -
> -	/* Active IOPs now in OPERATIONAL state */
> -	PDEBUG("HBA's in OPERATIONAL state\n");
> -
> -	printk("dpti: If you have a lot of devices this could take a few minutes.\n");
> -	for (pHba = hba_chain; pHba; pHba = next) {
> -		next = pHba->next;
> -		printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
> -		if (adpt_i2o_lct_get(pHba) < 0){
> -			adpt_i2o_delete_hba(pHba);
> -			continue;
> -		}
> -
> -		if (adpt_i2o_parse_lct(pHba) < 0){
> -			adpt_i2o_delete_hba(pHba);
> -			continue;
> -		}
> -		adpt_inquiry(pHba);
> -	}
> -
> -	adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
> -	if (IS_ERR(adpt_sysfs_class)) {
> -		printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n");
> -		adpt_sysfs_class = NULL;
> -	}
> -
> -	for (pHba = hba_chain; pHba; pHba = next) {
> -		next = pHba->next;
> -		if (adpt_scsi_host_alloc(pHba, sht) < 0){
> -			adpt_i2o_delete_hba(pHba);
> -			continue;
> -		}
> -		pHba->initialized = TRUE;
> -		pHba->state &= ~DPTI_STATE_RESET;
> -		if (adpt_sysfs_class) {
> -			struct device *dev = device_create(adpt_sysfs_class,
> -				NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
> -				"dpti%d", pHba->unit);
> -			if (IS_ERR(dev)) {
> -				printk(KERN_WARNING"dpti%d: unable to "
> -					"create device in dpt_i2o class\n",
> -					pHba->unit);
> -			}
> -		}
> -	}
> -
> -	// Register our control device node
> -	// nodes will need to be created in /dev to access this
> -	// the nodes can not be created from within the driver
> -	if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
> -		adpt_i2o_sys_shutdown();
> -		return 0;
> -	}
> -	return hba_count;
> -}
> -
> -
>  /*
>   * scsi_unregister will be called AFTER we return.
>   */
> @@ -901,7 +790,8 @@ static void adpt_i2o_sys_shutdown(void)
>  	 printk(KERN_INFO "Adaptec I2O controllers down.\n");
>  }
>  
> -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
> +static adpt_hba *adpt_install_hba(struct scsi_host_template *sht,
> +				  struct pci_dev *pDev)
>  {
>  
>  	adpt_hba* pHba = NULL;
> @@ -917,12 +807,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  	int raptorFlag = FALSE;
>  
>  	if(pci_enable_device(pDev)) {
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  	}
>  
>  	if (pci_request_regions(pDev, "dpt_i2o")) {
>  		PERROR("dpti: adpt_config_hba: pci request region failed\n");
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  	}
>  
>  	pci_set_master(pDev);
> @@ -936,7 +826,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  			dma64 = 1;
>  	}
>  	if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0)
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  
>  	/* adapter only supports message blocks below 4GB */
>  	pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32));
> @@ -984,7 +874,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  	if (!base_addr_virt) {
>  		pci_release_regions(pDev);
>  		PERROR("dpti: adpt_config_hba: io remap failed\n");
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  	}
>  
>          if(raptorFlag == TRUE) {
> @@ -993,7 +883,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  			PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
>  			iounmap(base_addr_virt);
>  			pci_release_regions(pDev);
> -			return -EINVAL;
> +			return ERR_PTR(-EINVAL);
>  		}
>  	} else {
>  		msg_addr_virt = base_addr_virt;
> @@ -1006,7 +896,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  			iounmap(msg_addr_virt);
>  		iounmap(base_addr_virt);
>  		pci_release_regions(pDev);
> -		return -ENOMEM;
> +		return ERR_PTR(-ENOMEM);
>  	}
>  
>  	mutex_lock(&adpt_configuration_lock);
> @@ -1065,10 +955,10 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
>  	if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
>  		printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
>  		adpt_i2o_delete_hba(pHba);
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  	}
>  
> -	return 0;
> +	return pHba;
>  }
>  
>  
> @@ -3568,47 +3458,124 @@ static struct scsi_host_template driver_template = {
>  	.use_clustering		= ENABLE_CLUSTERING,
>  };
>  
> -static int __init adpt_init(void)
> +static int adpt_pci_probe(struct pci_dev *pdev,
> +			  const struct pci_device_id *ent)
>  {
> -	int		error;
> -	adpt_hba	*pHba, *next;
> +	struct scsi_host_template *sht = &driver_template;
> +	adpt_hba *pHba, *pHba_temp;
> +	int err;
>  
> -	printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
> +	pHba = adpt_install_hba(sht, pdev);
> +	if (IS_ERR(pHba)) {
> +		PERROR("Could not Init an I2O RAID device\n");
> +		return PTR_ERR(pHba);
> +	}
>  
> -	error = adpt_detect(&driver_template);
> -	if (error < 0)
> -		return error;
> -	if (hba_chain == NULL)
> -		return -ENODEV;
> +	/*
> +	 * In INIT state, Activate IOPs
> +	 * Activate does get status , init outbound, and get hrt
> +	 */
> +	if (adpt_i2o_activate_hba(pHba) < 0)
> +		adpt_i2o_delete_hba(pHba);
>  
> -	for (pHba = hba_chain; pHba; pHba = pHba->next) {
> -		error = scsi_add_host(pHba->host, &pHba->pDev->dev);
> -		if (error)
> -			goto fail;
> -		scsi_scan_host(pHba->host);
> +	/* Active IOPs in HOLD state */
> +
> +rebuild_sys_tab:
> +	/*
> +	 * If build_sys_table fails, we kill everything and bail
> +	 * as we can't init the IOPs w/o a system table
> +	 */
> +	if (adpt_i2o_build_sys_table() < 0) {
> +		adpt_i2o_sys_shutdown();
> +		return -EIO;
>  	}
> -	return 0;
> -fail:
> -	for (pHba = hba_chain; pHba; pHba = next) {
> -		next = pHba->next;
> -		scsi_remove_host(pHba->host);
> +
> +	PDEBUG("HBA's in HOLD state\n");
> +
> +	/* If IOP don't get online, we need to rebuild the System table */
> +	for (pHba_temp = hba_chain; pHba_temp; pHba_temp = pHba_temp->next) {
> +		if (adpt_i2o_online_hba(pHba_temp) < 0) {
> +			adpt_i2o_delete_hba(pHba_temp);
> +			goto rebuild_sys_tab;
> +		}
>  	}
> -	return error;
> +
> +	/* Active IOPs now in OPERATIONAL state */
> +	PDEBUG("%s: HBA in OPERATIONAL state\n", pHba->name);
> +
> +	if (adpt_i2o_lct_get(pHba) < 0) {
> +		adpt_i2o_delete_hba(pHba);
> +		return -EIO;
> +	}
> +	if (adpt_i2o_parse_lct(pHba) < 0) {
> +		adpt_i2o_delete_hba(pHba);
> +		return -EIO;
> +	}
> +	adpt_inquiry(pHba);
> +
> +	if (!adpt_sysfs_class) {
> +		adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
> +		if (IS_ERR(adpt_sysfs_class)) {
> +			printk(KERN_WARNING
> +			       "dpti: unable to create dpt_i2o class\n");
> +			adpt_sysfs_class = NULL;
> +		}
> +	}
> +	if (adpt_scsi_host_alloc(pHba, sht) < 0) {
> +		adpt_i2o_delete_hba(pHba);
> +		return -EIO;
> +	}
> +
> +	pHba->initialized = TRUE;
> +	pHba->state &= ~DPTI_STATE_RESET;
> +	if (adpt_sysfs_class) {
> +		struct device *dev = device_create(adpt_sysfs_class,
> +			NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
> +			"dpti%d", pHba->unit);
> +		if (IS_ERR(dev)) {
> +			printk(KERN_WARNING
> +			       "dpti%d: unable to create device in dpt_i2o class\n",
> +			       pHba->unit);
> +		}
> +	}
> +
> +	/*
> +	 * Register our control device node
> +	 * nodes will need to be created in /dev to access this
> +	 * the nodes can not be created from within the driver
> +	 */
> +	if (!control_reg && hba_count) {
> +		if (register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
> +		adpt_i2o_sys_shutdown();
> +		return -EIO;
> +		}
> +		control_reg = true;
> +	}
> +
> +	err = scsi_add_host(pHba->host, &pHba->pDev->dev);
> +	if (err)
> +		return err;
> +
> +	scsi_scan_host(pHba->host);
> +	pci_set_drvdata(pdev, pHba);
> +
> +	return 0;
>  }
>  
> -static void __exit adpt_exit(void)
> +static void adpt_pci_remove(struct pci_dev *pdev)
>  {
> -	adpt_hba	*pHba, *next;
> +	adpt_hba *pHba = pci_get_drvdata(pdev);
>  
> -	for (pHba = hba_chain; pHba; pHba = pHba->next)
> -		scsi_remove_host(pHba->host);
> -	for (pHba = hba_chain; pHba; pHba = next) {
> -		next = pHba->next;
> -		adpt_release(pHba->host);
> -	}
> +	scsi_remove_host(pHba->host);
> +	adpt_release(pHba->host);
>  }
>  
> -module_init(adpt_init);
> -module_exit(adpt_exit);
> +static struct pci_driver adpt_driver = {
> +	.name = "adpt",
> +	.id_table = dptids,
> +	.probe = adpt_pci_probe,
> +	.remove = adpt_pci_remove,
> +};
>  
> +module_pci_driver(adpt_driver);
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
> index 1fa345a..e3481a4 100644
> --- a/drivers/scsi/dpti.h
> +++ b/drivers/scsi/dpti.h
> @@ -28,7 +28,6 @@
>   * SCSI interface function Prototypes
>   */
>  
> -static int adpt_detect(struct scsi_host_template * sht);
>  static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd);
>  static int adpt_abort(struct scsi_cmnd * cmd);
>  static int adpt_reset(struct scsi_cmnd* cmd);
> @@ -265,7 +264,6 @@ struct sg_simple_element {
>   */
>  
>  static void adpt_i2o_sys_shutdown(void);
> -static int adpt_init(void);
>  static int adpt_i2o_build_sys_table(void);
>  static irqreturn_t adpt_isr(int irq, void *dev_id);
>  
> @@ -301,7 +299,8 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba);
>  static void adpt_inquiry(adpt_hba* pHba);
>  static void adpt_fail_posted_scbs(adpt_hba* pHba);
>  static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun);
> -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
> +static adpt_hba *adpt_install_hba(struct scsi_host_template *sht,
> +				  struct pci_dev *pDev);
>  static int adpt_i2o_online_hba(adpt_hba* pHba);
>  static void adpt_i2o_post_wait_complete(u32, int);
>  static int adpt_i2o_systab_send(adpt_hba* pHba);
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sudip Mukherjee Feb. 17, 2016, 3:50 p.m. UTC | #2
On Wednesday 17 February 2016 07:57 PM, One Thousand Gnomes wrote:
> On Wed, 17 Feb 2016 17:50:14 +0530
> Sudip Mukherjee <sudipm.mukherjee@gmail.com> wrote:
>
>> This is a pci device but was not done in the usual way a pci driver is
>> done. Convert the driver into a proper pci driver.
>
> This looks completely wrong. Please read the I2O 1.5 specification
> document before playing with that code. You can't simply convert it to a
> standard PCI driver as all the IOPs are supposed to be detected and then
> the correct initialization sequence executed across the set of IOPs. IOPs
> are allowed to talk to one another and the system table binds it all
> together.

Yes, thanks for letting me know about the spec. It is saying
"The host locates each IOP, adds it
to the system configuration table, and initializes the IOP’s outbound 
message queue. The host then
provides each IOP with a list of all IOPs and the physical location of 
their inbound message queue."

>
> If you do hot plug then you need to follow the specification and do
> all the extra notifications. Unless you've got multiple FC909/FC920
> fibechannel cards or similar to test with I would just leave this well
> alone.

point noted.

> Your original simple patch is *MUCH* safer in this specific case.

The original patch is already having NACK from Johannes. So i better 
leave this code here.

regards
sudip
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Thumshirn Feb. 18, 2016, 8:19 a.m. UTC | #3
On Wed, Feb 17, 2016 at 09:20:03PM +0530, Sudip Mukherjee wrote:
> On Wednesday 17 February 2016 07:57 PM, One Thousand Gnomes wrote:
> >On Wed, 17 Feb 2016 17:50:14 +0530
> >Sudip Mukherjee <sudipm.mukherjee@gmail.com> wrote:
> >
> >>This is a pci device but was not done in the usual way a pci driver is
> >>done. Convert the driver into a proper pci driver.
> >
> >This looks completely wrong. Please read the I2O 1.5 specification
> >document before playing with that code. You can't simply convert it to a
> >standard PCI driver as all the IOPs are supposed to be detected and then
> >the correct initialization sequence executed across the set of IOPs. IOPs
> >are allowed to talk to one another and the system table binds it all
> >together.
> 
> Yes, thanks for letting me know about the spec. It is saying
> "The host locates each IOP, adds it
> to the system configuration table, and initializes the IOP’s outbound
> message queue. The host then
> provides each IOP with a list of all IOPs and the physical location of their
> inbound message queue."
> 
> >
> >If you do hot plug then you need to follow the specification and do
> >all the extra notifications. Unless you've got multiple FC909/FC920
> >fibechannel cards or similar to test with I would just leave this well
> >alone.
> 
> point noted.
> 
> >Your original simple patch is *MUCH* safer in this specific case.
> 
> The original patch is already having NACK from Johannes. So i better leave
> this code here.

Nah, wasn't a hard NACK. I'm OK with the original code, just was reluctant to
the #ifdefs. I agree I didn't know the I2O specifics and thought a "normal"
PCI driver fitting nicely in the driver model would be the way to go.

Please resend your v1 with my Reviewed-by

> 
> regards
> sudip
diff mbox

Patch

diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index d4cda5e..9f50d1ae 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -111,6 +111,7 @@  static int sys_tbl_len;
 
 static adpt_hba* hba_chain = NULL;
 static int hba_count = 0;
+static bool control_reg;
 
 static struct class *adpt_sysfs_class;
 
@@ -187,118 +188,6 @@  static struct pci_device_id dptids[] = {
 };
 MODULE_DEVICE_TABLE(pci,dptids);
 
-static int adpt_detect(struct scsi_host_template* sht)
-{
-	struct pci_dev *pDev = NULL;
-	adpt_hba *pHba;
-	adpt_hba *next;
-
-	PINFO("Detecting Adaptec I2O RAID controllers...\n");
-
-        /* search for all Adatpec I2O RAID cards */
-	while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {
-		if(pDev->device == PCI_DPT_DEVICE_ID ||
-		   pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){
-			if(adpt_install_hba(sht, pDev) ){
-				PERROR("Could not Init an I2O RAID device\n");
-				PERROR("Will not try to detect others.\n");
-				return hba_count-1;
-			}
-			pci_dev_get(pDev);
-		}
-	}
-
-	/* In INIT state, Activate IOPs */
-	for (pHba = hba_chain; pHba; pHba = next) {
-		next = pHba->next;
-		// Activate does get status , init outbound, and get hrt
-		if (adpt_i2o_activate_hba(pHba) < 0) {
-			adpt_i2o_delete_hba(pHba);
-		}
-	}
-
-
-	/* Active IOPs in HOLD state */
-
-rebuild_sys_tab:
-	if (hba_chain == NULL) 
-		return 0;
-
-	/*
-	 * If build_sys_table fails, we kill everything and bail
-	 * as we can't init the IOPs w/o a system table
-	 */	
-	if (adpt_i2o_build_sys_table() < 0) {
-		adpt_i2o_sys_shutdown();
-		return 0;
-	}
-
-	PDEBUG("HBA's in HOLD state\n");
-
-	/* If IOP don't get online, we need to rebuild the System table */
-	for (pHba = hba_chain; pHba; pHba = pHba->next) {
-		if (adpt_i2o_online_hba(pHba) < 0) {
-			adpt_i2o_delete_hba(pHba);	
-			goto rebuild_sys_tab;
-		}
-	}
-
-	/* Active IOPs now in OPERATIONAL state */
-	PDEBUG("HBA's in OPERATIONAL state\n");
-
-	printk("dpti: If you have a lot of devices this could take a few minutes.\n");
-	for (pHba = hba_chain; pHba; pHba = next) {
-		next = pHba->next;
-		printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
-		if (adpt_i2o_lct_get(pHba) < 0){
-			adpt_i2o_delete_hba(pHba);
-			continue;
-		}
-
-		if (adpt_i2o_parse_lct(pHba) < 0){
-			adpt_i2o_delete_hba(pHba);
-			continue;
-		}
-		adpt_inquiry(pHba);
-	}
-
-	adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
-	if (IS_ERR(adpt_sysfs_class)) {
-		printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n");
-		adpt_sysfs_class = NULL;
-	}
-
-	for (pHba = hba_chain; pHba; pHba = next) {
-		next = pHba->next;
-		if (adpt_scsi_host_alloc(pHba, sht) < 0){
-			adpt_i2o_delete_hba(pHba);
-			continue;
-		}
-		pHba->initialized = TRUE;
-		pHba->state &= ~DPTI_STATE_RESET;
-		if (adpt_sysfs_class) {
-			struct device *dev = device_create(adpt_sysfs_class,
-				NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
-				"dpti%d", pHba->unit);
-			if (IS_ERR(dev)) {
-				printk(KERN_WARNING"dpti%d: unable to "
-					"create device in dpt_i2o class\n",
-					pHba->unit);
-			}
-		}
-	}
-
-	// Register our control device node
-	// nodes will need to be created in /dev to access this
-	// the nodes can not be created from within the driver
-	if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
-		adpt_i2o_sys_shutdown();
-		return 0;
-	}
-	return hba_count;
-}
-
-
 /*
  * scsi_unregister will be called AFTER we return.
  */
@@ -901,7 +790,8 @@  static void adpt_i2o_sys_shutdown(void)
 	 printk(KERN_INFO "Adaptec I2O controllers down.\n");
 }
 
-static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev)
+static adpt_hba *adpt_install_hba(struct scsi_host_template *sht,
+				  struct pci_dev *pDev)
 {
 
 	adpt_hba* pHba = NULL;
@@ -917,12 +807,12 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 	int raptorFlag = FALSE;
 
 	if(pci_enable_device(pDev)) {
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	if (pci_request_regions(pDev, "dpt_i2o")) {
 		PERROR("dpti: adpt_config_hba: pci request region failed\n");
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	pci_set_master(pDev);
@@ -936,7 +826,7 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 			dma64 = 1;
 	}
 	if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0)
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 
 	/* adapter only supports message blocks below 4GB */
 	pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32));
@@ -984,7 +874,7 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 	if (!base_addr_virt) {
 		pci_release_regions(pDev);
 		PERROR("dpti: adpt_config_hba: io remap failed\n");
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
         if(raptorFlag == TRUE) {
@@ -993,7 +883,7 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 			PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
 			iounmap(base_addr_virt);
 			pci_release_regions(pDev);
-			return -EINVAL;
+			return ERR_PTR(-EINVAL);
 		}
 	} else {
 		msg_addr_virt = base_addr_virt;
@@ -1006,7 +896,7 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 			iounmap(msg_addr_virt);
 		iounmap(base_addr_virt);
 		pci_release_regions(pDev);
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	mutex_lock(&adpt_configuration_lock);
@@ -1065,10 +955,10 @@  static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
 	if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) {
 		printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq);
 		adpt_i2o_delete_hba(pHba);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
-	return 0;
+	return pHba;
 }
 
 
@@ -3568,47 +3458,124 @@  static struct scsi_host_template driver_template = {
 	.use_clustering		= ENABLE_CLUSTERING,
 };
 
-static int __init adpt_init(void)
+static int adpt_pci_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *ent)
 {
-	int		error;
-	adpt_hba	*pHba, *next;
+	struct scsi_host_template *sht = &driver_template;
+	adpt_hba *pHba, *pHba_temp;
+	int err;
 
-	printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
+	pHba = adpt_install_hba(sht, pdev);
+	if (IS_ERR(pHba)) {
+		PERROR("Could not Init an I2O RAID device\n");
+		return PTR_ERR(pHba);
+	}
 
-	error = adpt_detect(&driver_template);
-	if (error < 0)
-		return error;
-	if (hba_chain == NULL)
-		return -ENODEV;
+	/*
+	 * In INIT state, Activate IOPs
+	 * Activate does get status , init outbound, and get hrt
+	 */
+	if (adpt_i2o_activate_hba(pHba) < 0)
+		adpt_i2o_delete_hba(pHba);
 
-	for (pHba = hba_chain; pHba; pHba = pHba->next) {
-		error = scsi_add_host(pHba->host, &pHba->pDev->dev);
-		if (error)
-			goto fail;
-		scsi_scan_host(pHba->host);
+	/* Active IOPs in HOLD state */
+
+rebuild_sys_tab:
+	/*
+	 * If build_sys_table fails, we kill everything and bail
+	 * as we can't init the IOPs w/o a system table
+	 */
+	if (adpt_i2o_build_sys_table() < 0) {
+		adpt_i2o_sys_shutdown();
+		return -EIO;
 	}
-	return 0;
-fail:
-	for (pHba = hba_chain; pHba; pHba = next) {
-		next = pHba->next;
-		scsi_remove_host(pHba->host);
+
+	PDEBUG("HBA's in HOLD state\n");
+
+	/* If IOP don't get online, we need to rebuild the System table */
+	for (pHba_temp = hba_chain; pHba_temp; pHba_temp = pHba_temp->next) {
+		if (adpt_i2o_online_hba(pHba_temp) < 0) {
+			adpt_i2o_delete_hba(pHba_temp);
+			goto rebuild_sys_tab;
+		}
 	}
-	return error;
+
+	/* Active IOPs now in OPERATIONAL state */
+	PDEBUG("%s: HBA in OPERATIONAL state\n", pHba->name);
+
+	if (adpt_i2o_lct_get(pHba) < 0) {
+		adpt_i2o_delete_hba(pHba);
+		return -EIO;
+	}
+	if (adpt_i2o_parse_lct(pHba) < 0) {
+		adpt_i2o_delete_hba(pHba);
+		return -EIO;
+	}
+	adpt_inquiry(pHba);
+
+	if (!adpt_sysfs_class) {
+		adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o");
+		if (IS_ERR(adpt_sysfs_class)) {
+			printk(KERN_WARNING
+			       "dpti: unable to create dpt_i2o class\n");
+			adpt_sysfs_class = NULL;
+		}
+	}
+	if (adpt_scsi_host_alloc(pHba, sht) < 0) {
+		adpt_i2o_delete_hba(pHba);
+		return -EIO;
+	}
+
+	pHba->initialized = TRUE;
+	pHba->state &= ~DPTI_STATE_RESET;
+	if (adpt_sysfs_class) {
+		struct device *dev = device_create(adpt_sysfs_class,
+			NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
+			"dpti%d", pHba->unit);
+		if (IS_ERR(dev)) {
+			printk(KERN_WARNING
+			       "dpti%d: unable to create device in dpt_i2o class\n",
+			       pHba->unit);
+		}
+	}
+
+	/*
+	 * Register our control device node
+	 * nodes will need to be created in /dev to access this
+	 * the nodes can not be created from within the driver
+	 */
+	if (!control_reg && hba_count) {
+		if (register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {
+		adpt_i2o_sys_shutdown();
+		return -EIO;
+		}
+		control_reg = true;
+	}
+
+	err = scsi_add_host(pHba->host, &pHba->pDev->dev);
+	if (err)
+		return err;
+
+	scsi_scan_host(pHba->host);
+	pci_set_drvdata(pdev, pHba);
+
+	return 0;
 }
 
-static void __exit adpt_exit(void)
+static void adpt_pci_remove(struct pci_dev *pdev)
 {
-	adpt_hba	*pHba, *next;
+	adpt_hba *pHba = pci_get_drvdata(pdev);
 
-	for (pHba = hba_chain; pHba; pHba = pHba->next)
-		scsi_remove_host(pHba->host);
-	for (pHba = hba_chain; pHba; pHba = next) {
-		next = pHba->next;
-		adpt_release(pHba->host);
-	}
+	scsi_remove_host(pHba->host);
+	adpt_release(pHba->host);
 }
 
-module_init(adpt_init);
-module_exit(adpt_exit);
+static struct pci_driver adpt_driver = {
+	.name = "adpt",
+	.id_table = dptids,
+	.probe = adpt_pci_probe,
+	.remove = adpt_pci_remove,
+};
 
+module_pci_driver(adpt_driver);
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
index 1fa345a..e3481a4 100644
--- a/drivers/scsi/dpti.h
+++ b/drivers/scsi/dpti.h
@@ -28,7 +28,6 @@ 
  * SCSI interface function Prototypes
  */
 
-static int adpt_detect(struct scsi_host_template * sht);
 static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd);
 static int adpt_abort(struct scsi_cmnd * cmd);
 static int adpt_reset(struct scsi_cmnd* cmd);
@@ -265,7 +264,6 @@  struct sg_simple_element {
  */
 
 static void adpt_i2o_sys_shutdown(void);
-static int adpt_init(void);
 static int adpt_i2o_build_sys_table(void);
 static irqreturn_t adpt_isr(int irq, void *dev_id);
 
@@ -301,7 +299,8 @@  static void adpt_i2o_delete_hba(adpt_hba* pHba);
 static void adpt_inquiry(adpt_hba* pHba);
 static void adpt_fail_posted_scbs(adpt_hba* pHba);
 static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun);
-static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
+static adpt_hba *adpt_install_hba(struct scsi_host_template *sht,
+				  struct pci_dev *pDev);
 static int adpt_i2o_online_hba(adpt_hba* pHba);
 static void adpt_i2o_post_wait_complete(u32, int);
 static int adpt_i2o_systab_send(adpt_hba* pHba);