Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.23
[sfrench/cifs-2.6.git] / drivers / scsi / dpt_i2o.c
index f7b9dbd64a96ee1ae0af28d786a12c1f7ef09574..502732ac270ddcfa7cbecec1e282f9ff0c944c42 100644 (file)
@@ -55,7 +55,6 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
 #include <linux/sched.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/dma-mapping.h>
 
 #include <linux/timer.h>
@@ -174,20 +173,20 @@ static struct pci_device_id dptids[] = {
 };
 MODULE_DEVICE_TABLE(pci,dptids);
 
-static int adpt_detect(struct scsi_host_template* sht)
+static void adpt_exit(void);
+
+static int adpt_detect(void)
 {
        struct pci_dev *pDev = NULL;
        adpt_hba* pHba;
 
-       adpt_init();
-
        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) ){
+                       if(adpt_install_hba(pDev) ){
                                PERROR("Could not Init an I2O RAID device\n");
                                PERROR("Will not try to detect others.\n");
                                return hba_count-1;
@@ -249,34 +248,33 @@ rebuild_sys_tab:
        }
 
        for (pHba = hba_chain; pHba; pHba = pHba->next) {
-               if( adpt_scsi_register(pHba,sht) < 0){
+               if (adpt_scsi_register(pHba) < 0) {
                        adpt_i2o_delete_hba(pHba);
                        continue;
                }
                pHba->initialized = TRUE;
                pHba->state &= ~DPTI_STATE_RESET;
+               scsi_scan_host(pHba->host);
        }
 
        // 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();
+               adpt_exit();
                return 0;
        }
        return hba_count;
 }
 
 
-/*
- * scsi_unregister will be called AFTER we return. 
- */
-static int adpt_release(struct Scsi_Host *host)
+static int adpt_release(adpt_hba *pHba)
 {
-       adpt_hba* pHba = (adpt_hba*) host->hostdata[0];
+       struct Scsi_Host *shost = pHba->host;
+       scsi_remove_host(shost);
 //     adpt_i2o_quiesce_hba(pHba);
        adpt_i2o_delete_hba(pHba);
-       scsi_unregister(host);
+       scsi_host_put(shost);
        return 0;
 }
 
@@ -883,7 +881,7 @@ static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p)
 #endif
 
 
-static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) 
+static int adpt_install_hba(struct pci_dev* pDev)
 {
 
        adpt_hba* pHba = NULL;
@@ -1032,8 +1030,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
 
 
        mutex_lock(&adpt_configuration_lock);
-       // scsi_unregister calls our adpt_release which
-       // does a quiese
        if(pHba->host){
                free_irq(pHba->host->irq, pHba);
        }
@@ -1085,17 +1081,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
 }
 
 
-static int adpt_init(void)
-{
-       printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
-#ifdef REBOOT_NOTIFIER
-       register_reboot_notifier(&adpt_reboot_notifier);
-#endif
-
-       return 0;
-}
-
-
 static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun)
 {
        struct adpt_device* d;
@@ -1309,13 +1294,12 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
                schedule_timeout_uninterruptible(1);
        } while (m == EMPTY_QUEUE);
 
-       status = kmalloc(4, GFP_KERNEL|ADDR32);
+       status = kzalloc(4, GFP_KERNEL|ADDR32);
        if(status == NULL) {
                adpt_send_nop(pHba, m);
                printk(KERN_ERR"IOP reset failed - no free memory.\n");
                return -ENOMEM;
        }
-       memset(status,0,4);
 
        msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
@@ -1505,21 +1489,19 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
                                        continue;
                                }
                                if( pHba->channel[bus_no].device[scsi_id] == NULL){
-                                       pDev =  kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev =  kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
                                        pHba->channel[bus_no].device[scsi_id] = pDev;
-                                       memset(pDev,0,sizeof(struct adpt_device));
                                } else {
                                        for( pDev = pHba->channel[bus_no].device[scsi_id];      
                                                        pDev->next_lun; pDev = pDev->next_lun){
                                        }
-                                       pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev->next_lun == NULL) {
                                                return -ENOMEM;
                                        }
-                                       memset(pDev->next_lun,0,sizeof(struct adpt_device));
                                        pDev = pDev->next_lun;
                                }
                                pDev->tid = tid;
@@ -1668,12 +1650,11 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
                reply_size = REPLY_FRAME_SIZE;
        }
        reply_size *= 4;
-       reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
+       reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
        if(reply == NULL) {
                printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
                return -ENOMEM;
        }
-       memset(reply,0,REPLY_FRAME_SIZE*4);
        sg_offset = (msg[0]>>4)&0xf;
        msg[2] = 0x40000000; // IOCTL context
        msg[3] = (u32)reply;
@@ -2083,12 +2064,13 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d
        u32 *lenptr;
        int direction;
        int scsidir;
+       int nseg;
        u32 len;
        u32 reqlen;
        s32 rcode;
 
        memset(msg, 0 , sizeof(msg));
-       len = cmd->request_bufflen;
+       len = scsi_bufflen(cmd);
        direction = 0x00000000; 
        
        scsidir = 0x00000000;                   // DATA NO XFER
@@ -2145,21 +2127,21 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d
        lenptr=mptr++;          /* Remember me - fill in when we know */
        reqlen = 14;            // SINGLE SGE
        /* Now fill in the SGList and command */
-       if(cmd->use_sg) {
-               struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
-               int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg,
-                               cmd->sc_data_direction);
 
