summaryrefslogtreecommitdiffstats
path: root/sys/dev/ips
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2004-02-28 19:14:41 +0000
committerscottl <scottl@FreeBSD.org>2004-02-28 19:14:41 +0000
commit8337abed61d36809d4e921ce64a0699fc8e1f990 (patch)
tree9838032cf77c78cc90c2abba229573c0ab89c327 /sys/dev/ips
parent77d85757b823f55de35091e53a0706351d358805 (diff)
downloadFreeBSD-src-8337abed61d36809d4e921ce64a0699fc8e1f990.zip
FreeBSD-src-8337abed61d36809d4e921ce64a0699fc8e1f990.tar.gz
Switch from using mutexes to using semaphores to protect against early
completion of synchronous commands. Also switch to a per-array bioq as it appears to improve performance. Submitted by: mbr, imp.ch (bioq change)
Diffstat (limited to 'sys/dev/ips')
-rw-r--r--sys/dev/ips/ips.c42
-rw-r--r--sys/dev/ips/ips.h8
-rw-r--r--sys/dev/ips/ips_commands.c53
-rw-r--r--sys/dev/ips/ips_disk.c10
-rw-r--r--sys/dev/ips/ips_pci.c4
5 files changed, 65 insertions, 52 deletions
diff --git a/sys/dev/ips/ips.c b/sys/dev/ips/ips.c
index d735f83..20f5c31 100644
--- a/sys/dev/ips/ips.c
+++ b/sys/dev/ips/ips.c
@@ -102,16 +102,23 @@ static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum
static __inline__ int ips_cmdqueue_free(ips_softc_t *sc)
{
int i, error = -1;
- intrmask_t mask = splbio();
+ ips_command_t *command;
+ intrmask_t mask;
+
+ mask = splbio();
if(!sc->used_commands){
for(i = 0; i < sc->max_cmds; i++){
- if(!(sc->commandarray[i].command_phys_addr))
+
+ command = &sc->commandarray[i];
+ sema_destroy(&command->cmd_sema);
+
+ if(command->command_phys_addr == 0)
continue;
bus_dmamap_unload(sc->command_dmatag,
- sc->commandarray[i].command_dmamap);
+ command->command_dmamap);
bus_dmamem_free(sc->command_dmatag,
- sc->commandarray[i].command_buffer,
- sc->commandarray[i].command_dmamap);
+ command->command_buffer,
+ command->command_dmamap);
}
error = 0;
sc->state |= IPS_OFFLINE;
@@ -129,13 +136,10 @@ static __inline__ int ips_cmdqueue_init(ips_softc_t *sc)
SLIST_INIT(&sc->free_cmd_list);
STAILQ_INIT(&sc->cmd_wait_list);
for(i = 0; i < sc->max_cmds; i++){
- sc->commandarray[i].id = i;
- sc->commandarray[i].sc = sc;
- SLIST_INSERT_HEAD(&sc->free_cmd_list, &sc->commandarray[i],
- next);
- }
- for(i = 0; i < sc->max_cmds; i++){
command = &sc->commandarray[i];
+ command->id = i;
+ command->sc = sc;
+
if(bus_dmamem_alloc(sc->command_dmatag,&command->command_buffer,
BUS_DMA_NOWAIT, &command->command_dmamap))
goto error;
@@ -147,12 +151,15 @@ static __inline__ int ips_cmdqueue_init(ips_softc_t *sc)
command->command_buffer, command->command_dmamap);
goto error;
}
+
+ sema_init(&command->cmd_sema, 0, "IPS Command Semaphore");
+ SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
}
sc->state &= ~IPS_OFFLINE;
return 0;
error:
- ips_cmdqueue_free(sc);
- return ENOMEM;
+ ips_cmdqueue_free(sc);
+ return ENOMEM;
}
static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
@@ -254,6 +261,10 @@ void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
{
intrmask_t mask;
mask = splbio();
+
+ if (sema_value(&command->cmd_sema) != 0)
+ panic("ips: command returned non-zero semaphore");
+
SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
(sc->used_commands)--;
splx(mask);
@@ -375,6 +386,7 @@ int ips_adapter_init(ips_softc_t *sc)
{
int i;
DEVICE_PRINTF(1,sc->dev, "initializing\n");
+
if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
/* alignemnt */ 1,
/* boundary */ 0,
@@ -420,8 +432,6 @@ int ips_adapter_init(ips_softc_t *sc)
if(sc->ips_adapter_reinit(sc, 0))
goto error;
- mtx_init(&sc->cmd_mtx, "ips command mutex", NULL, MTX_DEF);
-
/* initialize ffdc values */
microtime(&sc->ffdc_resettime);
sc->ffdc_resetcount = 1;
@@ -534,8 +544,6 @@ int ips_adapter_free(ips_softc_t *sc)
mask = splbio();
untimeout(ips_timeout, sc, sc->timer);
splx(mask);
- if (mtx_initialized(&sc->cmd_mtx))
- mtx_destroy(&sc->cmd_mtx);
if(sc->sg_dmatag)
bus_dma_tag_destroy(sc->sg_dmatag);
diff --git a/sys/dev/ips/ips.h b/sys/dev/ips/ips.h
index f644df6..cd3b015 100644
--- a/sys/dev/ips/ips.h
+++ b/sys/dev/ips/ips.h
@@ -39,6 +39,7 @@
#include <sys/bio.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/sema.h>
#include <sys/time.h>
#include <machine/bus_memio.h>
@@ -376,6 +377,7 @@ typedef struct ips_command{
bus_dmamap_t command_dmamap;
void * command_buffer;
u_int32_t command_phys_addr;/*WARNING! must be changed if 64bit addressing ever used*/
+ struct sema cmd_sema;
ips_cmd_status_t status;
SLIST_ENTRY(ips_command) next;
bus_dma_tag_t data_dmatag;
@@ -427,7 +429,9 @@ typedef struct ips_softc{
void (* ips_adapter_intr)(void *sc);
void (* ips_issue_cmd)(ips_command_t *command);
ips_copper_queue_t * copper_queue;
- struct mtx cmd_mtx;
+ struct mtx queue_mtx;
+ struct bio_queue_head queue;
+
}ips_softc_t;
/* function defines from ips_ioctl.c */
@@ -438,7 +442,7 @@ extern void ipsd_finish(struct bio *iobuf);
/* function defines from ips_commands.c */
extern int ips_flush_cache(ips_softc_t *sc);
-extern void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf);
+extern void ips_start_io_request(ips_softc_t *sc);
extern int ips_get_drive_info(ips_softc_t *sc);
extern int ips_get_adapter_info(ips_softc_t *sc);
extern int ips_ffdc_reset(ips_softc_t *sc);
diff --git a/sys/dev/ips/ips_commands.c b/sys/dev/ips/ips_commands.c
index 8d3b367..b139287 100644
--- a/sys/dev/ips/ips_commands.c
+++ b/sys/dev/ips/ips_commands.c
@@ -44,9 +44,7 @@ static void ips_wakeup_callback(ips_command_t *command)
status->value = command->status.value;
bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_POSTWRITE);
- mtx_lock(&command->sc->cmd_mtx);
- wakeup(status);
- mtx_unlock(&command->sc->cmd_mtx);
+ sema_post(&command->cmd_sema);
}
/* Below are a series of functions for sending an IO request
* to the adapter. The flow order is: start, send, callback, finish.
@@ -163,15 +161,24 @@ static int ips_send_io_request(ips_command_t *command)
return 0;
}
-void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf)
+void ips_start_io_request(ips_softc_t *sc)
{
- if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)){
- device_printf(sc->dev, "no mem for command slots!\n");
- iobuf->bio_flags |= BIO_ERROR;
- iobuf->bio_error = ENOMEM;
- ipsd_finish(iobuf);
+ struct bio *iobuf;
+
+ mtx_lock(&sc->queue_mtx);
+ iobuf = bioq_first(&sc->queue);
+ if(!iobuf) {
+ mtx_unlock(&sc->queue_mtx);
+ return;
+ }
+
+ if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, IPS_NOWAIT_FLAG)){
+ mtx_unlock(&sc->queue_mtx);
return;
}
+
+ bioq_remove(&sc->queue, iobuf);
+ mtx_unlock(&sc->queue_mtx);
return;
}
@@ -236,15 +243,13 @@ static int ips_send_adapter_info_cmd(ips_command_t *command)
goto exit;
}
command->callback = ips_wakeup_callback;
- mtx_lock(&sc->cmd_mtx);
bus_dmamap_load(command->data_dmatag, command->data_dmamap,
command->data_buffer,IPS_ADAPTER_INFO_LEN,
ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
if ((status->value == IPS_ERROR_STATUS) ||
- (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK))
+ (sema_timedwait(&command->cmd_sema, 30*hz) == 0))
error = ETIMEDOUT;
- mtx_unlock(&sc->cmd_mtx);
if (error == 0) {
bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
@@ -343,14 +348,12 @@ static int ips_send_drive_info_cmd(ips_command_t *command)
goto exit;
}
command->callback = ips_wakeup_callback;
- mtx_lock(&sc->cmd_mtx);
bus_dmamap_load(command->data_dmatag, command->data_dmamap,
command->data_buffer,IPS_DRIVE_INFO_LEN,
ips_drive_info_callback, command, BUS_DMA_NOWAIT);
if ((status->value == IPS_ERROR_STATUS) ||
- (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK))
+ (sema_timedwait(&command->cmd_sema, 10*hz) == 0))
error = ETIMEDOUT;
- mtx_unlock(&sc->cmd_mtx);
if (error == 0) {
bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
@@ -406,11 +409,9 @@ static int ips_send_flush_cache_cmd(ips_command_t *command)
command_struct->id = command->id;
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
- mtx_lock(&sc->cmd_mtx);
sc->ips_issue_cmd(command);
if (status->value != IPS_ERROR_STATUS)
- msleep(status, &sc->cmd_mtx, 0, "flush2", 0);
- mtx_unlock(&sc->cmd_mtx);
+ sema_wait(&command->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
@@ -494,11 +495,9 @@ static int ips_send_ffdc_reset_cmd(ips_command_t *command)
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
- mtx_lock(&sc->cmd_mtx);
sc->ips_issue_cmd(command);
if (status->value != IPS_ERROR_STATUS)
- msleep(status, &sc->cmd_mtx, 0, "ffdc", 0);
- mtx_unlock(&sc->cmd_mtx);
+ sema_wait(&command->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
@@ -603,14 +602,12 @@ static int ips_read_nvram(ips_command_t *command){
goto exit;
}
command->callback = ips_write_nvram;
- mtx_lock(&sc->cmd_mtx);
bus_dmamap_load(command->data_dmatag, command->data_dmamap,
command->data_buffer,IPS_NVRAM_PAGE_SIZE,
ips_read_nvram_callback, command, BUS_DMA_NOWAIT);
if ((status->value == IPS_ERROR_STATUS) ||
- (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK))
+ (sema_timedwait(&command->cmd_sema, 30*hz) == 0))
error = ETIMEDOUT;
- mtx_unlock(&sc->cmd_mtx);
if (error == 0) {
bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
@@ -661,11 +658,9 @@ static int ips_send_config_sync_cmd(ips_command_t *command)
command_struct->reserve2 = IPS_POCL;
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
- mtx_lock(&sc->cmd_mtx);
sc->ips_issue_cmd(command);
if (status->value != IPS_ERROR_STATUS)
- msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0);
- mtx_unlock(&sc->cmd_mtx);
+ sema_wait(&command->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
@@ -684,11 +679,9 @@ static int ips_send_error_table_cmd(ips_command_t *command)
command_struct->reserve2 = IPS_CSL;
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
- mtx_lock(&sc->cmd_mtx);
sc->ips_issue_cmd(command);
if (status->value != IPS_ERROR_STATUS)
- msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0);
- mtx_unlock(&sc->cmd_mtx);
+ sema_wait(&command->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
diff --git a/sys/dev/ips/ips_disk.c b/sys/dev/ips/ips_disk.c
index f20a8f8..87b848e 100644
--- a/sys/dev/ips/ips_disk.c
+++ b/sys/dev/ips/ips_disk.c
@@ -79,6 +79,9 @@ static int ipsd_close(struct disk *dp)
/* ipsd_finish is called to clean up and return a completed IO request */
void ipsd_finish(struct bio *iobuf)
{
+ ipsdisk_softc_t *dsc;
+ dsc = iobuf->bio_disk->d_drv1;
+
if (iobuf->bio_flags & BIO_ERROR) {
ipsdisk_softc_t *dsc;
dsc = iobuf->bio_disk->d_drv1;
@@ -87,6 +90,7 @@ void ipsd_finish(struct bio *iobuf)
iobuf->bio_resid = 0;
biodone(iobuf);
+ ips_start_io_request(dsc->sc);
}
@@ -97,7 +101,10 @@ static void ipsd_strategy(struct bio *iobuf)
dsc = iobuf->bio_disk->d_drv1;
DEVICE_PRINTF(8,dsc->dev,"in strategy\n");
iobuf->bio_driver1 = (void *)(uintptr_t)dsc->sc->drives[dsc->disk_number].drivenum;
- ips_start_io_request(dsc->sc, iobuf);
+ mtx_lock(&dsc->sc->queue_mtx);
+ bioq_disksort(&dsc->sc->queue, iobuf);
+ mtx_unlock(&dsc->sc->queue_mtx);
+ ips_start_io_request(dsc->sc);
}
static int ipsd_probe(device_t dev)
@@ -161,4 +168,3 @@ static int ipsd_detach(device_t dev)
disk_destroy(dsc->ipsd_disk);
return 0;
}
-
diff --git a/sys/dev/ips/ips_pci.c b/sys/dev/ips/ips_pci.c
index 1981e28..c4a2db3 100644
--- a/sys/dev/ips/ips_pci.c
+++ b/sys/dev/ips/ips_pci.c
@@ -135,6 +135,8 @@ static int ips_pci_attach(device_t dev)
}
sc->ips_ich.ich_func = ips_intrhook;
sc->ips_ich.ich_arg = sc;
+ mtx_init(&sc->queue_mtx, "IPS bioqueue lock", MTX_DEF, 0);
+ bioq_init(&sc->queue);
if (config_intrhook_establish(&sc->ips_ich) != 0) {
printf("IPS can't establish configuration hook\n");
goto error;
@@ -182,7 +184,7 @@ static int ips_pci_detach(device_t dev)
if(ips_adapter_free(sc))
return EBUSY;
ips_pci_free(sc);
- mtx_destroy(&sc->cmd_mtx);
+ bioq_flush(&sc->queue, NULL, ENXIO);
}
return 0;
}
OpenPOWER on IntegriCloud