diff options
Diffstat (limited to 'drivers/scsi/smartpqi/smartpqi_init.c')
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 559 |
1 files changed, 418 insertions, 141 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index f0897d587454..7c0d069a3158 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "2.1.12-055" +#define DRIVER_VERSION "2.1.14-035" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 -#define DRIVER_RELEASE 12 -#define DRIVER_REVISION 55 +#define DRIVER_RELEASE 14 +#define DRIVER_REVISION 35 #define DRIVER_NAME "Microchip SmartPQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" @@ -54,6 +54,16 @@ MODULE_DESCRIPTION("Driver for Microchip Smart Family Controller version " MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); +struct pqi_cmd_priv { + int this_residual; +}; + +static struct pqi_cmd_priv *pqi_cmd_priv(struct scsi_cmnd *cmd) +{ + return scsi_cmd_priv(cmd); +} + +static void pqi_verify_structures(void); static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info, enum pqi_ctrl_shutdown_reason ctrl_shutdown_reason); static void pqi_ctrl_offline_worker(struct work_struct *work); @@ -68,7 +78,7 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info, static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, struct scsi_cmnd *scmd, u32 aio_handle, u8 *cdb, unsigned int cdb_length, struct pqi_queue_group *queue_group, - struct pqi_encryption_info *encryption_info, bool raid_bypass); + struct pqi_encryption_info *encryption_info, bool raid_bypass, bool io_high_prio); static int pqi_aio_submit_r1_write_io(struct pqi_ctrl_info *ctrl_info, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group, struct pqi_encryption_info *encryption_info, struct pqi_scsi_dev *device, @@ -376,7 +386,7 @@ static inline void pqi_ctrl_wait_until_quiesced(struct pqi_ctrl_info *ctrl_info) displayed_warning = false; start_jiffies = jiffies; - warning_timeout = (PQI_QUIESCE_WARNING_TIMEOUT_SECS * PQI_HZ) + start_jiffies; + warning_timeout = (PQI_QUIESCE_WARNING_TIMEOUT_SECS * HZ) + start_jiffies; while (atomic_read(&ctrl_info->num_busy_threads) > atomic_read(&ctrl_info->num_blocked_threads)) { @@ -385,7 +395,7 @@ static inline void pqi_ctrl_wait_until_quiesced(struct pqi_ctrl_info *ctrl_info) "waiting %u seconds for driver activity to quiesce\n", jiffies_to_msecs(jiffies - start_jiffies) / 1000); displayed_warning = true; - warning_timeout = (PQI_QUIESCE_WARNING_TIMEOUT_SECS * PQI_HZ) + jiffies; + warning_timeout = (PQI_QUIESCE_WARNING_TIMEOUT_SECS * HZ) + jiffies; } usleep_range(1000, 2000); } @@ -462,7 +472,7 @@ static inline void pqi_schedule_rescan_worker(struct pqi_ctrl_info *ctrl_info) pqi_schedule_rescan_worker_with_delay(ctrl_info, 0); } -#define PQI_RESCAN_WORK_DELAY (10 * PQI_HZ) +#define PQI_RESCAN_WORK_DELAY (10 * HZ) static inline void pqi_schedule_rescan_worker_delayed(struct pqi_ctrl_info *ctrl_info) { @@ -1038,7 +1048,7 @@ static int pqi_write_current_time_to_host_wellness( return rc; } -#define PQI_UPDATE_TIME_WORK_INTERVAL (24UL * 60 * 60 * PQI_HZ) +#define PQI_UPDATE_TIME_WORK_INTERVAL (24UL * 60 * 60 * HZ) static void pqi_update_time_worker(struct work_struct *work) { @@ -1181,8 +1191,8 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b for (i = 0; i < num_physicals; i++) { memcpy(&rpl_16byte_wwid_list->lun_entries[i].lunid, &rpl_8byte_wwid_list->lun_entries[i].lunid, sizeof(rpl_8byte_wwid_list->lun_entries[i].lunid)); - memset(&rpl_16byte_wwid_list->lun_entries[i].wwid, 0, 8); - memcpy(&rpl_16byte_wwid_list->lun_entries[i].wwid[8], &rpl_8byte_wwid_list->lun_entries[i].wwid, sizeof(rpl_8byte_wwid_list->lun_entries[i].wwid)); + memcpy(&rpl_16byte_wwid_list->lun_entries[i].wwid[0], &rpl_8byte_wwid_list->lun_entries[i].wwid, sizeof(rpl_8byte_wwid_list->lun_entries[i].wwid)); + memset(&rpl_16byte_wwid_list->lun_entries[i].wwid[8], 0, 8); rpl_16byte_wwid_list->lun_entries[i].device_type = rpl_8byte_wwid_list->lun_entries[i].device_type; rpl_16byte_wwid_list->lun_entries[i].device_flags = rpl_8byte_wwid_list->lun_entries[i].device_flags; rpl_16byte_wwid_list->lun_entries[i].lun_count = rpl_8byte_wwid_list->lun_entries[i].lun_count; @@ -1549,6 +1559,7 @@ no_buffer: device->volume_offline = volume_offline; } +#define PQI_DEVICE_NCQ_PRIO_SUPPORTED 0x01 #define PQI_DEVICE_PHY_MAP_SUPPORTED 0x10 static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, @@ -1587,9 +1598,6 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, sizeof(device->phys_connector)); device->bay = id_phys->phys_bay_in_box; - memcpy(&device->page_83_identifier, &id_phys->page_83_identifier, - sizeof(device->page_83_identifier)); - if ((id_phys->even_more_flags & PQI_DEVICE_PHY_MAP_SUPPORTED) && id_phys->phy_count) device->phy_id = @@ -1597,6 +1605,10 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, else device->phy_id = 0xFF; + device->ncq_prio_support = + ((get_unaligned_le32(&id_phys->misc_drive_flags) >> 16) & + PQI_DEVICE_NCQ_PRIO_SUPPORTED); + return 0; } @@ -2010,8 +2022,8 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info, /* Assumes the SCSI device list lock is held. */ -static void pqi_scsi_update_device(struct pqi_scsi_dev *existing_device, - struct pqi_scsi_dev *new_device) +static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, + struct pqi_scsi_dev *existing_device, struct pqi_scsi_dev *new_device) { existing_device->device_type = new_device->device_type; existing_device->bus = new_device->bus; @@ -2021,9 +2033,8 @@ static void pqi_scsi_update_device(struct pqi_scsi_dev *existing_device, existing_device->target_lun_valid = true; } - if ((existing_device->volume_status == CISS_LV_QUEUED_FOR_EXPANSION || - existing_device->volume_status == CISS_LV_UNDERGOING_EXPANSION) && - new_device->volume_status == CISS_LV_OK) + if (pqi_is_logical_device(existing_device) && + ctrl_info->logical_volume_rescan_needed) existing_device->rescan = true; /* By definition, the scsi3addr and wwid fields are already the same. */ @@ -2054,7 +2065,7 @@ static void pqi_scsi_update_device(struct pqi_scsi_dev *existing_device, sizeof(existing_device->box)); memcpy(existing_device->phys_connector, new_device->phys_connector, sizeof(existing_device->phys_connector)); - existing_device->next_bypass_group = 0; + memset(existing_device->next_bypass_group, 0, sizeof(existing_device->next_bypass_group)); kfree(existing_device->raid_map); existing_device->raid_map = new_device->raid_map; existing_device->raid_bypass_configured = @@ -2141,7 +2152,7 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, */ device->new_device = false; matching_device->device_gone = false; - pqi_scsi_update_device(matching_device, device); + pqi_scsi_update_device(ctrl_info, matching_device, device); break; case DEVICE_NOT_FOUND: /* @@ -2213,8 +2224,8 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, } /* - * Notify the SCSI ML if the queue depth of any existing device has - * changed. + * Notify the SML of any existing device changes such as; + * queue depth, device size. */ list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry) { if (device->sdev && device->queue_depth != device->advertised_queue_depth) { @@ -2243,6 +2254,9 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, } } } + + ctrl_info->logical_volume_rescan_needed = false; + } static inline bool pqi_is_supported_device(struct pqi_scsi_dev *device) @@ -2274,16 +2288,12 @@ static inline void pqi_mask_device(u8 *scsi3addr) scsi3addr[3] |= 0xc0; } -static inline bool pqi_is_device_with_sas_address(struct pqi_scsi_dev *device) +static inline bool pqi_is_multipath_device(struct pqi_scsi_dev *device) { - switch (device->device_type) { - case SA_DEVICE_TYPE_SAS: - case SA_DEVICE_TYPE_EXPANDER_SMP: - case SA_DEVICE_TYPE_SES: - return true; - } + if (pqi_is_logical_device(device)) + return false; - return false; + return (device->path_map & (device->path_map - 1)) != 0; } static inline bool pqi_expose_device(struct pqi_scsi_dev *device) @@ -2291,17 +2301,6 @@ static inline bool pqi_expose_device(struct pqi_scsi_dev *device) return !device->is_physical_device || !pqi_skip_device(device->scsi3addr); } -static inline void pqi_set_physical_device_wwid(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device, struct report_phys_lun_16byte_wwid *phys_lun) -{ - if (ctrl_info->unique_wwid_in_report_phys_lun_supported || - ctrl_info->rpl_extended_format_4_5_supported || - pqi_is_device_with_sas_address(device)) - memcpy(device->wwid, phys_lun->wwid, sizeof(device->wwid)); - else - memcpy(&device->wwid[8], device->page_83_identifier, 8); -} - static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) { int i; @@ -2469,7 +2468,7 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) pqi_assign_bus_target_lun(device); if (device->is_physical_device) { - pqi_set_physical_device_wwid(ctrl_info, device, phys_lun); + memcpy(device->wwid, phys_lun->wwid, sizeof(device->wwid)); if ((phys_lun->device_flags & CISS_REPORT_PHYS_DEV_FLAG_AIO_ENABLED) && phys_lun->aio_handle) { @@ -2482,8 +2481,7 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) sizeof(device->volume_id)); } - if (pqi_is_device_with_sas_address(device)) - device->sas_address = get_unaligned_be64(&device->wwid[8]); + device->sas_address = get_unaligned_be64(&device->wwid[0]); new_device_list[num_valid_devices++] = device; } @@ -2513,17 +2511,15 @@ static void pqi_remove_all_scsi_devices(struct pqi_ctrl_info *ctrl_info) struct pqi_scsi_dev *device; struct pqi_scsi_dev *next; - spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); - list_for_each_entry_safe(device, next, &ctrl_info->scsi_device_list, scsi_device_list_entry) { if (pqi_is_device_added(device)) pqi_remove_device(ctrl_info, device); + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); list_del(&device->scsi_device_list_entry); pqi_free_device(device); + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); } - - spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); } static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info) @@ -2950,11 +2946,11 @@ static int pqi_raid_bypass_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, if (rmd.is_write) { pqi_calc_aio_r1_nexus(raid_map, &rmd); } else { - group = device->next_bypass_group; + group = device->next_bypass_group[rmd.map_index]; next_bypass_group = group + 1; if (next_bypass_group >= rmd.layout_map_count) next_bypass_group = 0; - device->next_bypass_group = next_bypass_group; + device->next_bypass_group[rmd.map_index] = next_bypass_group; rmd.map_index += group * rmd.data_disks_per_row; } } else if ((device->raid_level == SA_RAID_5 || @@ -3009,7 +3005,7 @@ static int pqi_raid_bypass_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, return pqi_aio_submit_io(ctrl_info, scmd, rmd.aio_handle, rmd.cdb, rmd.cdb_length, queue_group, - encryption_info_ptr, true); + encryption_info_ptr, true, false); } #define PQI_STATUS_IDLE 0x0 @@ -3034,7 +3030,7 @@ static int pqi_wait_for_pqi_mode_ready(struct pqi_ctrl_info *ctrl_info) u8 status; pqi_registers = ctrl_info->pqi_registers; - timeout = (PQI_MODE_READY_TIMEOUT_SECS * PQI_HZ) + jiffies; + timeout = (PQI_MODE_READY_TIMEOUT_SECS * HZ) + jiffies; while (1) { signature = readq(&pqi_registers->signature); @@ -3213,12 +3209,14 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) int residual_count; int xfer_count; bool device_offline; + struct pqi_scsi_dev *device; scmd = io_request->scmd; error_info = io_request->error_info; host_byte = DID_OK; sense_data_length = 0; device_offline = false; + device = scmd->device->hostdata; switch (error_info->service_response) { case PQI_AIO_SERV_RESPONSE_COMPLETE: @@ -3243,8 +3241,14 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) break; case PQI_AIO_STATUS_AIO_PATH_DISABLED: pqi_aio_path_disabled(io_request); - scsi_status = SAM_STAT_GOOD; - io_request->status = -EAGAIN; + if (pqi_is_multipath_device(device)) { + pqi_device_remove_start(device); + host_byte = DID_NO_CONNECT; + scsi_status = SAM_STAT_CHECK_CONDITION; + } else { + scsi_status = SAM_STAT_GOOD; + io_request->status = -EAGAIN; + } break; case PQI_AIO_STATUS_NO_PATH_TO_DEVICE: case PQI_AIO_STATUS_INVALID_DEVICE: @@ -3520,7 +3524,7 @@ static enum pqi_soft_reset_status pqi_poll_for_soft_reset_status( u8 status; unsigned long timeout; - timeout = (PQI_SOFT_RESET_STATUS_TIMEOUT_SECS * PQI_HZ) + jiffies; + timeout = (PQI_SOFT_RESET_STATUS_TIMEOUT_SECS * HZ) + jiffies; while (1) { status = pqi_read_soft_reset_status(ctrl_info); @@ -3684,6 +3688,8 @@ static void pqi_event_worker(struct work_struct *work) } else { ack_event = true; rescan_needed = true; + if (event->event_type == PQI_EVENT_TYPE_LOGICAL_DEVICE) + ctrl_info->logical_volume_rescan_needed = true; } if (ack_event) pqi_acknowledge_event(ctrl_info, event); @@ -3698,7 +3704,7 @@ out: pqi_ctrl_unbusy(ctrl_info); } -#define PQI_HEARTBEAT_TIMER_INTERVAL (10 * PQI_HZ) +#define PQI_HEARTBEAT_TIMER_INTERVAL (10 * HZ) static void pqi_heartbeat_timer_handler(struct timer_list *t) { @@ -4245,7 +4251,7 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info) return 0; } -#define PQI_ADMIN_QUEUE_CREATE_TIMEOUT_JIFFIES PQI_HZ +#define PQI_ADMIN_QUEUE_CREATE_TIMEOUT_JIFFIES HZ #define PQI_ADMIN_QUEUE_CREATE_POLL_INTERVAL_MSECS 1 static int pqi_create_admin_queues(struct pqi_ctrl_info *ctrl_info) @@ -4339,7 +4345,7 @@ static int pqi_poll_for_admin_response(struct pqi_ctrl_info *ctrl_info, admin_queues = &ctrl_info->admin_queues; oq_ci = admin_queues->oq_ci_copy; - timeout = (PQI_ADMIN_REQUEST_TIMEOUT_SECS * PQI_HZ) + jiffies; + timeout = (PQI_ADMIN_REQUEST_TIMEOUT_SECS * HZ) + jiffies; while (1) { oq_pi = readl(admin_queues->oq_pi); @@ -4454,7 +4460,7 @@ static int pqi_wait_for_completion_io(struct pqi_ctrl_info *ctrl_info, while (1) { if (wait_for_completion_io_timeout(wait, - PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS * PQI_HZ)) { + PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS * HZ)) { rc = 0; break; } @@ -5555,25 +5561,62 @@ static void pqi_aio_io_complete(struct pqi_io_request *io_request, scsi_dma_unmap(scmd); if (io_request->status == -EAGAIN || pqi_raid_bypass_retry_needed(io_request)) { set_host_byte(scmd, DID_IMM_RETRY); - scmd->SCp.this_residual++; + pqi_cmd_priv(scmd)->this_residual++; } pqi_free_io_request(io_request); pqi_scsi_done(scmd); } +static inline bool pqi_is_io_high_priority(struct pqi_ctrl_info *ctrl_info, + struct pqi_scsi_dev *device, struct scsi_cmnd *scmd) +{ + bool io_high_prio; + int priority_class; + + io_high_prio = false; + + if (device->ncq_prio_enable) { + priority_class = + IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))); + if (priority_class == IOPRIO_CLASS_RT) { + /* Set NCQ priority for read/write commands. */ + switch (scmd->cmnd[0]) { + case WRITE_16: + case READ_16: + case WRITE_12: + case READ_12: + case WRITE_10: + case READ_10: + case WRITE_6: + case READ_6: + io_high_prio = true; + break; + } + } + } + + return io_high_prio; +} + static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group) { + bool io_high_prio; + + io_high_prio = pqi_is_io_high_priority(ctrl_info, device, scmd); + return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle, - scmd->cmnd, scmd->cmd_len, queue_group, NULL, false); + scmd->cmnd, scmd->cmd_len, queue_group, NULL, + false, io_high_prio); } static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, struct scsi_cmnd *scmd, u32 aio_handle, u8 *cdb, unsigned int cdb_length, struct pqi_queue_group *queue_group, - struct pqi_encryption_info *encryption_info, bool raid_bypass) + struct pqi_encryption_info *encryption_info, bool raid_bypass, + bool io_high_prio) { int rc; struct pqi_io_request *io_request; @@ -5585,12 +5628,13 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, io_request->raid_bypass = raid_bypass; request = io_request->iu; - memset(request, 0, offsetof(struct pqi_raid_path_request, sg_descriptors)); + memset(request, 0, offsetof(struct pqi_aio_path_request, sg_descriptors)); request->header.iu_type = PQI_REQUEST_IU_AIO_PATH_IO; put_unaligned_le32(aio_handle, &request->nexus_id); put_unaligned_le32(scsi_bufflen(scmd), &request->buffer_length); request->task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE; + request->command_priority = io_high_prio; put_unaligned_le16(io_request->index, &request->request_id); request->error_index = request->request_id; if (cdb_length > sizeof(request->cdb)) @@ -5779,7 +5823,7 @@ static inline bool pqi_is_bypass_eligible_request(struct scsi_cmnd *scmd) if (blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) return false; - return scmd->SCp.this_residual == 0; + return pqi_cmd_priv(scmd)->this_residual == 0; } /* @@ -6008,7 +6052,7 @@ static int pqi_wait_until_inbound_queues_empty(struct pqi_ctrl_info *ctrl_info) displayed_warning = false; start_jiffies = jiffies; - warning_timeout = (PQI_INBOUND_QUEUES_NONEMPTY_WARNING_TIMEOUT_SECS * PQI_HZ) + start_jiffies; + warning_timeout = (PQI_INBOUND_QUEUES_NONEMPTY_WARNING_TIMEOUT_SECS * HZ) + start_jiffies; while (1) { queued_io_count = pqi_queued_io_count(ctrl_info); @@ -6023,7 +6067,7 @@ static int pqi_wait_until_inbound_queues_empty(struct pqi_ctrl_info *ctrl_info) "waiting %u seconds for queued I/O to drain (queued I/O count: %u; non-empty inbound queue count: %u)\n", jiffies_to_msecs(jiffies - start_jiffies) / 1000, queued_io_count, nonempty_inbound_queue_count); displayed_warning = true; - warning_timeout = (PQI_INBOUND_QUEUES_NONEMPTY_WARNING_TIMEOUT_SECS * PQI_HZ) + jiffies; + warning_timeout = (PQI_INBOUND_QUEUES_NONEMPTY_WARNING_TIMEOUT_SECS * HZ) + jiffies; } usleep_range(1000, 2000); } @@ -6091,7 +6135,7 @@ static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info, unsigned long msecs_waiting; start_jiffies = jiffies; - warning_timeout = (PQI_PENDING_IO_WARNING_TIMEOUT_SECS * PQI_HZ) + start_jiffies; + warning_timeout = (PQI_PENDING_IO_WARNING_TIMEOUT_SECS * HZ) + start_jiffies; while ((cmds_outstanding = atomic_read(&device->scsi_cmds_outstanding)) > 0) { pqi_check_ctrl_health(ctrl_info); @@ -6110,7 +6154,7 @@ static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info, "scsi %d:%d:%d:%d: waiting %lu seconds for %d outstanding command(s)\n", ctrl_info->scsi_host->host_no, device->bus, device->target, device->lun, msecs_waiting / 1000, cmds_outstanding); - warning_timeout = (PQI_PENDING_IO_WARNING_TIMEOUT_SECS * PQI_HZ) + jiffies; + warning_timeout = (PQI_PENDING_IO_WARNING_TIMEOUT_SECS * HZ) + jiffies; } usleep_range(1000, 2000); } @@ -6139,7 +6183,7 @@ static int pqi_wait_for_lun_reset_completion(struct pqi_ctrl_info *ctrl_info, while (1) { if (wait_for_completion_io_timeout(wait, - PQI_LUN_RESET_POLL_COMPLETION_SECS * PQI_HZ)) { + PQI_LUN_RESET_POLL_COMPLETION_SECS * HZ)) { rc = 0; break; } @@ -7026,7 +7070,7 @@ static ssize_t pqi_sas_address_show(struct device *dev, spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; - if (!device || !pqi_is_device_with_sas_address(device)) { + if (!device) { spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); return -ENODEV; } @@ -7123,6 +7167,71 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, return scnprintf(buffer, PAGE_SIZE, "0x%x\n", raid_bypass_cnt); } +static ssize_t pqi_sas_ncq_prio_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pqi_ctrl_info *ctrl_info; + struct scsi_device *sdev; + struct pqi_scsi_dev *device; + unsigned long flags; + int output_len = 0; + + sdev = to_scsi_device(dev); + ctrl_info = shost_to_hba(sdev->host); + + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); + + device = sdev->hostdata; + if (!device) { + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + return -ENODEV; + } + + output_len = snprintf(buf, PAGE_SIZE, "%d\n", + device->ncq_prio_enable); + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + + return output_len; +} + +static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pqi_ctrl_info *ctrl_info; + struct scsi_device *sdev; + struct pqi_scsi_dev *device; + unsigned long flags; + u8 ncq_prio_enable = 0; + + if (kstrtou8(buf, 0, &ncq_prio_enable)) + return -EINVAL; + + sdev = to_scsi_device(dev); + ctrl_info = shost_to_hba(sdev->host); + + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); + + device = sdev->hostdata; + + if (!device) { + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + return -ENODEV; + } + + if (!device->ncq_prio_support || + !device->is_physical_device) { + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + return -EINVAL; + } + + device->ncq_prio_enable = ncq_prio_enable; + + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + + return strlen(buf); +} + static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL); static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL); static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL); @@ -7130,6 +7239,8 @@ static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL); static DEVICE_ATTR(ssd_smart_path_enabled, 0444, pqi_ssd_smart_path_enabled_show, NULL); static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL); static DEVICE_ATTR(raid_bypass_cnt, 0444, pqi_raid_bypass_cnt_show, NULL); +static DEVICE_ATTR(sas_ncq_prio_enable, 0644, + pqi_sas_ncq_prio_enable_show, pqi_sas_ncq_prio_enable_store); static struct attribute *pqi_sdev_attrs[] = { &dev_attr_lunid.attr, @@ -7139,6 +7250,7 @@ static struct attribute *pqi_sdev_attrs[] = { &dev_attr_ssd_smart_path_enabled.attr, &dev_attr_raid_level.attr, &dev_attr_raid_bypass_cnt.attr, + &dev_attr_sas_ncq_prio_enable.attr, NULL }; @@ -7159,6 +7271,7 @@ static struct scsi_host_template pqi_driver_template = { .map_queues = pqi_map_queues, .sdev_groups = pqi_sdev_groups, .shost_groups = pqi_shost_groups, + .cmd_size = sizeof(struct pqi_cmd_priv), }; static int pqi_register_scsi(struct pqi_ctrl_info *ctrl_info) @@ -7514,10 +7627,6 @@ static void pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info, case PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT: ctrl_info->tmf_iu_timeout_supported = firmware_feature->enabled; break; - case PQI_FIRMWARE_FEATURE_UNIQUE_WWID_IN_REPORT_PHYS_LUN: - ctrl_info->unique_wwid_in_report_phys_lun_supported = - firmware_feature->enabled; - break; case PQI_FIRMWARE_FEATURE_FW_TRIAGE: ctrl_info->firmware_triage_supported = firmware_feature->enabled; pqi_save_fw_triage_setting(ctrl_info, firmware_feature->enabled); @@ -7616,11 +7725,6 @@ static struct pqi_firmware_feature pqi_firmware_features[] = { .feature_status = pqi_firmware_feature_status, }, { - .feature_name = "Unique WWID in Report Physical LUN", - .feature_bit = PQI_FIRMWARE_FEATURE_UNIQUE_WWID_IN_REPORT_PHYS_LUN, - .feature_status = pqi_ctrl_update_feature_flags, - }, - { .feature_name = "Firmware Triage", .feature_bit = PQI_FIRMWARE_FEATURE_FW_TRIAGE, .feature_status = pqi_ctrl_update_feature_flags, @@ -7729,7 +7833,6 @@ static void pqi_ctrl_reset_config(struct pqi_ctrl_info *ctrl_info) ctrl_info->enable_r6_writes = false; ctrl_info->raid_iu_timeout_supported = false; ctrl_info->tmf_iu_timeout_supported = false; - ctrl_info->unique_wwid_in_report_phys_lun_supported = false; ctrl_info->firmware_triage_supported = false; ctrl_info->rpl_extended_format_4_5_supported = false; } @@ -7857,6 +7960,21 @@ static int pqi_force_sis_mode(struct pqi_ctrl_info *ctrl_info) return pqi_revert_to_sis_mode(ctrl_info); } +static void pqi_perform_lockup_action(void) +{ + switch (pqi_lockup_action) { + case PANIC: + panic("FATAL: Smart Family Controller lockup detected"); + break; + case REBOOT: + emergency_restart(); + break; + case NONE: + default: + break; + } +} + static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) { int rc; @@ -7869,7 +7987,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) return rc; } sis_soft_reset(ctrl_info); - msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ); + ssleep(PQI_POST_RESET_DELAY_SECS); } else { rc = pqi_force_sis_mode(ctrl_info); if (rc) @@ -7881,8 +7999,15 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) * commands. */ rc = sis_wait_for_ctrl_ready(ctrl_info); - if (rc) + if (rc) { + if (reset_devices) { + dev_err(&ctrl_info->pci_dev->dev, + "kdump init failed with error %d\n", rc); + pqi_lockup_action = REBOOT; + pqi_perform_lockup_action(); + } return rc; + } /* * Get the controller properties. This allows us to determine @@ -8607,21 +8732,6 @@ static int pqi_ofa_ctrl_restart(struct pqi_ctrl_info *ctrl_info, unsigned int de return pqi_ctrl_init_resume(ctrl_info); } -static void pqi_perform_lockup_action(void) -{ - switch (pqi_lockup_action) { - case PANIC: - panic("FATAL: Smart Family Controller lockup detected"); - break; - case REBOOT: - emergency_restart(); - break; - case NONE: - default: - break; - } -} - static struct pqi_raid_error_info pqi_ctrl_offline_raid_error_info = { .data_out_result = PQI_DATA_IN_OUT_HARDWARE_ERROR, .status = SAM_STAT_CHECK_CONDITION, @@ -8712,7 +8822,7 @@ static int pqi_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { int rc; - int node, cp_node; + int node; struct pqi_ctrl_info *ctrl_info; pqi_print_ctrl_info(pci_dev, id); @@ -8731,10 +8841,10 @@ static int pqi_pci_probe(struct pci_dev *pci_dev, node = dev_to_node(&pci_dev->dev); if (node == NUMA_NO_NODE) { - cp_node = cpu_to_node(0); - if (cp_node == NUMA_NO_NODE) - cp_node = 0; - set_dev_node(&pci_dev->dev, cp_node); + node = cpu_to_node(0); + if (node == NUMA_NO_NODE) + node = 0; + set_dev_node(&pci_dev->dev, node); } ctrl_info = pqi_alloc_ctrl_info(node); @@ -8793,6 +8903,7 @@ static void pqi_shutdown(struct pci_dev *pci_dev) { int rc; struct pqi_ctrl_info *ctrl_info; + enum bmic_flush_cache_shutdown_event shutdown_event; ctrl_info = pci_get_drvdata(pci_dev); if (!ctrl_info) { @@ -8808,11 +8919,16 @@ static void pqi_shutdown(struct pci_dev *pci_dev) pqi_ctrl_block_requests(ctrl_info); pqi_ctrl_wait_until_quiesced(ctrl_info); + if (system_state == SYSTEM_RESTART) + shutdown_event = RESTART; + else + shutdown_event = SHUTDOWN; + /* * Write all data in the controller's battery-backed cache to * storage. */ - rc = pqi_flush_cache(ctrl_info, SHUTDOWN); + rc = pqi_flush_cache(ctrl_info, shutdown_event); if (rc) dev_err(&pci_dev->dev, "unable to flush controller cache\n"); @@ -8845,10 +8961,22 @@ static void pqi_process_module_params(void) pqi_process_lockup_action_param(); } -static __maybe_unused int pqi_suspend(struct pci_dev *pci_dev, pm_message_t state) +#if defined(CONFIG_PM) + +static inline enum bmic_flush_cache_shutdown_event pqi_get_flush_cache_shutdown_event(struct pci_dev *pci_dev) +{ + if (pci_dev->subsystem_vendor == PCI_VENDOR_ID_ADAPTEC2 && pci_dev->subsystem_device == 0x1304) + return RESTART; + + return SUSPEND; +} + +static int pqi_suspend_or_freeze(struct device *dev, bool suspend) { + struct pci_dev *pci_dev; struct pqi_ctrl_info *ctrl_info; + pci_dev = to_pci_dev(dev); ctrl_info = pci_get_drvdata(pci_dev); pqi_wait_until_ofa_finished(ctrl_info); @@ -8858,16 +8986,17 @@ static __maybe_unused int pqi_suspend(struct pci_dev *pci_dev, pm_message_t stat pqi_ctrl_block_device_reset(ctrl_info); pqi_ctrl_block_requests(ctrl_info); pqi_ctrl_wait_until_quiesced(ctrl_info); - pqi_flush_cache(ctrl_info, SUSPEND); - pqi_stop_heartbeat_timer(ctrl_info); - pqi_crash_if_pending_command(ctrl_info); + if (suspend) { + enum bmic_flush_cache_shutdown_event shutdown_event; - if (state.event == PM_EVENT_FREEZE) - return 0; + shutdown_event = pqi_get_flush_cache_shutdown_event(pci_dev); + pqi_flush_cache(ctrl_info, shutdown_event); + } - pci_save_state(pci_dev); - pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); + pqi_stop_heartbeat_timer(ctrl_info); + pqi_crash_if_pending_command(ctrl_info); + pqi_free_irqs(ctrl_info); ctrl_info->controller_online = false; ctrl_info->pqi_mode_enabled = false; @@ -8875,44 +9004,89 @@ static __maybe_unused int pqi_suspend(struct pci_dev *pci_dev, pm_message_t stat return 0; } -static __maybe_unused int pqi_resume(struct pci_dev *pci_dev) +static __maybe_unused int pqi_suspend(struct device *dev) +{ + return pqi_suspend_or_freeze(dev, true); +} + +static int pqi_resume_or_restore(struct device *dev) { int rc; + struct pci_dev *pci_dev; struct pqi_ctrl_info *ctrl_info; + pci_dev = to_pci_dev(dev); ctrl_info = pci_get_drvdata(pci_dev); - if (pci_dev->current_state != PCI_D0) { - ctrl_info->max_hw_queue_index = 0; - pqi_free_interrupts(ctrl_info); - pqi_change_irq_mode(ctrl_info, IRQ_MODE_INTX); - rc = request_irq(pci_irq_vector(pci_dev, 0), pqi_irq_handler, - IRQF_SHARED, DRIVER_NAME_SHORT, - &ctrl_info->queue_groups[0]); - if (rc) { - dev_err(&ctrl_info->pci_dev->dev, - "irq %u init failed with error %d\n", - pci_dev->irq, rc); - return rc; - } - pqi_ctrl_unblock_device_reset(ctrl_info); - pqi_ctrl_unblock_requests(ctrl_info); - pqi_scsi_unblock_requests(ctrl_info); - pqi_ctrl_unblock_scan(ctrl_info); - return 0; - } - - pci_set_power_state(pci_dev, PCI_D0); - pci_restore_state(pci_dev); + rc = pqi_request_irqs(ctrl_info); + if (rc) + return rc; pqi_ctrl_unblock_device_reset(ctrl_info); pqi_ctrl_unblock_requests(ctrl_info); pqi_scsi_unblock_requests(ctrl_info); pqi_ctrl_unblock_scan(ctrl_info); + ssleep(PQI_POST_RESET_DELAY_SECS); + return pqi_ctrl_init_resume(ctrl_info); } +static int pqi_freeze(struct device *dev) +{ + return pqi_suspend_or_freeze(dev, false); +} + +static int pqi_thaw(struct device *dev) +{ + int rc; + struct pci_dev *pci_dev; + struct pqi_ctrl_info *ctrl_info; + + pci_dev = to_pci_dev(dev); + ctrl_info = pci_get_drvdata(pci_dev); + + rc = pqi_request_irqs(ctrl_info); + if (rc) + return rc; + + ctrl_info->controller_online = true; + ctrl_info->pqi_mode_enabled = true; + + pqi_ctrl_unblock_device_reset(ctrl_info); + pqi_ctrl_unblock_requests(ctrl_info); + pqi_scsi_unblock_requests(ctrl_info); + pqi_ctrl_unblock_scan(ctrl_info); + + return 0; +} + +static int pqi_poweroff(struct device *dev) +{ + struct pci_dev *pci_dev; + struct pqi_ctrl_info *ctrl_info; + enum bmic_flush_cache_shutdown_event shutdown_event; + + pci_dev = to_pci_dev(dev); + ctrl_info = pci_get_drvdata(pci_dev); + + shutdown_event = pqi_get_flush_cache_shutdown_event(pci_dev); + pqi_flush_cache(ctrl_info, shutdown_event); + + return 0; +} + +static const struct dev_pm_ops pqi_pm_ops = { + .suspend = pqi_suspend, + .resume = pqi_resume_or_restore, + .freeze = pqi_freeze, + .thaw = pqi_thaw, + .poweroff = pqi_poweroff, + .restore = pqi_resume_or_restore, +}; + +#endif /* CONFIG_PM */ + /* Define the PCI IDs for the controllers that we support. */ static const struct pci_device_id pqi_pci_id_table[] = { { @@ -8945,10 +9119,6 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, - 0x193d, 0x8460) - }, - { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x193d, 0x1104) }, { @@ -9045,6 +9215,34 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x006b) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x006c) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x006d) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x006f) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0070) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0071) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0072) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x19e5, 0xd227) }, { @@ -9201,6 +9399,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1304) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1380) }, { @@ -9261,6 +9463,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1463) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1470) }, { @@ -9273,6 +9479,14 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1473) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1474) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1480) }, { @@ -9297,6 +9511,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14a4) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14a5) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14a6) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x14b0) }, { @@ -9313,6 +9539,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14c2) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x14d0) }, { @@ -9417,6 +9647,22 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1590, 0x036f) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1590, 0x0381) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1590, 0x0382) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1590, 0x0383) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1d8d, 0x0800) }, { @@ -9441,6 +9687,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f0c, 0x3161) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x5445) }, { @@ -9453,6 +9703,30 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x5449) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x544a) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x544b) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x544d) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x544e) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x544f) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x0b27) }, { @@ -9479,8 +9753,9 @@ static struct pci_driver pqi_pci_driver = { .remove = pqi_pci_remove, .shutdown = pqi_shutdown, #if defined(CONFIG_PM) - .suspend = pqi_suspend, - .resume = pqi_resume, + .driver = { + .pm = &pqi_pm_ops + }, #endif }; @@ -9489,6 +9764,8 @@ static int __init pqi_init(void) int rc; pr_info(DRIVER_NAME "\n"); + pqi_verify_structures(); + sis_verify_structures(); pqi_sas_transport_template = sas_attach_transport(&pqi_sas_transport_functions); if (!pqi_sas_transport_template) @@ -9512,7 +9789,7 @@ static void __exit pqi_cleanup(void) module_init(pqi_init); module_exit(pqi_cleanup); -static void __attribute__((unused)) verify_structures(void) +static void pqi_verify_structures(void) { BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, sis_host_to_ctrl_doorbell) != 0x20); |