summaryrefslogtreecommitdiffstats
path: root/sys/dev/ips/ips_commands.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-01-28 05:02:13 +0000
committerscottl <scottl@FreeBSD.org>2005-01-28 05:02:13 +0000
commitbad78b265c4a0765532ab7d2ac5493c0a2e39191 (patch)
tree16fadd7614f98d4101435336cd7d5d0a95bbb58d /sys/dev/ips/ips_commands.c
parenta52d6034c25c293be752e89574f77b0c7059ae46 (diff)
downloadFreeBSD-src-bad78b265c4a0765532ab7d2ac5493c0a2e39191.zip
FreeBSD-src-bad78b265c4a0765532ab7d2ac5493c0a2e39191.tar.gz
Lock the IPS driver and bring it out from under Giant. Also do some
significant clean up and optimizations: - don't call bioq_disksort() on every command, the hardware will do that for us. - remove all of the complicated bio deferral code. bio's that can't be serviced immediately can just wait on the bioq. - Only reserve one command object for doing control commands to the card. This simplifies a lot of code and significantly reduces the size of the command struct. - Allocate commands out of a slab instead of embedding them into the softc. - Call the command action method directly instead of having ips_get_free_cmd() call it indirectly. MFC After: 1 week
Diffstat (limited to 'sys/dev/ips/ips_commands.c')
-rw-r--r--sys/dev/ips/ips_commands.c184
1 files changed, 65 insertions, 119 deletions
diff --git a/sys/dev/ips/ips_commands.c b/sys/dev/ips/ips_commands.c
index e2495ab..bbaed71 100644
--- a/sys/dev/ips/ips_commands.c
+++ b/sys/dev/ips/ips_commands.c
@@ -39,12 +39,9 @@ __FBSDID("$FreeBSD$");
*/
static void ips_wakeup_callback(ips_command_t *command)
{
- ips_cmd_status_t *status;
- status = command->arg;
- status->value = command->status.value;
bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_POSTWRITE);
- sema_post(&command->cmd_sema);
+ sema_post(&command->sc->cmd_sema);
}
/* Below are a series of functions for sending an IO request
* to the adapter. The flow order is: start, send, callback, finish.
@@ -62,7 +59,6 @@ static void ips_io_request_finish(ips_command_t *command)
BUS_DMASYNC_POSTWRITE);
}
bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
- bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
if(COMMAND_ERROR(&command->status)){
iobuf->bio_flags |=BIO_ERROR;
iobuf->bio_error = EIO;
@@ -85,7 +81,6 @@ static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,in
if(error){
printf("ips: error = %d in ips_sg_request_callback\n", error);
bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
- bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
iobuf->bio_flags |= BIO_ERROR;
iobuf->bio_error = ENOMEM;
ips_insert_free_cmd(sc, command);
@@ -140,20 +135,10 @@ static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,in
return;
}
-static int ips_send_io_request(ips_command_t *command)
+static int ips_send_io_request(ips_command_t *command, struct bio *iobuf)
{
- ips_softc_t *sc = command->sc;
- struct bio *iobuf = command->arg;
- command->data_dmatag = sc->sg_dmatag;
- if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){
- device_printf(sc->dev, "dmamap failed\n");
- iobuf->bio_flags |= BIO_ERROR;
- iobuf->bio_error = ENOMEM;
- ips_insert_free_cmd(sc, command);
- ipsd_finish(iobuf);
- return 0;
- }
command->callback = ips_io_request_finish;
+ command->arg = iobuf;
PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
bus_dmamap_load(command->data_dmatag, command->data_dmamap,
iobuf->bio_data, iobuf->bio_bcount,
@@ -164,21 +149,17 @@ static int ips_send_io_request(ips_command_t *command)
void ips_start_io_request(ips_softc_t *sc)
{
struct bio *iobuf;
+ ips_command_t *command;
- mtx_lock(&sc->queue_mtx);
iobuf = bioq_first(&sc->queue);
- if(!iobuf) {
- mtx_unlock(&sc->queue_mtx);
+ if(!iobuf)
return;
- }
- if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, IPS_NOWAIT_FLAG)){
- mtx_unlock(&sc->queue_mtx);
+ if (ips_get_free_cmd(sc, &command, 0))
return;
- }
bioq_remove(&sc->queue, iobuf);
- mtx_unlock(&sc->queue_mtx);
+ ips_send_io_request(command, iobuf);
return;
}
@@ -193,8 +174,7 @@ static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,
ips_adapter_info_cmd *command_struct;
sc = command->sc;
if(error){
- ips_cmd_status_t * status = command->arg;
- status->value = IPS_ERROR_STATUS; /* a lovely error value */
+ command->status.value = IPS_ERROR_STATUS; /* a lovely error value */
ips_insert_free_cmd(sc, command);
printf("ips: error = %d in ips_get_adapter_info\n", error);
return;
@@ -217,7 +197,6 @@ static int ips_send_adapter_info_cmd(ips_command_t *command)
{
int error = 0;
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
/* alignemnt */ 1,
@@ -230,8 +209,8 @@ static int ips_send_adapter_info_cmd(ips_command_t *command)
/* numsegs */ 1,
/* maxsegsize*/ IPS_ADAPTER_INFO_LEN,
/* flags */ 0,
- /* lockfunc */ busdma_lock_mutex,
- /* lockarg */ &Giant,
+ /* lockfunc */ NULL,
+ /* lockarg */ NULL,
&command->data_dmatag) != 0) {
printf("ips: can't alloc dma tag for adapter status\n");
error = ENOMEM;
@@ -247,8 +226,8 @@ static int ips_send_adapter_info_cmd(ips_command_t *command)
command->data_buffer,IPS_ADAPTER_INFO_LEN,
ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
- if ((status->value == IPS_ERROR_STATUS) ||
- (sema_timedwait(&command->cmd_sema, 30*hz) != 0))
+ if ((command->status.value == IPS_ERROR_STATUS) ||
+ (sema_timedwait(&sc->cmd_sema, 30*hz) != 0))
error = ETIMEDOUT;
if (error == 0) {
@@ -270,21 +249,17 @@ exit:
int ips_get_adapter_info(ips_softc_t *sc)
{
+ ips_command_t *command;
int error = 0;
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
- if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status,
- IPS_NOWAIT_FLAG) > 0){
+
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){
device_printf(sc->dev, "unable to get adapter configuration\n");
- free(status, M_IPSBUF);
return ENXIO;
}
- if (COMMAND_ERROR(status)){
+ ips_send_adapter_info_cmd(command);
+ if (COMMAND_ERROR(&command->status)){
error = ENXIO;
}
- free(status, M_IPSBUF);
return error;
}
@@ -299,8 +274,7 @@ static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,in
ips_drive_cmd *command_struct;
sc = command->sc;
if(error){
- ips_cmd_status_t * status = command->arg;
- status->value = IPS_ERROR_STATUS;
+ command->status.value = IPS_ERROR_STATUS;
ips_insert_free_cmd(sc, command);
printf("ips: error = %d in ips_get_drive_info\n", error);
return;
@@ -321,7 +295,6 @@ static int ips_send_drive_info_cmd(ips_command_t *command)
{
int error = 0;
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
ips_drive_info_t *driveinfo;
if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
@@ -335,8 +308,8 @@ static int ips_send_drive_info_cmd(ips_command_t *command)
/* numsegs */ 1,
/* maxsegsize*/ IPS_DRIVE_INFO_LEN,
/* flags */ 0,
- /* lockfunc */ busdma_lock_mutex,
- /* lockarg */ &Giant,
+ /* lockfunc */ NULL,
+ /* lockarg */ NULL,
&command->data_dmatag) != 0) {
printf("ips: can't alloc dma tag for drive status\n");
error = ENOMEM;
@@ -351,8 +324,8 @@ static int ips_send_drive_info_cmd(ips_command_t *command)
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) ||
- (sema_timedwait(&command->cmd_sema, 10*hz) != 0))
+ if ((command->status.value == IPS_ERROR_STATUS) ||
+ (sema_timedwait(&sc->cmd_sema, 10*hz) != 0))
error = ETIMEDOUT;
if (error == 0) {
@@ -377,20 +350,16 @@ exit:
int ips_get_drive_info(ips_softc_t *sc)
{
int error = 0;
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
- if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status,
- IPS_NOWAIT_FLAG) > 0){
- free(status, M_IPSBUF);
+ ips_command_t *command;
+
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){
device_printf(sc->dev, "unable to get drive configuration\n");
return ENXIO;
}
- if(COMMAND_ERROR(status)){
+ ips_send_drive_info_cmd(command);
+ if(COMMAND_ERROR(&command->status)){
error = ENXIO;
}
- free(status, M_IPSBUF);
return error;
}
@@ -399,7 +368,6 @@ int ips_get_drive_info(ips_softc_t *sc)
static int ips_send_flush_cache_cmd(ips_command_t *command)
{
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
ips_generic_cmd *command_struct;
PRINTF(10,"ips test: got a command, building flush command\n");
@@ -410,28 +378,24 @@ static int ips_send_flush_cache_cmd(ips_command_t *command)
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
sc->ips_issue_cmd(command);
- if (status->value != IPS_ERROR_STATUS)
- sema_wait(&command->cmd_sema);
+ if (command->status.value != IPS_ERROR_STATUS)
+ sema_wait(&sc->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
int ips_flush_cache(ips_softc_t *sc)
{
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
+ ips_command_t *command;
+
device_printf(sc->dev, "flushing cache\n");
- if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status,
- IPS_NOWAIT_FLAG)){
- free(status, M_IPSBUF);
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){
device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n");
}
- if(COMMAND_ERROR(status)){
+ ips_send_flush_cache_cmd(command);
+ if(COMMAND_ERROR(&command->status)){
device_printf(sc->dev, "ERROR: cache flush command failed!\n");
}
- free(status, M_IPSBUF);
return 0;
}
@@ -481,7 +445,6 @@ void static ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime)
static int ips_send_ffdc_reset_cmd(ips_command_t *command)
{
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
ips_adapter_ffdc_cmd *command_struct;
PRINTF(10,"ips test: got a command, building ffdc reset command\n");
@@ -496,27 +459,23 @@ static int ips_send_ffdc_reset_cmd(ips_command_t *command)
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
sc->ips_issue_cmd(command);
- if (status->value != IPS_ERROR_STATUS)
- sema_wait(&command->cmd_sema);
+ if (command->status.value != IPS_ERROR_STATUS)
+ sema_wait(&sc->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
int ips_ffdc_reset(ips_softc_t *sc)
{
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
- if(ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status,
- IPS_NOWAIT_FLAG)){
- free(status, M_IPSBUF);
+ ips_command_t *command;
+
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){
device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n");
}
- if(COMMAND_ERROR(status)){
+ ips_send_ffdc_reset_cmd(command);
+ if(COMMAND_ERROR(&command->status)){
device_printf(sc->dev, "ERROR: ffdc reset command failed!\n");
}
- free(status, M_IPSBUF);
return 0;
}
@@ -553,8 +512,7 @@ static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,in
ips_rw_nvram_cmd *command_struct;
sc = command->sc;
if(error){
- ips_cmd_status_t * status = command->arg;
- status->value = IPS_ERROR_STATUS;
+ command->status.value = IPS_ERROR_STATUS;
ips_insert_free_cmd(sc, command);
printf("ips: error = %d in ips_read_nvram_callback\n", error);
return;
@@ -573,10 +531,10 @@ static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,in
sc->ips_issue_cmd(command);
}
-static int ips_read_nvram(ips_command_t *command){
+static int ips_read_nvram(ips_command_t *command)
+{
int error = 0;
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
/* alignemnt */ 1,
@@ -589,8 +547,8 @@ static int ips_read_nvram(ips_command_t *command){
/* numsegs */ 1,
/* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
/* flags */ 0,
- /* lockfunc */ busdma_lock_mutex,
- /* lockarg */ &Giant,
+ /* lockfunc */ NULL,
+ /* lockarg */ NULL,
&command->data_dmatag) != 0) {
printf("ips: can't alloc dma tag for nvram\n");
error = ENOMEM;
@@ -605,8 +563,8 @@ static int ips_read_nvram(ips_command_t *command){
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) ||
- (sema_timedwait(&command->cmd_sema, 30*hz) != 0))
+ if ((command->status.value == IPS_ERROR_STATUS) ||
+ (sema_timedwait(&sc->cmd_sema, 30*hz) != 0))
error = ETIMEDOUT;
if (error == 0) {
@@ -625,19 +583,16 @@ exit:
int ips_update_nvram(ips_softc_t *sc)
{
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
- if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){
- free(status, M_IPSBUF);
+ ips_command_t *command;
+
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){
device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n");
return 1;
}
- if(COMMAND_ERROR(status)){
+ ips_read_nvram(command);
+ if(COMMAND_ERROR(&command->status)){
device_printf(sc->dev, "ERROR: nvram update command failed!\n");
}
- free(status, M_IPSBUF);
return 0;
@@ -647,7 +602,6 @@ int ips_update_nvram(ips_softc_t *sc)
static int ips_send_config_sync_cmd(ips_command_t *command)
{
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
ips_generic_cmd *command_struct;
PRINTF(10,"ips test: got a command, building flush command\n");
@@ -659,8 +613,8 @@ static int ips_send_config_sync_cmd(ips_command_t *command)
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
sc->ips_issue_cmd(command);
- if (status->value != IPS_ERROR_STATUS)
- sema_wait(&command->cmd_sema);
+ if (command->status.value != IPS_ERROR_STATUS)
+ sema_wait(&sc->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
@@ -668,7 +622,6 @@ static int ips_send_config_sync_cmd(ips_command_t *command)
static int ips_send_error_table_cmd(ips_command_t *command)
{
ips_softc_t *sc = command->sc;
- ips_cmd_status_t *status = command->arg;
ips_generic_cmd *command_struct;
PRINTF(10,"ips test: got a command, building errortable command\n");
@@ -680,8 +633,8 @@ static int ips_send_error_table_cmd(ips_command_t *command)
bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
BUS_DMASYNC_PREWRITE);
sc->ips_issue_cmd(command);
- if (status->value != IPS_ERROR_STATUS)
- sema_wait(&command->cmd_sema);
+ if (command->status.value != IPS_ERROR_STATUS)
+ sema_wait(&sc->cmd_sema);
ips_insert_free_cmd(sc, command);
return 0;
}
@@ -689,36 +642,29 @@ static int ips_send_error_table_cmd(ips_command_t *command)
int ips_clear_adapter(ips_softc_t *sc)
{
- ips_cmd_status_t *status;
- status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
- if(!status)
- return ENOMEM;
+ ips_command_t *command;
+
device_printf(sc->dev, "syncing config\n");
- if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status,
- IPS_NOWAIT_FLAG)){
- free(status, M_IPSBUF);
+ if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){
device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
return 1;
}
- if(COMMAND_ERROR(status)){
- free(status, M_IPSBUF);
+ ips_send_config_sync_cmd(command);
+ if(COMMAND_ERROR(&command->status)){
device_printf(sc->dev, "ERROR: cache sync command failed!\n");
return 1;
}
device_printf(sc->dev, "clearing error table\n");
- if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status,
- IPS_NOWAIT_FLAG)){
- free(status, M_IPSBUF);
+ if(ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){
device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
return 1;
}
- if(COMMAND_ERROR(status)){
+ ips_send_error_table_cmd(command);
+ if(COMMAND_ERROR(&command->status)){
device_printf(sc->dev, "ERROR: etable command failed!\n");
- free(status, M_IPSBUF);
return 1;
}
- free(status, M_IPSBUF);
return 0;
}
OpenPOWER on IntegriCloud