]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/aic7xxx/aic7xxx_osm.c
Pull sn-handle-sc-powerdown into release branch
[linux-2.6-omap-h63xx.git] / drivers / scsi / aic7xxx / aic7xxx_osm.c
index 6ee1435d37fac9efbce4d3a3ecd763c4ed2cfe5e..051970efba6803a0486e6b6a8b09573d71201b07 100644 (file)
@@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
                                         struct scsi_cmnd *cmd);
 static void ahc_linux_sem_timeout(u_long arg);
 static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
-static void ahc_linux_release_simq(u_long arg);
+static void ahc_linux_release_simq(struct ahc_softc *ahc);
 static int  ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
 static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -476,26 +476,20 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 {
        struct   ahc_softc *ahc;
        struct   ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
+       int rtn = SCSI_MLQUEUE_HOST_BUSY;
+       unsigned long flags;
 
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
-       /*
-        * Save the callback on completion function.
-        */
-       cmd->scsi_done = scsi_done;
-
-       /*
-        * Close the race of a command that was in the process of
-        * being queued to us just as our simq was frozen.  Let
-        * DV commands through so long as we are only frozen to
-        * perform DV.
-        */
-       if (ahc->platform_data->qfrozen != 0)
-               return SCSI_MLQUEUE_HOST_BUSY;
-
-       cmd->result = CAM_REQ_INPROG << 16;
+       ahc_lock(ahc, &flags);
+       if (ahc->platform_data->qfrozen == 0) {
+               cmd->scsi_done = scsi_done;
+               cmd->result = CAM_REQ_INPROG << 16;
+               rtn = ahc_linux_run_command(ahc, dev, cmd);
+       }
+       ahc_unlock(ahc, &flags);
 
-       return ahc_linux_run_command(ahc, dev, cmd);
+       return rtn;
 }
 
 static inline struct scsi_target **
@@ -641,7 +635,7 @@ ahc_linux_slave_configure(struct scsi_device *sdev)
        ahc = *((struct ahc_softc **)sdev->host->hostdata);
 
        if (bootverbose)
-               printf("%s: Slave Configure %d\n", ahc_name(ahc), sdev->id);
+               sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
 
        ahc_linux_device_queue_depth(sdev);
 
@@ -686,7 +680,7 @@ ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
        u_int    channel;
 
        ahc = *((struct ahc_softc **)sdev->host->hostdata);
-       channel = sdev->channel;
+       channel = sdev_channel(sdev);
 
        bh = scsi_bios_ptable(bdev);
        if (bh) {
@@ -759,7 +753,7 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd)
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
        ahc_lock(ahc, &flags);
-       found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
+       found = ahc_reset_channel(ahc, scmd_channel(cmd) + 'A',
                                  /*initiate reset*/TRUE);
        ahc_unlock(ahc, &flags);
 
@@ -1067,10 +1061,11 @@ uint32_t aic7xxx_verbose;
 int
 ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
 {
-       char     buf[80];
-       struct   Scsi_Host *host;
+       char    buf[80];
+       struct  Scsi_Host *host;
        char    *new_name;
-       u_long   s;
+       u_long  s;
+       int     retval;
 
        template->name = ahc->description;
        host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
@@ -1078,8 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
                return (ENOMEM);
 
        *((struct ahc_softc **)host->hostdata) = ahc;
-       ahc_lock(ahc, &s);
-       scsi_assign_lock(host, &ahc->platform_data->spin_lock);
        ahc->platform_data->host = host;
        host->can_queue = AHC_MAX_QUEUE;
        host->cmd_per_lun = 2;
@@ -1090,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
        host->max_lun = AHC_NUM_LUNS;
        host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
        host->sg_tablesize = AHC_NSEG;
+       ahc_lock(ahc, &s);
        ahc_set_unit(ahc, ahc_linux_unit++);
+       ahc_unlock(ahc, &s);
        sprintf(buf, "scsi%d", host->host_no);
        new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
        if (new_name != NULL) {
@@ -1100,13 +1095,19 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
        host->unique_id = ahc->unit;
        ahc_linux_initialize_scsi_bus(ahc);
        ahc_intr_enable(ahc, TRUE);
-       ahc_unlock(ahc, &s);
 
        host->transportt = ahc_linux_transport_template;
 
-       scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+       retval = scsi_add_host(host,
+                       (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
+       if (retval) {
+               printk(KERN_WARNING "aic7xxx: scsi_add_host failed\n");
+               scsi_host_put(host);
+               return retval;
+       }
+
        scsi_scan_host(host);
-       return (0);
+       return 0;
 }
 
 /*
@@ -1119,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
 {
        int i;
        int numtarg;
+       unsigned long s;
 
        i = 0;
        numtarg = 0;
 
+       ahc_lock(ahc, &s);
+
        if (aic7xxx_no_reset != 0)
                ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
 
@@ -1169,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
                ahc_update_neg_request(ahc, &devinfo, tstate,
                                       tinfo, AHC_NEG_ALWAYS);
        }
+       ahc_unlock(ahc, &s);
        /* Give the bus some time to recover */
        if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
                ahc_linux_freeze_simq(ahc);
-               init_timer(&ahc->platform_data->reset_timer);
-               ahc->platform_data->reset_timer.data = (u_long)ahc;
-               ahc->platform_data->reset_timer.expires =
-                   jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
-               ahc->platform_data->reset_timer.function =
-                   ahc_linux_release_simq;
-               add_timer(&ahc->platform_data->reset_timer);
+               msleep(AIC7XXX_RESET_DELAY);
+               ahc_linux_release_simq(ahc);
        }
 }
 
@@ -2058,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg)
 static void
 ahc_linux_freeze_simq(struct ahc_softc *ahc)
 {
+       unsigned long s;
+
+       ahc_lock(ahc, &s);
        ahc->platform_data->qfrozen++;
        if (ahc->platform_data->qfrozen == 1) {
                scsi_block_requests(ahc->platform_data->host);
@@ -2067,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc)
                                        CAM_LUN_WILDCARD, SCB_LIST_NULL,
                                        ROLE_INITIATOR, CAM_REQUEUE_REQ);
        }