+       nseg = scsi_dma_map(cmd);
+       BUG_ON(nseg < 0);
+       if (nseg) {
+               struct scatterlist *sg;
 
                len = 0;
-               for(i = 0 ; i < sg_count; i++) {
+               scsi_for_each_sg(cmd, sg, nseg, i) {
                        *mptr++ = direction|0x10000000|sg_dma_len(sg);
                        len+=sg_dma_len(sg);
                        *mptr++ = sg_dma_address(sg);
-                       sg++;
+                       /* Make this an end of list */
+                       if (i == nseg - 1)
+                               mptr[-2] = direction|0xD0000000|sg_dma_len(sg);
                }
-               /* Make this an end of list */
-               mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1);
                reqlen = mptr - msg;
                *lenptr = len;
                
@@ -2168,16 +2150,8 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d
                                len, cmd->underflow);
                }
        } else {
-               *lenptr = len = cmd->request_bufflen;
-               if(len == 0) {
-                       reqlen = 12;
-               } else {
-                       *mptr++ = 0xD0000000|direction|cmd->request_bufflen;
-                       *mptr++ = pci_map_single(pHba->pDev,
-                               cmd->request_buffer,
-                               cmd->request_bufflen,
-                               cmd->sc_data_direction);
-               }
+               *lenptr = len = 0;
+               reqlen = 12;
        }
        
        /* Stick the headers on */
@@ -2192,37 +2166,6 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d
 }
 
 
-static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht)
-{
-       struct Scsi_Host *host = NULL;
-
-       host = scsi_register(sht, sizeof(adpt_hba*));
-       if (host == NULL) {
-               printk ("%s: scsi_register returned NULL\n",pHba->name);
-               return -1;
-       }
-       host->hostdata[0] = (unsigned long)pHba;
-       pHba->host = host;
-
-       host->irq = pHba->pDev->irq;
-       /* no IO ports, so don't have to set host->io_port and 
-        * host->n_io_port
-        */
-       host->io_port = 0;
-       host->n_io_port = 0;
-                               /* see comments in scsi_host.h */
-       host->max_id = 16;
-       host->max_lun = 256;
-       host->max_channel = pHba->top_scsi_channel + 1;
-       host->cmd_per_lun = 1;
-       host->unique_id = (uint) pHba;
-       host->sg_tablesize = pHba->sg_tablesize;
-       host->can_queue = pHba->post_fifo_size;
-
-       return 0;
-}
-
-
 static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
 {
        adpt_hba* pHba;
@@ -2237,7 +2180,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
        hba_status = detailed_status >> 8;
 
        // calculate resid for sg 
-       cmd->resid = cmd->request_bufflen - readl(reply+5);
+       scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
 
        pHba = (adpt_hba*) cmd->device->host->hostdata[0];
 
@@ -2445,7 +2388,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
                                }
                                pDev = pHba->channel[bus_no].device[scsi_id];   
                                if( pDev == NULL){
-                                       pDev =  kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev =  kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
@@ -2454,12 +2397,11 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
                                        while (pDev->next_lun) {
                                                pDev = pDev->next_lun;
                                        }
-                                       pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
+                                       pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
                                        if(pDev == NULL) {
                                                return -ENOMEM;
                                        }
                                }
-                               memset(pDev,0,sizeof(struct adpt_device));
                                pDev->tid = d->lct_data.tid;
                                pDev->scsi_channel = bus_no;
                                pDev->scsi_id = scsi_id;
@@ -3342,12 +3284,10 @@ static static void adpt_delay(int millisec)
 
 #endif
 
-static struct scsi_host_template driver_template = {
+static struct scsi_host_template adpt_template = {
        .name                   = "dpt_i2o",
        .proc_name              = "dpt_i2o",
        .proc_info              = adpt_proc_info,
-       .detect                 = adpt_detect,  
-       .release                = adpt_release,
        .info                   = adpt_info,
        .queuecommand           = adpt_queue,
        .eh_abort_handler       = adpt_abort,
@@ -3361,5 +3301,62 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
 };
-#include "scsi_module.c"
+
+static s32 adpt_scsi_register(adpt_hba* pHba)
+{
+       struct Scsi_Host *host;
+
+       host = scsi_host_alloc(&adpt_template, sizeof(adpt_hba*));
+       if (host == NULL) {
+               printk ("%s: scsi_host_alloc returned NULL\n",pHba->name);
+               return -1;
+       }
+       host->hostdata[0] = (unsigned long)pHba;
+       pHba->host = host;
+
+       host->irq = pHba->pDev->irq;
+       /* no IO ports, so don't have to set host->io_port and
+        * host->n_io_port
+        */
+       host->io_port = 0;
+       host->n_io_port = 0;
+                               /* see comments in scsi_host.h */
+       host->max_id = 16;
+       host->max_lun = 256;
+       host->max_channel = pHba->top_scsi_channel + 1;
+       host->cmd_per_lun = 1;
+       host->unique_id = (uint) pHba;
+       host->sg_tablesize = pHba->sg_tablesize;
+       host->can_queue = pHba->post_fifo_size;
+
+       if (scsi_add_host(host, &pHba->pDev->dev)) {
+               scsi_host_put(host);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int __init adpt_init(void)
+{
+       int count;
+
+       printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
+#ifdef REBOOT_NOTIFIER
+       register_reboot_notifier(&adpt_reboot_notifier);
+#endif
+
+       count = adpt_detect();
+
+       return count > 0 ? 0 : -ENODEV;
+}
+
+static void __exit adpt_exit(void)
+{
+       while (hba_chain)
+               adpt_release(hba_chain);
+}
+
+module_init(adpt_init);
+module_exit(adpt_exit);
 MODULE_LICENSE("GPL");