" periodically to prevent tag starvation.\n"
" This may be required by some older disk\n"
" drives or RAID arrays.\n"
+" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for every target\n"
" on every bus\n"
struct scb *);
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(struct ahc_softc *ahc);
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
printf("Setting Global Tags= %d\n", tags);
- for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) {
+ for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) {
for (j = 0; j < AHC_NUM_TARGETS; j++) {
aic7xxx_tag_info[i].tag_commands[j] = tags;
}
{
if ((instance >= 0) && (targ >= 0)
- && (instance < ARRAY_SIZE(aic7xxx_tag_info))
+ && (instance < NUM_ELEMENTS(aic7xxx_tag_info))
&& (targ < AHC_NUM_TARGETS)) {
aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff;
if (bootverbose)
end = strchr(s, '\0');
/*
- * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE
+ * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS
* will never be 0 in this case.
*/
n = 0;
while ((p = strsep(&s, ",.")) != NULL) {
if (*p == '\0')
continue;
- for (i = 0; i < ARRAY_SIZE(options); i++) {
+ for (i = 0; i < NUM_ELEMENTS(options); i++) {
n = strlen(options[i].name);
if (strncmp(options[i].name, p, n) == 0)
break;
}
- if (i == ARRAY_SIZE(options))
+ if (i == NUM_ELEMENTS(options))
continue;
if (strncmp(p, "global_tag_depth", n) == 0) {
memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
ahc->platform_data->irq = AHC_LINUX_NOIRQ;
ahc_lockinit(ahc);
+ init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
if (aic7xxx_pci_parity == 0)
tags = 0;
if ((ahc->user_discenable & devinfo->target_mask) != 0) {
- if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) {
+ if (ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) {
if (warned_user == 0) {
printf(KERN_WARNING
if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
|| ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-
- if (ahc->platform_data->eh_done)
- complete(ahc->platform_data->eh_done);
+ if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
+ ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
+ up(&ahc->platform_data->eh_sem);
+ }
}
ahc_free_scb(ahc, scb);
cmd->scsi_done(cmd);
}
+static void
+ahc_linux_sem_timeout(u_long arg)
+{
+ struct ahc_softc *ahc;
+ u_long s;
+
+ ahc = (struct ahc_softc *)arg;
+
+ ahc_lock(ahc, &s);
+ if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
+ ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
+ up(&ahc->platform_data->eh_sem);
+ }
+ ahc_unlock(ahc, &s);
+}
+
static void
ahc_linux_freeze_simq(struct ahc_softc *ahc)
{
if (paused)
ahc_unpause(ahc);
if (wait) {
- DECLARE_COMPLETION_ONSTACK(done);
+ struct timer_list timer;
+ int ret;
- ahc->platform_data->eh_done = &done;
+ ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE;
ahc_unlock(ahc, &flags);
+ init_timer(&timer);
+ timer.data = (u_long)ahc;
+ timer.expires = jiffies + (5 * HZ);
+ timer.function = ahc_linux_sem_timeout;
+ add_timer(&timer);
printf("Recovery code sleeping\n");
- if (!wait_for_completion_timeout(&done, 5 * HZ)) {
- ahc_lock(ahc, &flags);
- ahc->platform_data->eh_done = NULL;
- ahc_unlock(ahc, &flags);
-
+ down(&ahc->platform_data->eh_sem);
+ printf("Recovery code awake\n");
+ ret = del_timer_sync(&timer);
+ if (ret == 0) {
printf("Timer Expired\n");
retval = FAILED;
}
- printf("Recovery code awake\n");
} else
ahc_unlock(ahc, &flags);
return (retval);
}
#endif
-static void ahc_linux_get_signalling(struct Scsi_Host *shost)
-{
- struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
- unsigned long flags;
- u8 mode;
-
- if (!(ahc->features & AHC_ULTRA2)) {
- /* non-LVD chipset, may not have SBLKCTL reg */
- spi_signalling(shost) =
- ahc->features & AHC_HVD ?
- SPI_SIGNAL_HVD :
- SPI_SIGNAL_SE;
- return;
- }
-
- ahc_lock(ahc, &flags);
- ahc_pause(ahc);
- mode = ahc_inb(ahc, SBLKCTL);
- ahc_unpause(ahc);
- ahc_unlock(ahc, &flags);
-
- if (mode & ENAB40)
- spi_signalling(shost) = SPI_SIGNAL_LVD;
- else if (mode & ENAB20)
- spi_signalling(shost) = SPI_SIGNAL_SE;
- else
- spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
-}
-
static struct spi_function_template ahc_linux_transport_functions = {
.set_offset = ahc_linux_set_offset,
.show_offset = 1,
.set_qas = ahc_linux_set_qas,
.show_qas = 1,
#endif
- .get_signalling = ahc_linux_get_signalling,
};