+       ahc_unlock(ahc, &s);
 }
 
 static void
-ahc_linux_release_simq(u_long arg)
+ahc_linux_release_simq(struct ahc_softc *ahc)
 {
-       struct ahc_softc *ahc;
        u_long s;
        int    unblock_reqs;
 
-       ahc = (struct ahc_softc *)arg;
-
        unblock_reqs = 0;
        ahc_lock(ahc, &s);
        if (ahc->platform_data->qfrozen > 0)
@@ -2111,15 +2112,14 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
        int    paused;
        int    wait;
        int    disconnected;
+       unsigned long flags;
 
        pending_scb = NULL;
        paused = FALSE;
        wait = FALSE;
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
-       printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
-              ahc_name(ahc), cmd->device->channel,
-              cmd->device->id, cmd->device->lun,
+       scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n",
               flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
 
        printf("CDB:");
@@ -2127,7 +2127,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
                printf(" 0x%x", cmd->cmnd[cdb_byte]);
        printf("\n");
 
-       spin_lock_irq(&ahc->platform_data->spin_lock);
+       ahc_lock(ahc, &flags);
 
        /*
         * First determine if we currently own this command.
@@ -2174,18 +2174,16 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
 
                /* Any SCB for this device will do for a target reset */
                LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
-                       if (ahc_match_scb(ahc, pending_scb, cmd->device->id,
-                                         cmd->device->channel + 'A',
+                       if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
+                                         scmd_channel(cmd) + 'A',
                                          CAM_LUN_WILDCARD,
-                                         SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+                                         SCB_LIST_NULL, ROLE_INITIATOR))
                                break;
                }
        }
 
        if (pending_scb == NULL) {
-               printf("%s:%d:%d:%d: Command not found\n",
-                      ahc_name(ahc), cmd->device->channel, cmd->device->id,
-                      cmd->device->lun);
+               scmd_printk(KERN_INFO, cmd, "Command not found\n");
                goto no_cmd;
        }
 
@@ -2207,9 +2205,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
        paused = TRUE;
 
        if ((pending_scb->flags & SCB_ACTIVE) == 0) {
-               printf("%s:%d:%d:%d: Command already completed\n",
-                      ahc_name(ahc), cmd->device->channel, cmd->device->id,
-                      cmd->device->lun);
+               scmd_printk(KERN_INFO, cmd, "Command already completed\n");
                goto no_cmd;
        }
 
@@ -2266,7 +2262,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
        if (last_phase != P_BUSFREE
         && (pending_scb->hscb->tag == active_scb_index
          || (flag == SCB_DEVICE_RESET
-          && SCSIID_TARGET(ahc, saved_scsiid) == cmd->device->id))) {
+          && SCSIID_TARGET(ahc, saved_scsiid) == scmd_id(cmd)))) {
 
                /*
                 * We're active on the bus, so assert ATN
@@ -2276,9 +2272,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
                pending_scb->flags |= SCB_RECOVERY_SCB|flag;
                ahc_outb(ahc, MSG_OUT, HOST_MSG);
                ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
-               printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
-                      ahc_name(ahc), cmd->device->channel, cmd->device->id,
-                      cmd->device->lun);
+               scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
                wait = TRUE;
        } else if (disconnected) {
 
@@ -2344,9 +2338,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
                printf("Device is disconnected, re-queuing SCB\n");
                wait = TRUE;
        } else {
-               printf("%s:%d:%d:%d: Unable to deliver message\n",
-                      ahc_name(ahc), cmd->device->channel, cmd->device->id,
-                      cmd->device->lun);
+               scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
                retval = FAILED;
                goto done;
        }
@@ -2367,7 +2359,8 @@ done:
                int ret;
 
                ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE;
-               spin_unlock_irq(&ahc->platform_data->spin_lock);
+               ahc_unlock(ahc, &flags);
+
                init_timer(&timer);
                timer.data = (u_long)ahc;
                timer.expires = jiffies + (5 * HZ);
@@ -2381,10 +2374,8 @@ done:
                        printf("Timer Expired\n");
                        retval = FAILED;
                }
-               spin_lock_irq(&ahc->platform_data->spin_lock);
-       }
-
-       spin_unlock_irq(&ahc->platform_data->spin_lock);
+       } else
+               ahc_unlock(ahc, &flags);
        return (retval);
 }