X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2F3w-9xxx.c;h=9132549813efa874634386b0a562afaca7a30ab1;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=caeb6d246e578eb0732feb99def77729f1980877;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index caeb6d246..913254981 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2,9 +2,8 @@ 3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux. Written By: Adam Radford - Modifications By: Tom Couch - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. + Copyright (C) 2004-2005 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,9 +62,6 @@ 2.26.02.003 - Correctly handle single sgl's with use_sg=1. 2.26.02.004 - Add support for 9550SX controllers. 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher. - 2.26.02.006 - Fix 9550SX pchip reset timeout. - Add big endian support. - 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic(). */ #include @@ -212,7 +208,7 @@ static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id) header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; tw_dev->posted_request_count--; - aen = le16_to_cpu(header->status_block.error); + aen = header->status_block.error; full_command_packet = tw_dev->command_packet_virt[request_id]; command_packet = &full_command_packet->command.oldcommand; @@ -309,7 +305,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) tw_dev->posted_request_count--; header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; - aen = le16_to_cpu(header->status_block.error); + aen = header->status_block.error; queue = 0; count++; @@ -369,7 +365,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H tw_dev->aen_clobber = 1; } - aen = le16_to_cpu(header->status_block.error); + aen = header->status_block.error; memset(event, 0, sizeof(TW_Event)); event->severity = TW_SEV_OUT(header->status_block.severity__reserved); @@ -386,7 +382,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0'; event->parameter_len = strlen(header->err_specific_desc); - memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str)))); + memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len); if (event->severity != TW_AEN_SEVERITY_DEBUG) printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n", host, @@ -466,24 +462,24 @@ static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id) command_packet = &full_command_packet->command.oldcommand; command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM); command_packet->request_id = request_id; - command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); - command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE); + command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id]; + command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; command_packet->size = TW_COMMAND_SIZE; - command_packet->byte6_offset.parameter_count = cpu_to_le16(1); + command_packet->byte6_offset.parameter_count = 1; /* Setup the param */ param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; memset(param, 0, TW_SECTOR_SIZE); - param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */ - param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */ - param->parameter_size_bytes = cpu_to_le16(4); + param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */ + param->parameter_id = 0x3; /* SchedulerTime */ + param->parameter_size_bytes = 4; /* Convert system time in UTC to local time seconds since last Sunday 12:00AM */ do_gettimeofday(&utc); local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60)); schedulertime = local_time - (3 * 86400); - schedulertime = cpu_to_le32(schedulertime % 604800); + schedulertime = schedulertime % 604800; memcpy(param->data, &schedulertime, sizeof(u32)); @@ -935,19 +931,26 @@ out: /* This function will clear the pchip/response queue on 9550SX */ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) { - u32 response_que_value = 0; - unsigned long before; - int retval = 1; + u32 status_reg_value, response_que_value; + int count = 0, retval = 1; if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { - before = jiffies; - while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) { response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); - if (time_after(jiffies, before + HZ * 30)) + if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) { + /* P-chip settle time */ + msleep(500); + retval = 0; goto out; + } + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + count++; } - /* P-chip settle time */ - msleep(500); + if (count == TW_MAX_RESPONSE_DRAIN) + goto out; + retval = 0; } else retval = 0; @@ -969,7 +972,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_ error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]); /* Don't print error for Logical unit not supported during rollcall */ - error = le16_to_cpu(full_command_packet->header.status_block.error); + error = full_command_packet->header.status_block.error; if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) { if (print_host) printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n", @@ -1027,7 +1030,7 @@ static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id) tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; } /* End twa_free_request_id() */ -/* This function will get parameter table entries from the firmware */ +/* This function will get parameter table entires from the firmware */ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes) { TW_Command_Full *full_command_packet; @@ -1044,18 +1047,18 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); command_packet->size = TW_COMMAND_SIZE; command_packet->request_id = request_id; - command_packet->byte6_offset.block_count = cpu_to_le16(1); + command_packet->byte6_offset.block_count = 1; /* Now setup the param */ param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; memset(param, 0, TW_SECTOR_SIZE); - param->table_id = cpu_to_le16(table_id | 0x8000); - param->parameter_id = cpu_to_le16(parameter_id); - param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes); + param->table_id = table_id | 0x8000; + param->parameter_id = parameter_id; + param->parameter_size_bytes = parameter_size_bytes; param_value = tw_dev->generic_buffer_phys[request_id]; - command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value); - command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE); + command_packet->byte8_offset.param.sgl[0].address = param_value; + command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; /* Post the command packet to the board */ twa_post_command_packet(tw_dev, request_id, 1); @@ -1104,20 +1107,18 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand; tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION); tw_initconnect->request_id = request_id; - tw_initconnect->message_credits = cpu_to_le16(message_credits); + tw_initconnect->message_credits = message_credits; tw_initconnect->features = set_features; /* Turn on 64-bit sgl support if we need to */ tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0; - tw_initconnect->features = cpu_to_le32(tw_initconnect->features); - if (set_features & TW_EXTENDED_INIT_CONNECT) { tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED; - tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl); - tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id); - tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch); - tw_initconnect->fw_build = cpu_to_le16(current_fw_build); + tw_initconnect->fw_srl = current_fw_srl; + tw_initconnect->fw_arch_id = current_fw_arch_id; + tw_initconnect->fw_branch = current_fw_branch; + tw_initconnect->fw_build = current_fw_build; } else tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE; @@ -1129,11 +1130,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection"); } else { if (set_features & TW_EXTENDED_INIT_CONNECT) { - *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl); - *fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id); - *fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch); - *fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build); - *init_connect_result = le32_to_cpu(tw_initconnect->result); + *fw_on_ctlr_srl = tw_initconnect->fw_srl; + *fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id; + *fw_on_ctlr_branch = tw_initconnect->fw_branch; + *fw_on_ctlr_build = tw_initconnect->fw_build; + *init_connect_result = tw_initconnect->result; } retval = 0; } @@ -1357,10 +1358,10 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d newcommand = &full_command_packet->command.newcommand; newcommand->request_id__lunl = TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id); - newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); - newcommand->sg_list[0].length = cpu_to_le32(length); + newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; + newcommand->sg_list[0].length = length; newcommand->sgl_entries__lunh = - cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1)); + TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1); } else { oldcommand = &full_command_packet->command.oldcommand; oldcommand->request_id = request_id; @@ -1368,8 +1369,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { /* Load the sg list */ sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); - sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); - sgl->length = cpu_to_le32(length); + sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; + sgl->length = length; if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) oldcommand->size += 1; @@ -1827,10 +1828,10 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (srb) { command_packet->unit = srb->device->id; command_packet->request_id__lunl = - cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id)); + TW_REQ_LUN_IN(srb->device->lun, request_id); } else { command_packet->request_id__lunl = - cpu_to_le16(TW_REQ_LUN_IN(0, request_id)); + TW_REQ_LUN_IN(0, request_id); command_packet->unit = 0; } @@ -1840,8 +1841,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, /* Map sglist from scsi layer to cmd packet */ if (tw_dev->srb[request_id]->use_sg == 0) { if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { - command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); - command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); + command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; + command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); } else { @@ -1849,12 +1850,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (buffaddr == 0) goto out; - command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr); - command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen); + command_packet->sg_list[0].address = buffaddr; + command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen; } - command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1)); + command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1); - if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { + if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); goto out; } @@ -1868,35 +1869,35 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); kunmap_atomic(buf - sg->offset, KM_IRQ0); } - command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); - command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); + command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; + command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; } else { sg_count = twa_map_scsi_sg_data(tw_dev, request_id); if (sg_count == 0) goto out; for (i = 0; i < sg_count; i++) { - command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i])); - command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i])); - if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { + command_packet->sg_list[i].address = sg_dma_address(&sglist[i]); + command_packet->sg_list[i].length = sg_dma_len(&sglist[i]); + if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); goto out; } } } - command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg)); + command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg); } } else { /* Internal cdb post */ for (i = 0; i < use_sg; i++) { - command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address); - command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length); - if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { + command_packet->sg_list[i].address = sglistarg[i].address; + command_packet->sg_list[i].length = sglistarg[i].length; + if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post"); goto out; } } - command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg)); + command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg); } if (srb) { @@ -2118,8 +2119,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH), (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE, TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH), - le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, - TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH))); + *(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, + TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)); /* Now setup the interrupt handler */ retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);