Commit 200a0a27 authored by Justin T. Gibbs's avatar Justin T. Gibbs

Aic7xxx Driver Update (version 6.2.32)

 o Perform an audit on use of del_timer() and switch to del_timer_sync()
   where appropriate.
 o Remove the reboot notifier hook which is unused in 2.5.X.
 o Correct some driver unload bugs.
parent 1558c0fe
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#29 $ * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#30 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -314,7 +314,7 @@ aha2840_load_seeprom(struct ahc_softc *ahc) ...@@ -314,7 +314,7 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
if (bootverbose) if (bootverbose)
printf("%s: Reading SEEPROM...", ahc_name(ahc)); printf("%s: Reading SEEPROM...", ahc_name(ahc));
have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
/*start_addr*/0, sizeof(sc)/2); /*start_addr*/0, sizeof(*sc)/2);
if (have_seeprom) { if (have_seeprom) {
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#124 $ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#128 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
...@@ -3949,7 +3949,6 @@ ahc_free(struct ahc_softc *ahc) ...@@ -3949,7 +3949,6 @@ ahc_free(struct ahc_softc *ahc)
{ {
int i; int i;
ahc_fini_scbdata(ahc);
switch (ahc->init_level) { switch (ahc->init_level) {
default: default:
case 5: case 5:
...@@ -3981,6 +3980,7 @@ ahc_free(struct ahc_softc *ahc) ...@@ -3981,6 +3980,7 @@ ahc_free(struct ahc_softc *ahc)
ahc_dma_tag_destroy(ahc, ahc->parent_dmat); ahc_dma_tag_destroy(ahc, ahc->parent_dmat);
#endif #endif
ahc_platform_free(ahc); ahc_platform_free(ahc);
ahc_fini_scbdata(ahc);
for (i = 0; i < AHC_NUM_TARGETS; i++) { for (i = 0; i < AHC_NUM_TARGETS; i++) {
struct ahc_tmode_tstate *tstate; struct ahc_tmode_tstate *tstate;
...@@ -5100,7 +5100,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) ...@@ -5100,7 +5100,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
} while (--maxloops } while (--maxloops
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0 && ((intstat & INT_PEND) != 0
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)))); || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0));
if (maxloops == 0) { if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x", printf("Infinite interrupt loop, INTSTAT = %x",
ahc_inb(ahc, INTSTAT)); ahc_inb(ahc, INTSTAT));
......
/* /*
* Adaptec AIC7xxx device driver for Linux. * Adaptec AIC7xxx device driver for Linux.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#206 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#210 $
* *
* Copyright (c) 1994 John Aycock * Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science. * The University of Calgary Department of Computer Science.
...@@ -1082,7 +1082,8 @@ ahc_linux_slave_destroy(Scsi_Device *device) ...@@ -1082,7 +1082,8 @@ ahc_linux_slave_destroy(Scsi_Device *device)
&& (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
dev->flags |= AHC_DEV_UNCONFIGURED; dev->flags |= AHC_DEV_UNCONFIGURED;
if (TAILQ_EMPTY(&dev->busyq) if (TAILQ_EMPTY(&dev->busyq)
&& dev->active == 0) && dev->active == 0
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
ahc_linux_free_device(ahc, dev); ahc_linux_free_device(ahc, dev);
} }
ahc_midlayer_entrypoint_unlock(ahc, &flags); ahc_midlayer_entrypoint_unlock(ahc, &flags);
...@@ -1346,35 +1347,6 @@ ahc_runq_tasklet(unsigned long data) ...@@ -1346,35 +1347,6 @@ ahc_runq_tasklet(unsigned long data)
#endif #endif
} }
/************************ Shutdown/halt/reboot hook ***************************/
#include <linux/notifier.h>
#include <linux/reboot.h>
static struct notifier_block ahc_linux_notifier = {
ahc_linux_halt, NULL, 0
};
static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
struct ahc_softc *ahc;
/*
* In 2.5.X, this is called prior to the filesystems
* being synced and the SCSI layer being properly
* shutdown. A different API is required there,
* but the device hooks for this don't quite look
* right.
*/
if (event == SYS_DOWN || event == SYS_HALT) {
TAILQ_FOREACH(ahc, &ahc_tailq, links) {
ahc_shutdown(ahc);
}
}
#endif
return (NOTIFY_OK);
}
/******************************** Macros **************************************/ /******************************** Macros **************************************/
#define BUILD_SCSIID(ahc, cmd) \ #define BUILD_SCSIID(ahc, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) \ ((((cmd)->device->id << TID_SHIFT) & TID) \
...@@ -1613,7 +1585,7 @@ ahc_linux_setup_tag_info_global(char *p) ...@@ -1613,7 +1585,7 @@ ahc_linux_setup_tag_info_global(char *p)
} }
static void static void
ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value) ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
{ {
if ((instance >= 0) && (targ >= 0) if ((instance >= 0) && (targ >= 0)
...@@ -1626,7 +1598,7 @@ ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value) ...@@ -1626,7 +1598,7 @@ ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value)
} }
static void static void
ahc_linux_setup_dv(void *arg, int instance, int targ, int32_t value) ahc_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
{ {
if ((instance >= 0) if ((instance >= 0)
...@@ -1694,10 +1666,10 @@ aic7xxx_setup(char *s) ...@@ -1694,10 +1666,10 @@ aic7xxx_setup(char *s)
ahc_linux_setup_tag_info_global(p + n); ahc_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) { } else if (strncmp(p, "tag_info", n) == 0) {
s = aic_parse_brace_option("tag_info", p + n, end, s = aic_parse_brace_option("tag_info", p + n, end,
2, ahc_linux_setup_tag_info, NULL); 2, ahc_linux_setup_tag_info, 0);
} else if (strncmp(p, "dv", n) == 0) { } else if (strncmp(p, "dv", n) == 0) {
s = aic_parse_brace_option("dv", p + n, end, 1, s = aic_parse_brace_option("dv", p + n, end, 1,
ahc_linux_setup_dv, NULL); ahc_linux_setup_dv, 0);
} else if (p[n] == ':') { } else if (p[n] == ':') {
*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
} else if (strncmp(p, "verbose", n) == 0) { } else if (strncmp(p, "verbose", n) == 0) {
...@@ -1953,8 +1925,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) ...@@ -1953,8 +1925,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
if (aic7xxx_pci_parity == 0) if (aic7xxx_pci_parity == 0)
ahc->flags |= AHC_DISABLE_PCI_PERR; ahc->flags |= AHC_DISABLE_PCI_PERR;
if (TAILQ_EMPTY(&ahc_tailq))
register_reboot_notifier(&ahc_linux_notifier);
return (0); return (0);
} }
...@@ -1966,6 +1936,7 @@ ahc_platform_free(struct ahc_softc *ahc) ...@@ -1966,6 +1936,7 @@ ahc_platform_free(struct ahc_softc *ahc)
int i, j; int i, j;
if (ahc->platform_data != NULL) { if (ahc->platform_data != NULL) {
del_timer_sync(&ahc->platform_data->completeq_timer);
ahc_linux_kill_dv_thread(ahc); ahc_linux_kill_dv_thread(ahc);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_kill(&ahc->platform_data->runq_tasklet); tasklet_kill(&ahc->platform_data->runq_tasklet);
...@@ -1981,15 +1952,20 @@ ahc_platform_free(struct ahc_softc *ahc) ...@@ -1981,15 +1952,20 @@ ahc_platform_free(struct ahc_softc *ahc)
for (i = 0; i < AHC_NUM_TARGETS; i++) { for (i = 0; i < AHC_NUM_TARGETS; i++) {
targ = ahc->platform_data->targets[i]; targ = ahc->platform_data->targets[i];
if (targ != NULL) { if (targ != NULL) {
/* Keep target around through the loop. */
targ->refcount++;
for (j = 0; j < AHC_NUM_LUNS; j++) { for (j = 0; j < AHC_NUM_LUNS; j++) {
if (targ->devices[j] != NULL) {
if (targ->devices[j] == NULL)
continue;
dev = targ->devices[j]; dev = targ->devices[j];
ahc_linux_free_device(ahc, dev); ahc_linux_free_device(ahc, dev);
} }
if (ahc->platform_data->targets[i] == /*
NULL) * Forcibly free the target now that
break; * all devices are gone.
} */
ahc_linux_free_target(ahc, targ);
} }
} }
...@@ -2575,10 +2551,14 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset) ...@@ -2575,10 +2551,14 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
} }
ahc_lock(ahc, &s); ahc_lock(ahc, &s);
if (targ->dv_buffer != NULL) if (targ->dv_buffer != NULL) {
free(targ->dv_buffer, M_DEVBUF); free(targ->dv_buffer, M_DEVBUF);
if (targ->dv_buffer1 != NULL) targ->dv_buffer = NULL;
}
if (targ->dv_buffer1 != NULL) {
free(targ->dv_buffer1, M_DEVBUF); free(targ->dv_buffer1, M_DEVBUF);
targ->dv_buffer1 = NULL;
}
targ->flags &= ~AHC_DV_REQUIRED; targ->flags &= ~AHC_DV_REQUIRED;
if (targ->refcount == 0) if (targ->refcount == 0)
ahc_linux_free_target(ahc, targ); ahc_linux_free_target(ahc, targ);
...@@ -3998,7 +3978,7 @@ ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) ...@@ -3998,7 +3978,7 @@ ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
{ {
struct ahc_linux_target *targ; struct ahc_linux_target *targ;
del_timer(&dev->timer); del_timer_sync(&dev->timer);
targ = dev->target; targ = dev->target;
targ->devices[dev->lun] = NULL; targ->devices[dev->lun] = NULL;
free(dev, M_DEVBUF); free(dev, M_DEVBUF);
...@@ -4227,7 +4207,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) ...@@ -4227,7 +4207,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (TAILQ_EMPTY(&dev->busyq)) { if (TAILQ_EMPTY(&dev->busyq)) {
if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
&& dev->active == 0) && dev->active == 0
&& (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
ahc_linux_free_device(ahc, dev); ahc_linux_free_device(ahc, dev);
} else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
...@@ -4707,6 +4688,9 @@ ahc_linux_dev_timed_unfreeze(u_long arg) ...@@ -4707,6 +4688,9 @@ ahc_linux_dev_timed_unfreeze(u_long arg)
if (dev->qfrozen == 0 if (dev->qfrozen == 0
&& (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
ahc_linux_run_device_queue(ahc, dev); ahc_linux_run_device_queue(ahc, dev);
if (TAILQ_EMPTY(&dev->busyq)
&& dev->active == 0)
ahc_linux_free_device(ahc, dev);
ahc_unlock(ahc, &s); ahc_unlock(ahc, &s);
} }
...@@ -5024,7 +5008,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) ...@@ -5024,7 +5008,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
printf("Recovery code sleeping\n"); printf("Recovery code sleeping\n");
down(&ahc->platform_data->eh_sem); down(&ahc->platform_data->eh_sem);
printf("Recovery code awake\n"); printf("Recovery code awake\n");
ret = del_timer(&timer); ret = del_timer_sync(&timer);
if (ret == 0) { if (ret == 0) {
printf("Timer Expired\n"); printf("Timer Expired\n");
retval = FAILED; retval = FAILED;
...@@ -5138,8 +5122,6 @@ ahc_linux_exit(void) ...@@ -5138,8 +5122,6 @@ ahc_linux_exit(void)
*/ */
ahc_linux_pci_exit(); ahc_linux_pci_exit();
#endif #endif
unregister_reboot_notifier(&ahc_linux_notifier);
} }
module_init(ahc_linux_init); module_init(ahc_linux_init);
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#131 $ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#133 $
* *
*/ */
#ifndef _AIC7XXX_LINUX_H_ #ifndef _AIC7XXX_LINUX_H_
...@@ -267,7 +267,7 @@ typedef struct timer_list ahc_timer_t; ...@@ -267,7 +267,7 @@ typedef struct timer_list ahc_timer_t;
/***************************** Timer Facilities *******************************/ /***************************** Timer Facilities *******************************/
#define ahc_timer_init init_timer #define ahc_timer_init init_timer
#define ahc_timer_stop del_timer #define ahc_timer_stop del_timer_sync
typedef void ahc_linux_callback_t (u_long); typedef void ahc_linux_callback_t (u_long);
static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
ahc_callback_t *func, void *arg); ahc_callback_t *func, void *arg);
...@@ -305,7 +305,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec) ...@@ -305,7 +305,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
#define AHC_SCSI_HAS_HOST_LOCK 0 #define AHC_SCSI_HAS_HOST_LOCK 0
#endif #endif
#define AIC7XXX_DRIVER_VERSION "6.2.31" #define AIC7XXX_DRIVER_VERSION "6.2.32"
/**************************** Front End Queues ********************************/ /**************************** Front End Queues ********************************/
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment