--- zzzz-none-000/linux-2.6.19.2/drivers/scsi/aic7xxx/aic7xxx_osm.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/drivers/scsi/aic7xxx/aic7xxx_osm.c 2007-01-11 07:38:19.000000000 +0000 @@ -328,7 +328,7 @@ * force all outstanding transactions to be serviced prior to a new * transaction. */ -static uint32_t aic7xxx_periodic_otag; +uint32_t aic7xxx_periodic_otag; /* * Module information and settable options. @@ -512,6 +512,7 @@ struct seeprom_config *sc = ahc->seep_config; unsigned long flags; struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget); + struct ahc_linux_target *targ = scsi_transport_target_data(starget); unsigned short scsirate; struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *tinfo; @@ -532,6 +533,7 @@ BUG_ON(*ahc_targp != NULL); *ahc_targp = starget; + memset(targ, 0, sizeof(*targ)); if (sc) { int maxsync = AHC_SYNCRATE_DT; @@ -592,11 +594,14 @@ struct ahc_softc *ahc = *((struct ahc_softc **)sdev->host->hostdata); struct scsi_target *starget = sdev->sdev_target; + struct ahc_linux_target *targ = scsi_transport_target_data(starget); struct ahc_linux_device *dev; if (bootverbose) printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id); + BUG_ON(targ->sdev[sdev->lun] != NULL); + dev = scsi_transport_device_data(sdev); memset(dev, 0, sizeof(*dev)); @@ -613,6 +618,8 @@ */ dev->maxtags = 0; + targ->sdev[sdev->lun] = sdev; + spi_period(starget) = 0; return 0; @@ -637,6 +644,22 @@ return 0; } +static void +ahc_linux_slave_destroy(struct scsi_device *sdev) +{ + struct ahc_softc *ahc; + struct ahc_linux_device *dev = scsi_transport_device_data(sdev); + struct ahc_linux_target *targ = scsi_transport_target_data(sdev->sdev_target); + + ahc = *((struct ahc_softc **)sdev->host->hostdata); + if (bootverbose) + printf("%s: Slave Destroy %d\n", ahc_name(ahc), sdev->id); + + BUG_ON(dev->active); + + targ->sdev[sdev->lun] = NULL; +} + #if defined(__i386__) /* * Return the disk geometry for the given SCSI device. @@ -754,11 +777,11 @@ #endif .can_queue = AHC_MAX_QUEUE, .this_id = -1, - .max_sectors = 8192, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, .slave_alloc = ahc_linux_slave_alloc, .slave_configure = ahc_linux_slave_configure, + .slave_destroy = ahc_linux_slave_destroy, .target_alloc = ahc_linux_target_alloc, .target_destroy = ahc_linux_target_destroy, }; @@ -1180,13 +1203,21 @@ ahc_platform_free(struct ahc_softc *ahc) { struct scsi_target *starget; - int i; + int i, j; if (ahc->platform_data != NULL) { /* destroy all of the device and target objects */ for (i = 0; i < AHC_NUM_TARGETS; i++) { starget = ahc->platform_data->starget[i]; if (starget != NULL) { + for (j = 0; j < AHC_NUM_LUNS; j++) { + struct ahc_linux_target *targ = + scsi_transport_target_data(starget); + + if (targ->sdev[j] == NULL) + continue; + targ->sdev[j] = NULL; + } ahc->platform_data->starget[i] = NULL; } } @@ -1220,13 +1251,24 @@ } void -ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, - struct ahc_devinfo *devinfo, ahc_queue_alg alg) +ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, + ahc_queue_alg alg) { + struct scsi_target *starget; + struct ahc_linux_target *targ; struct ahc_linux_device *dev; + struct scsi_device *sdev; + u_int target_offset; int was_queuing; int now_queuing; + target_offset = devinfo->target; + if (devinfo->channel != 'A') + target_offset += 8; + starget = ahc->platform_data->starget[target_offset]; + targ = scsi_transport_target_data(starget); + BUG_ON(targ == NULL); + sdev = targ->sdev[devinfo->lun]; if (sdev == NULL) return; dev = scsi_transport_device_data(sdev); @@ -1359,15 +1401,11 @@ tags = ahc_linux_user_tagdepth(ahc, &devinfo); if (tags != 0 && sdev->tagged_supported != 0) { - ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_TAGGED); - ahc_send_async(ahc, devinfo.channel, devinfo.target, - devinfo.lun, AC_TRANSFER_NEG); + ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED); ahc_print_devinfo(ahc, &devinfo); printf("Tagged Queuing enabled. Depth %d\n", tags); } else { - ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_NONE); - ahc_send_async(ahc, devinfo.channel, devinfo.target, - devinfo.lun, AC_TRANSFER_NEG); + ahc_set_tags(ahc, &devinfo, AHC_QUEUE_NONE); } } @@ -1591,7 +1629,7 @@ void ahc_send_async(struct ahc_softc *ahc, char channel, - u_int target, u_int lun, ac_code code) + u_int target, u_int lun, ac_code code, void *arg) { switch (code) { case AC_TRANSFER_NEG: @@ -1837,9 +1875,9 @@ if (scb->flags & SCB_SENSE) { u_int sense_size; - sense_size = min(sizeof(struct scsi_sense_data) + sense_size = MIN(sizeof(struct scsi_sense_data) - ahc_get_sense_residual(scb), - (u_long)sizeof(cmd->sense_buffer)); + sizeof(cmd->sense_buffer)); memcpy(cmd->sense_buffer, ahc_get_sense_buf(ahc, scb), sense_size); if (sense_size < sizeof(cmd->sense_buffer)) @@ -1908,7 +1946,7 @@ } ahc_set_transaction_status(scb, CAM_REQUEUE_REQ); ahc_set_scsi_status(scb, SCSI_STATUS_OK); - ahc_platform_set_tags(ahc, sdev, &devinfo, + ahc_platform_set_tags(ahc, &devinfo, (dev->flags & AHC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; @@ -1919,7 +1957,7 @@ */ dev->openings = 1; ahc_set_scsi_status(scb, SCSI_STATUS_BUSY); - ahc_platform_set_tags(ahc, sdev, &devinfo, + ahc_platform_set_tags(ahc, &devinfo, (dev->flags & AHC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; @@ -2561,6 +2599,8 @@ if (!ahc_linux_transport_template) return -ENODEV; + scsi_transport_reserve_target(ahc_linux_transport_template, + sizeof(struct ahc_linux_target)); scsi_transport_reserve_device(ahc_linux_transport_template, sizeof(struct ahc_linux_device));