diff options
Diffstat (limited to 'drivers/scsi/3w-sas.c')
| -rw-r--r-- | drivers/scsi/3w-sas.c | 322 |
1 files changed, 125 insertions, 197 deletions
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index c845bdbeb6c0..e319be7d369c 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1,7 +1,7 @@ /* 3w-sas.c -- LSI 3ware SAS/SATA-RAID Controller device driver for Linux. - Written By: Adam Radford <linuxraid@lsi.com> + Written By: Adam Radford <aradford@gmail.com> Copyright (C) 2009 LSI Corporation. @@ -43,10 +43,7 @@ LSI 3ware 9750 6Gb/s SAS/SATA-RAID Bugs/Comments/Suggestions should be mailed to: - linuxraid@lsi.com - - For more information, goto: - http://www.lsi.com + aradford@gmail.com History ------- @@ -67,7 +64,7 @@ #include <linux/slab.h> #include <asm/io.h> #include <asm/irq.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> @@ -99,7 +96,7 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res /* This function returns AENs through sysfs */ static ssize_t twl_sysfs_aen_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *outbuf, loff_t offset, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); @@ -119,18 +116,18 @@ static ssize_t twl_sysfs_aen_read(struct file *filp, struct kobject *kobj, } /* End twl_sysfs_aen_read() */ /* aen_read sysfs attribute initializer */ -static struct bin_attribute twl_sysfs_aen_read_attr = { +static const struct bin_attribute twl_sysfs_aen_read_attr = { .attr = { .name = "3ware_aen_read", .mode = S_IRUSR, - }, + }, .size = 0, .read = twl_sysfs_aen_read }; /* This function returns driver compatibility info through sysfs */ static ssize_t twl_sysfs_compat_info(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *outbuf, loff_t offset, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); @@ -150,11 +147,11 @@ static ssize_t twl_sysfs_compat_info(struct file *filp, struct kobject *kobj, } /* End twl_sysfs_compat_info() */ /* compat_info sysfs attribute initializer */ -static struct bin_attribute twl_sysfs_compat_info_attr = { +static const struct bin_attribute twl_sysfs_compat_info_attr = { .attr = { .name = "3ware_compat_info", .mode = S_IRUSR, - }, + }, .size = 0, .read = twl_sysfs_compat_info }; @@ -169,56 +166,45 @@ static ssize_t twl_show_stats(struct device *dev, ssize_t len; spin_lock_irqsave(tw_dev->host->host_lock, flags); - len = snprintf(buf, PAGE_SIZE, "3w-sas Driver version: %s\n" - "Current commands posted: %4d\n" - "Max commands posted: %4d\n" - "Last sgl length: %4d\n" - "Max sgl length: %4d\n" - "Last sector count: %4d\n" - "Max sector count: %4d\n" - "SCSI Host Resets: %4d\n" - "AEN's: %4d\n", - TW_DRIVER_VERSION, - tw_dev->posted_request_count, - tw_dev->max_posted_request_count, - tw_dev->sgl_entries, - tw_dev->max_sgl_entries, - tw_dev->sector_count, - tw_dev->max_sector_count, - tw_dev->num_resets, - tw_dev->aen_count); + len = sysfs_emit(buf, "3w-sas Driver version: %s\n" + "Current commands posted: %4d\n" + "Max commands posted: %4d\n" + "Last sgl length: %4d\n" + "Max sgl length: %4d\n" + "Last sector count: %4d\n" + "Max sector count: %4d\n" + "SCSI Host Resets: %4d\n" + "AEN's: %4d\n", + TW_DRIVER_VERSION, + tw_dev->posted_request_count, + tw_dev->max_posted_request_count, + tw_dev->sgl_entries, + tw_dev->max_sgl_entries, + tw_dev->sector_count, + tw_dev->max_sector_count, + tw_dev->num_resets, + tw_dev->aen_count); spin_unlock_irqrestore(tw_dev->host->host_lock, flags); return len; } /* End twl_show_stats() */ -/* This function will set a devices queue depth */ -static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth, - int reason) -{ - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - - if (queue_depth > TW_Q_LENGTH-2) - queue_depth = TW_Q_LENGTH-2; - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); - return queue_depth; -} /* End twl_change_queue_depth() */ - /* stats sysfs attribute initializer */ static struct device_attribute twl_host_stats_attr = { .attr = { - .name = "3ware_stats", + .name = "3ware_stats", .mode = S_IRUGO, }, .show = twl_show_stats }; /* Host attributes initializer */ -static struct device_attribute *twl_host_attrs[] = { - &twl_host_stats_attr, +static struct attribute *twl_host_attrs[] = { + &twl_host_stats_attr.attr, NULL, }; +ATTRIBUTE_GROUPS(twl_host); + /* This function will look up an AEN severity string */ static char *twl_aen_severity_lookup(unsigned char severity_code) { @@ -237,7 +223,6 @@ out: static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header) { u32 local_time; - struct timeval time; TW_Event *event; unsigned short aen; char host[16]; @@ -256,8 +241,8 @@ static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H memset(event, 0, sizeof(TW_Event)); event->severity = TW_SEV_OUT(header->status_block.severity__reserved); - do_gettimeofday(&time); - local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60)); + /* event->time_stamp_sec overflows in y2106 */ + local_time = (u32)(ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60)); event->time_stamp_sec = local_time; event->aen_code = aen; event->retrieved = TW_AEN_NOT_RETRIEVED; @@ -303,41 +288,20 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id) return 0; } /* End twl_post_command_packet() */ -/* This function will perform a pci-dma mapping for a scatter gather list */ -static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) -{ - int use_sg; - struct scsi_cmnd *cmd = tw_dev->srb[request_id]; - - use_sg = scsi_dma_map(cmd); - if (!use_sg) - return 0; - else if (use_sg < 0) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list"); - return 0; - } - - cmd->SCp.phase = TW_PHASE_SGLIST; - cmd->SCp.have_data_in = use_sg; - - return use_sg; -} /* End twl_map_scsi_sg_data() */ - /* This function hands scsi cdb's to the firmware */ -static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) +static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + unsigned char *cdb, int use_sg, + TW_SG_Entry_ISO *sglistarg) { TW_Command_Full *full_command_packet; TW_Command_Apache *command_packet; int i, sg_count; struct scsi_cmnd *srb = NULL; - struct scatterlist *sglist = NULL, *sg; + struct scatterlist *sg; int retval = 1; - if (tw_dev->srb[request_id]) { + if (tw_dev->srb[request_id]) srb = tw_dev->srb[request_id]; - if (scsi_sglist(srb)) - sglist = scsi_sglist(srb); - } /* Initialize command packet */ full_command_packet = tw_dev->command_packet_virt[request_id]; @@ -370,8 +334,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (!sglistarg) { /* Map sglist from scsi layer to cmd packet */ if (scsi_sg_count(srb)) { - sg_count = twl_map_scsi_sg_data(tw_dev, request_id); - if (sg_count == 0) + sg_count = scsi_dma_map(srb); + if (sg_count <= 0) goto out; scsi_for_each_sg(srb, sg, sg_count, i) { @@ -409,7 +373,7 @@ out: /* This function will read the aen queue from the isr */ static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) { - char cdb[TW_MAX_CDB_LEN]; + unsigned char cdb[TW_MAX_CDB_LEN]; TW_SG_Entry_ISO sglist[1]; TW_Command_Full *full_command_packet; int retval = 1; @@ -444,11 +408,10 @@ out: static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id) { u32 schedulertime; - struct timeval utc; TW_Command_Full *full_command_packet; TW_Command *command_packet; TW_Param_Apache *param; - u32 local_time; + time64_t local_time; /* Fill out the command packet */ full_command_packet = tw_dev->command_packet_virt[request_id]; @@ -468,12 +431,11 @@ static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id) param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */ param->parameter_size_bytes = cpu_to_le16(4); - /* Convert system time in UTC to local time seconds since last + /* 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); + local_time = (ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60)); + div_u64_rem(local_time - (3 * 86400), 604800, &schedulertime); + schedulertime = cpu_to_le32(schedulertime); memcpy(param->data, &schedulertime, sizeof(u32)); @@ -520,7 +482,7 @@ static int twl_aen_complete(TW_Device_Extension *tw_dev, int request_id) /* Keep reading the queue in case there are more aen's */ if (twl_aen_read_queue(tw_dev, request_id)) goto out2; - else { + else { retval = 0; goto out; } @@ -585,7 +547,7 @@ static int twl_poll_response(TW_Device_Extension *tw_dev, int request_id, int se msleep(50); } retval = 0; -out: +out: return retval; } /* End twl_poll_response() */ @@ -593,7 +555,7 @@ out: static int twl_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) { int request_id = 0; - char cdb[TW_MAX_CDB_LEN]; + unsigned char cdb[TW_MAX_CDB_LEN]; TW_SG_Entry_ISO sglist[1]; int finished = 0, count = 0; TW_Command_Full *full_command_packet; @@ -683,14 +645,14 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) unsigned long *cpu_addr; int retval = 1; - cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle); + cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, + size * TW_Q_LENGTH, &dma_handle, + GFP_KERNEL); if (!cpu_addr) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed"); goto out; } - memset(cpu_addr, 0, size*TW_Q_LENGTH); - for (i = 0; i < TW_Q_LENGTH; i++) { switch(which) { case 0: @@ -728,7 +690,7 @@ static void twl_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm newcommand->request_id__lunl = cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id)); if (length) { - newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); + newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache)); newcommand->sg_list[0].length = TW_CPU_TO_SGL(length); } newcommand->sgl_entries__lunh = @@ -740,7 +702,7 @@ static void twl_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { /* Load the sg list */ sgl = (TW_SG_Entry_ISO *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry_ISO)/4) + pae + (sizeof(dma_addr_t) > 4 ? 1 : 0)); - sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); + sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache)); sgl->length = TW_CPU_TO_SGL(length); oldcommand->size += pae; oldcommand->size += sizeof(dma_addr_t) > 4 ? 1 : 0; @@ -786,7 +748,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511; /* Now allocate ioctl buf memory */ - cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle, GFP_KERNEL); + cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted + sizeof(TW_Ioctl_Buf_Apache), &dma_handle, GFP_KERNEL); if (!cpu_addr) { retval = -ENOMEM; goto out2; @@ -795,7 +757,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long tw_ioctl = (TW_Ioctl_Buf_Apache *)cpu_addr; /* Now copy down the entire ioctl */ - if (copy_from_user(tw_ioctl, argp, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache) - 1)) + if (copy_from_user(tw_ioctl, argp, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache))) goto out3; /* See which ioctl we are doing */ @@ -839,7 +801,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long /* Now copy in the command packet response */ memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virt[request_id], sizeof(TW_Command_Full)); - + /* Now complete the io */ spin_lock_irqsave(tw_dev->host->host_lock, flags); tw_dev->posted_request_count--; @@ -853,11 +815,11 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long } /* Now copy the entire response to userspace */ - if (copy_to_user(argp, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length - 1) == 0) + if (copy_to_user(argp, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length) == 0) retval = 0; out3: /* Now free ioctl buf memory */ - dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); + dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted + sizeof(TW_Ioctl_Buf_Apache), cpu_addr, dma_handle); out2: mutex_unlock(&tw_dev->ioctl_lock); out: @@ -900,7 +862,6 @@ static int twl_fill_sense(TW_Device_Extension *tw_dev, int i, int request_id, in TW_Command_Full *full_command_packet; unsigned short error; char *error_str; - int retval = 1; header = tw_dev->sense_buffer_virt[i]; full_command_packet = tw_dev->command_packet_virt[request_id]; @@ -916,7 +877,7 @@ static int twl_fill_sense(TW_Device_Extension *tw_dev, int i, int request_id, in tw_dev->host->host_no, TW_MESSAGE_SOURCE_CONTROLLER_ERROR, header->status_block.error, - error_str, + error_str, header->err_specific_desc); else printk(KERN_WARNING "3w-sas: ERROR: (0x%02X:0x%04X): %s:%s.\n", @@ -932,26 +893,26 @@ static int twl_fill_sense(TW_Device_Extension *tw_dev, int i, int request_id, in goto out; } out: - return retval; + return 1; } /* End twl_fill_sense() */ /* This function will free up device extension resources */ static void twl_free_device_extension(TW_Device_Extension *tw_dev) { if (tw_dev->command_packet_virt[0]) - pci_free_consistent(tw_dev->tw_pci_dev, + dma_free_coherent(&tw_dev->tw_pci_dev->dev, sizeof(TW_Command_Full)*TW_Q_LENGTH, tw_dev->command_packet_virt[0], tw_dev->command_packet_phys[0]); if (tw_dev->generic_buffer_virt[0]) - pci_free_consistent(tw_dev->tw_pci_dev, + dma_free_coherent(&tw_dev->tw_pci_dev->dev, TW_SECTOR_SIZE*TW_Q_LENGTH, tw_dev->generic_buffer_virt[0], tw_dev->generic_buffer_phys[0]); if (tw_dev->sense_buffer_virt[0]) - pci_free_consistent(tw_dev->tw_pci_dev, + dma_free_coherent(&tw_dev->tw_pci_dev->dev, sizeof(TW_Command_Apache_Header)* TW_Q_LENGTH, tw_dev->sense_buffer_virt[0], @@ -974,8 +935,8 @@ static void *twl_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl command_packet = &full_command_packet->command.oldcommand; 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->size = TW_COMMAND_SIZE; + command_packet->request_id = request_id; command_packet->byte6_offset.block_count = cpu_to_le16(1); /* Now setup the param */ @@ -1005,14 +966,14 @@ static void *twl_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl /* This function will send an initconnection command to controller */ static int twl_initconnection(TW_Device_Extension *tw_dev, int message_credits, - u32 set_features, unsigned short current_fw_srl, - unsigned short current_fw_arch_id, - unsigned short current_fw_branch, - unsigned short current_fw_build, - unsigned short *fw_on_ctlr_srl, - unsigned short *fw_on_ctlr_arch_id, - unsigned short *fw_on_ctlr_branch, - unsigned short *fw_on_ctlr_build, + u32 set_features, unsigned short current_fw_srl, + unsigned short current_fw_arch_id, + unsigned short current_fw_branch, + unsigned short current_fw_build, + unsigned short *fw_on_ctlr_srl, + unsigned short *fw_on_ctlr_arch_id, + unsigned short *fw_on_ctlr_branch, + unsigned short *fw_on_ctlr_build, u32 *init_connect_result) { TW_Command_Full *full_command_packet; @@ -1023,7 +984,7 @@ static int twl_initconnection(TW_Device_Extension *tw_dev, int message_credits, full_command_packet = tw_dev->command_packet_virt[request_id]; memset(full_command_packet, 0, sizeof(TW_Command_Full)); full_command_packet->header.header_desc.size_header = 128; - + 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; @@ -1041,7 +1002,7 @@ static int twl_initconnection(TW_Device_Extension *tw_dev, int message_credits, 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); - } else + } else tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE; /* Send command packet to the board */ @@ -1116,15 +1077,6 @@ out: return retval; } /* End twl_initialize_device_extension() */ -/* This function will perform a pci-dma unmap */ -static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) -{ - struct scsi_cmnd *cmd = tw_dev->srb[request_id]; - - if (cmd->SCp.phase == TW_PHASE_SGLIST) - scsi_dma_unmap(cmd); -} /* End twl_unmap_scsi_data() */ - /* This function will handle attention interrupts */ static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev) { @@ -1257,7 +1209,7 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance) if (!error) cmd->result = (DID_OK << 16); - + /* Report residual bytes for single sgl */ if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) { if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id])) @@ -1265,11 +1217,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance) } /* Now complete the io */ + scsi_dma_unmap(cmd); + scsi_done(cmd); tw_dev->state[request_id] = TW_S_COMPLETED; twl_free_request_id(tw_dev, request_id); tw_dev->posted_request_count--; - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - twl_unmap_scsi_data(tw_dev, request_id); } /* Check for another response interrupt */ @@ -1291,7 +1243,7 @@ static int twl_poll_register(TW_Device_Extension *tw_dev, void *reg, u32 value, reg_value = readl(reg); before = jiffies; - while ((reg_value & value) != result) { + while ((reg_value & value) != result) { reg_value = readl(reg); if (time_after(jiffies, before + HZ * seconds)) goto out; @@ -1374,7 +1326,8 @@ static int twl_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset) } /* Load rest of compatibility struct */ - strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION)); + strscpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, + sizeof(tw_dev->tw_compat_info.driver_version)); tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL; tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH; tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD; @@ -1414,10 +1367,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res if ((tw_dev->state[i] != TW_S_FINISHED) && (tw_dev->state[i] != TW_S_INITIAL) && (tw_dev->state[i] != TW_S_COMPLETED)) { - if (tw_dev->srb[i]) { - tw_dev->srb[i]->result = (DID_RESET << 16); - tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); - twl_unmap_scsi_data(tw_dev, i); + struct scsi_cmnd *cmd = tw_dev->srb[i]; + + if (cmd) { + cmd->result = (DID_RESET << 16); + scsi_dma_unmap(cmd); + scsi_done(cmd); } } } @@ -1449,12 +1404,9 @@ out: } /* End twl_reset_device_extension() */ /* This funciton returns unit geometry in cylinders/heads/sectors */ -static int twl_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) +static int twl_scsi_biosparam(struct scsi_device *sdev, struct gendisk *unused, sector_t capacity, int geom[]) { int heads, sectors; - TW_Device_Extension *tw_dev; - - tw_dev = (TW_Device_Extension *)sdev->host->hostdata; if (capacity >= 0x200000) { heads = 255; @@ -1501,8 +1453,9 @@ out: } /* End twl_scsi_eh_reset() */ /* This is the main scsi queue function to handle scsi opcodes */ -static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt) { + void (*done)(struct scsi_cmnd *) = scsi_done; int request_id, retval; TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; @@ -1512,18 +1465,12 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ goto out; } - /* Save done function into scsi_cmnd struct */ - SCpnt->scsi_done = done; - /* Get a free request id */ twl_get_request_id(tw_dev, &request_id); /* Save the scsi command for use by the ISR */ tw_dev->srb[request_id] = SCpnt; - /* Initialize phase to zero */ - SCpnt->SCp.phase = TW_PHASE_INITIAL; - retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); if (retval) { tw_dev->state[request_id] = TW_S_COMPLETED; @@ -1571,36 +1518,36 @@ static void twl_shutdown(struct pci_dev *pdev) tw_dev = (TW_Device_Extension *)host->hostdata; - if (tw_dev->online) + if (tw_dev->online) __twl_shutdown(tw_dev); } /* End twl_shutdown() */ /* This function configures unit settings when a unit is coming on-line */ -static int twl_slave_configure(struct scsi_device *sdev) +static int twl_sdev_configure(struct scsi_device *sdev, + struct queue_limits *lim) { /* Force 60 second timeout */ blk_queue_rq_timeout(sdev->request_queue, 60 * HZ); return 0; -} /* End twl_slave_configure() */ +} /* End twl_sdev_configure() */ -/* scsi_host_template initializer */ -static struct scsi_host_template driver_template = { +static const struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "3w-sas", .queuecommand = twl_scsi_queue, .eh_host_reset_handler = twl_scsi_eh_reset, .bios_param = twl_scsi_biosparam, - .change_queue_depth = twl_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .can_queue = TW_Q_LENGTH-2, - .slave_configure = twl_slave_configure, + .sdev_configure = twl_sdev_configure, .this_id = -1, .sg_tablesize = TW_LIBERATOR_MAX_SGL_LENGTH, .max_sectors = TW_MAX_SECTORS, .cmd_per_lun = TW_MAX_CMDS_PER_LUN, - .use_clustering = ENABLE_CLUSTERING, - .shost_attrs = twl_host_attrs, - .emulated = 1 + .shost_groups = twl_host_groups, + .emulated = 1, + .no_write_same = 1, }; /* This function will probe and initialize a card */ @@ -1620,14 +1567,12 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) - || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) - || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask"); - retval = -ENODEV; - goto out_disable_device; - } + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (retval) { + TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask"); + retval = -ENODEV; + goto out_disable_device; + } host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); if (!host) { @@ -1643,6 +1588,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) if (twl_initialize_device_extension(tw_dev)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension"); + retval = -ENOMEM; goto out_free_device_extension; } @@ -1657,6 +1603,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) tw_dev->base_addr = pci_iomap(pdev, 1, 0); if (!tw_dev->base_addr) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap"); + retval = -ENOMEM; goto out_release_mem_region; } @@ -1666,6 +1613,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) /* Initialize the card */ if (twl_reset_sequence(tw_dev, 0)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe"); + retval = -ENOMEM; goto out_iounmap; } @@ -1719,7 +1667,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) /* Re-enable interrupts on the card */ TWL_UNMASK_INTERRUPTS(tw_dev); - + /* Finally, scan the host */ scsi_scan_host(host); @@ -1800,11 +1748,10 @@ static void twl_remove(struct pci_dev *pdev) twl_device_extension_count--; } /* End twl_remove() */ -#ifdef CONFIG_PM /* This function is called on PCI suspend */ -static int twl_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused twl_suspend(struct device *dev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); + struct Scsi_Host *host = dev_get_drvdata(dev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; printk(KERN_WARNING "3w-sas: Suspending host %d.\n", tw_dev->host->host_no); @@ -1823,43 +1770,27 @@ static int twl_suspend(struct pci_dev *pdev, pm_message_t state) /* Clear doorbell interrupt */ TWL_CLEAR_DB_INTERRUPT(tw_dev); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } /* End twl_suspend() */ /* This function is called on PCI resume */ -static int twl_resume(struct pci_dev *pdev) +static int __maybe_unused twl_resume(struct device *dev) { int retval = 0; + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; printk(KERN_WARNING "3w-sas: Resuming host %d.\n", tw_dev->host->host_no); - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); + pci_try_set_mwi(pdev); - retval = pci_enable_device(pdev); + retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (retval) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x24, "Enable device failed during resume"); - return retval; + TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume"); + retval = -ENODEV; + goto out_disable_device; } - pci_set_master(pdev); - pci_try_set_mwi(pdev); - - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) - || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) - || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume"); - retval = -ENODEV; - goto out_disable_device; - } - /* Initialize the card */ if (twl_reset_sequence(tw_dev, 0)) { retval = -ENODEV; @@ -1886,29 +1817,26 @@ static int twl_resume(struct pci_dev *pdev) out_disable_device: scsi_remove_host(host); - pci_disable_device(pdev); return retval; } /* End twl_resume() */ -#endif /* PCI Devices supported by this driver */ -static struct pci_device_id twl_pci_tbl[] = { +static const struct pci_device_id twl_pci_tbl[] = { { PCI_VDEVICE(3WARE, PCI_DEVICE_ID_3WARE_9750) }, { } }; MODULE_DEVICE_TABLE(pci, twl_pci_tbl); +static SIMPLE_DEV_PM_OPS(twl_pm_ops, twl_suspend, twl_resume); + /* pci_driver initializer */ static struct pci_driver twl_driver = { .name = "3w-sas", .id_table = twl_pci_tbl, .probe = twl_probe, .remove = twl_remove, -#ifdef CONFIG_PM - .suspend = twl_suspend, - .resume = twl_resume, -#endif + .driver.pm = &twl_pm_ops, .shutdown = twl_shutdown }; |
