diff options
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/host.c | 17 | ||||
-rw-r--r-- | drivers/scsi/isci/host.h | 19 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 24 | ||||
-rw-r--r-- | drivers/scsi/isci/phy.c | 171 | ||||
-rw-r--r-- | drivers/scsi/isci/phy.h | 155 | ||||
-rw-r--r-- | drivers/scsi/isci/port.c | 263 | ||||
-rw-r--r-- | drivers/scsi/isci/port.h | 114 | ||||
-rw-r--r-- | drivers/scsi/isci/registers.h | 27 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 82 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 212 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.c | 19 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.h | 97 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 370 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 228 | ||||
-rw-r--r-- | drivers/scsi/isci/scu_task_context.h | 55 | ||||
-rw-r--r-- | drivers/scsi/isci/task.c | 158 | ||||
-rw-r--r-- | drivers/scsi/isci/task.h | 40 |
17 files changed, 911 insertions, 1140 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 6ca9b26bb2f..d4bf9c12ecd 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -649,15 +649,13 @@ static void isci_host_start_complete(struct isci_host *ihost, enum sci_status co int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) { - struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); + struct isci_host *ihost = ha->lldd_ha; if (test_bit(IHOST_START_PENDING, &ihost->flags)) return 0; - /* todo: use sas_flush_discovery once it is upstream */ - scsi_flush_work(shost); - - scsi_flush_work(shost); + sas_drain_work(ha); dev_dbg(&ihost->pdev->dev, "%s: ihost->status = %d, time = %ld\n", @@ -1490,6 +1488,15 @@ sci_controller_set_interrupt_coalescence(struct isci_host *ihost, static void sci_controller_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); + u32 val; + + /* enable clock gating for power control of the scu unit */ + val = readl(&ihost->smu_registers->clock_gating_control); + val &= ~(SMU_CGUCR_GEN_BIT(REGCLK_ENABLE) | + SMU_CGUCR_GEN_BIT(TXCLK_ENABLE) | + SMU_CGUCR_GEN_BIT(XCLK_ENABLE)); + val |= SMU_CGUCR_GEN_BIT(IDLE_ENABLE); + writel(val, &ihost->smu_registers->clock_gating_control); /* set the default interrupt coalescence number and timeout value. */ sci_controller_set_interrupt_coalescence(ihost, 0, 0); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 5477f0fa823..adbad69d106 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -187,6 +187,7 @@ struct isci_host { int id; /* unique within a given pci device */ struct isci_phy phys[SCI_MAX_PHYS]; struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ + struct asd_sas_port sas_ports[SCI_MAX_PORTS]; struct sas_ha_struct sas_ha; spinlock_t state_lock; @@ -393,24 +394,6 @@ static inline int sci_remote_device_node_count(struct isci_remote_device *idev) #define sci_controller_clear_invalid_phy(controller, phy) \ ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) -static inline struct device *sciphy_to_dev(struct isci_phy *iphy) -{ - - if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) - return NULL; - - return &iphy->isci_port->isci_host->pdev->dev; -} - -static inline struct device *sciport_to_dev(struct isci_port *iport) -{ - - if (!iport || !iport->isci_host) - return NULL; - - return &iport->isci_host->pdev->dev; -} - static inline struct device *scirdev_to_dev(struct isci_remote_device *idev) { if (!idev || !idev->isci_port || !idev->isci_port->isci_host) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 17c4c2c89c2..5137db5a5d8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -60,6 +60,7 @@ #include <linux/efi.h> #include <asm/string.h> #include <scsi/scsi_host.h> +#include "host.h" #include "isci.h" #include "task.h" #include "probe_roms.h" @@ -154,7 +155,6 @@ static struct scsi_host_template isci_sht = { .queuecommand = sas_queuecommand, .target_alloc = sas_target_alloc, .slave_configure = sas_slave_configure, - .slave_destroy = sas_slave_destroy, .scan_finished = isci_host_scan_finished, .scan_start = isci_host_scan_start, .change_queue_depth = sas_change_queue_depth, @@ -166,9 +166,6 @@ static struct scsi_host_template isci_sht = { .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, - .eh_device_reset_handler = sas_eh_device_reset_handler, - .eh_bus_reset_handler = isci_bus_reset_handler, - .slave_alloc = sas_slave_alloc, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, .shost_attrs = isci_host_attrs, @@ -194,6 +191,9 @@ static struct sas_domain_function_template isci_transport_ops = { .lldd_lu_reset = isci_task_lu_reset, .lldd_query_task = isci_task_query_task, + /* ata recovery called from ata-eh */ + .lldd_ata_check_ready = isci_ata_check_ready, + /* Port and Adapter management */ .lldd_clear_nexus_port = isci_task_clear_nexus_port, .lldd_clear_nexus_ha = isci_task_clear_nexus_ha, @@ -242,18 +242,13 @@ static int isci_register_sas_ha(struct isci_host *isci_host) if (!sas_ports) return -ENOMEM; - /*----------------- Libsas Initialization Stuff---------------------- - * Set various fields in the sas_ha struct: - */ - sas_ha->sas_ha_name = DRV_NAME; sas_ha->lldd_module = THIS_MODULE; sas_ha->sas_addr = &isci_host->phys[0].sas_addr[0]; - /* set the array of phy and port structs. */ for (i = 0; i < SCI_MAX_PHYS; i++) { sas_phys[i] = &isci_host->phys[i].sas_phy; - sas_ports[i] = &isci_host->ports[i].sas_port; + sas_ports[i] = &isci_host->sas_ports[i]; } sas_ha->sas_phy = sas_phys; @@ -528,6 +523,13 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic goto err_host_alloc; } pci_info->hosts[i] = h; + + /* turn on DIF support */ + scsi_host_set_prot(h->shost, + SHOST_DIF_TYPE1_PROTECTION | + SHOST_DIF_TYPE2_PROTECTION | + SHOST_DIF_TYPE3_PROTECTION); + scsi_host_set_guard(h->shost, SHOST_DIX_GUARD_CRC); } err = isci_setup_interrupts(pdev); @@ -551,9 +553,9 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) int i; for_each_isci_host(i, ihost, pdev) { + wait_for_start(ihost); isci_unregister(ihost); isci_host_deinit(ihost); - sci_controller_disable_interrupts(ihost); } } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index fe18acfd6eb..fab3586840b 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -59,6 +59,16 @@ #include "scu_event_codes.h" #include "probe_roms.h" +#undef C +#define C(a) (#a) +static const char *phy_state_name(enum sci_phy_states state) +{ + static const char * const strings[] = PHY_STATES; + + return strings[state]; +} +#undef C + /* Maximum arbitration wait time in micro-seconds */ #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) @@ -67,6 +77,19 @@ enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy) return iphy->max_negotiated_speed; } +static struct isci_host *phy_to_host(struct isci_phy *iphy) +{ + struct isci_phy *table = iphy - iphy->phy_index; + struct isci_host *ihost = container_of(table, typeof(*ihost), phys[0]); + + return ihost; +} + +static struct device *sciphy_to_dev(struct isci_phy *iphy) +{ + return &phy_to_host(iphy)->pdev->dev; +} + static enum sci_status sci_phy_transport_layer_initialization(struct isci_phy *iphy, struct scu_transport_layer_registers __iomem *reg) @@ -446,8 +469,8 @@ enum sci_status sci_phy_start(struct isci_phy *iphy) enum sci_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_STOPPED) { - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -472,8 +495,8 @@ enum sci_status sci_phy_stop(struct isci_phy *iphy) case SCI_PHY_READY: break; default: - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -486,8 +509,8 @@ enum sci_status sci_phy_reset(struct isci_phy *iphy) enum sci_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_READY) { - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -536,8 +559,8 @@ enum sci_status sci_phy_consume_power_handler(struct isci_phy *iphy) return SCI_SUCCESS; } default: - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -591,6 +614,60 @@ static void sci_phy_complete_link_training(struct isci_phy *iphy, sci_change_state(&iphy->sm, next_state); } +static const char *phy_event_name(u32 event_code) +{ + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_PORT_SELECTOR_DETECTED: + return "port selector"; + case SCU_EVENT_SENT_PORT_SELECTION: + return "port selection"; + case SCU_EVENT_HARD_RESET_TRANSMITTED: + return "tx hard reset"; + case SCU_EVENT_HARD_RESET_RECEIVED: + return "rx hard reset"; + case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: + return "identify timeout"; + case SCU_EVENT_LINK_FAILURE: + return "link fail"; + case SCU_EVENT_SATA_SPINUP_HOLD: + return "sata spinup hold"; + case SCU_EVENT_SAS_15_SSC: + case SCU_EVENT_SAS_15: + return "sas 1.5"; + case SCU_EVENT_SAS_30_SSC: + case SCU_EVENT_SAS_30: + return "sas 3.0"; + case SCU_EVENT_SAS_60_SSC: + case SCU_EVENT_SAS_60: + return "sas 6.0"; + case SCU_EVENT_SATA_15_SSC: + case SCU_EVENT_SATA_15: + return "sata 1.5"; + case SCU_EVENT_SATA_30_SSC: + case SCU_EVENT_SATA_30: + return "sata 3.0"; + case SCU_EVENT_SATA_60_SSC: + case SCU_EVENT_SATA_60: + return "sata 6.0"; + case SCU_EVENT_SAS_PHY_DETECTED: + return "sas detect"; + case SCU_EVENT_SATA_PHY_DETECTED: + return "sata detect"; + default: + return "unknown"; + } +} + +#define phy_event_dbg(iphy, state, code) \ + dev_dbg(sciphy_to_dev(iphy), "phy-%d:%d: %s event: %s (%x)\n", \ + phy_to_host(iphy)->id, iphy->phy_index, \ + phy_state_name(state), phy_event_name(code), code) + +#define phy_event_warn(iphy, state, code) \ + dev_warn(sciphy_to_dev(iphy), "phy-%d:%d: %s event: %s (%x)\n", \ + phy_to_host(iphy)->id, iphy->phy_index, \ + phy_state_name(state), phy_event_name(code), code) + enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) { enum sci_phy_states state = iphy->sm.current_state_id; @@ -607,11 +684,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) iphy->is_in_link_training = true; break; default: - dev_dbg(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); + phy_event_dbg(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -648,11 +721,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; break; } @@ -677,10 +746,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, event_code); + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -691,11 +757,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received unexpected " - "event_code %x\n", - __func__, - event_code); + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -719,11 +781,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -751,12 +809,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_phy_start_sas_link_training(iphy); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -793,11 +846,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_phy_start_sas_link_training(iphy); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } @@ -815,12 +864,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE; } return SCI_SUCCESS; @@ -838,10 +882,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) iphy->bcn_received_while_port_unassigned = true; break; default: - dev_warn(sciphy_to_dev(iphy), - "%sP SCIC PHY 0x%p ready state machine received " - "unexpected event_code %x\n", - __func__, iphy, event_code); + phy_event_warn(iphy, state, event_code); return SCI_FAILURE_INVALID_STATE; } return SCI_SUCCESS; @@ -852,18 +893,14 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(iphy), - "%s: SCIC PHY 0x%p resetting state machine received " - "unexpected event_code %x\n", - __func__, iphy, event_code); - + phy_event_warn(iphy, state, event_code); return SCI_FAILURE_INVALID_STATE; break; } return SCI_SUCCESS; default: - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -956,8 +993,8 @@ enum sci_status sci_phy_frame_handler(struct isci_phy *iphy, u32 frame_index) return result; } default: - dev_dbg(sciphy_to_dev(iphy), - "%s: in wrong state: %d\n", __func__, state); + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n", + __func__, phy_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -1299,7 +1336,6 @@ void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) sas_addr = cpu_to_be64(sci_sas_addr); memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr)); - iphy->isci_port = NULL; iphy->sas_phy.enabled = 0; iphy->sas_phy.id = index; iphy->sas_phy.sas_addr = &iphy->sas_addr[0]; @@ -1333,13 +1369,13 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, { int ret = 0; struct isci_phy *iphy = sas_phy->lldd_phy; - struct isci_port *iport = iphy->isci_port; + struct asd_sas_port *port = sas_phy->port; struct isci_host *ihost = sas_phy->ha->lldd_ha; unsigned long flags; dev_dbg(&ihost->pdev->dev, "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", - __func__, sas_phy, func, buf, iphy, iport); + __func__, sas_phy, func, buf, iphy, port); switch (func) { case PHY_FUNC_DISABLE: @@ -1356,11 +1392,10 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, break; case PHY_FUNC_HARD_RESET: - if (!iport) + if (!port) return -ENODEV; - /* Perform the port reset. */ - ret = isci_port_perform_hard_reset(ihost, iport, iphy); + ret = isci_port_perform_hard_reset(ihost, port->lldd_port, iphy); break; case PHY_FUNC_GET_EVENTS: { diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 67699c8e321..0e45833ba06 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -103,7 +103,6 @@ struct isci_phy { struct scu_transport_layer_registers __iomem *transport_layer_registers; struct scu_link_layer_registers __iomem *link_layer_registers; struct asd_sas_phy sas_phy; - struct isci_port *isci_port; u8 sas_addr[SAS_ADDR_SIZE]; union { struct sas_identify_frame iaf; @@ -344,101 +343,65 @@ enum sci_phy_counter_id { SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR }; -enum sci_phy_states { - /** - * Simply the initial state for the base domain state machine. - */ - SCI_PHY_INITIAL, - - /** - * This state indicates that the phy has successfully been stopped. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the INITIAL state. - * This state is entered from the STARTING state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_PHY_STOPPED, - - /** - * This state indicates that the phy is in the process of becomming - * ready. In this state no new IO operations are permitted on this phy. - * This state is entered from the STOPPED state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_PHY_STARTING, - - /** - * Initial state - */ - SCI_PHY_SUB_INITIAL, - - /** - * Wait state for the hardware OSSP event type notification - */ - SCI_PHY_SUB_AWAIT_OSSP_EN, - - /** - * Wait state for the PHY speed notification - */ - SCI_PHY_SUB_AWAIT_SAS_SPEED_EN, - - /** - * Wait state for the IAF Unsolicited frame notification - */ - SCI_PHY_SUB_AWAIT_IAF_UF, - - /** - * Wait state for the request to consume power - */ - SCI_PHY_SUB_AWAIT_SAS_POWER, - - /** - * Wait state for request to consume power - */ - SCI_PHY_SUB_AWAIT_SATA_POWER, - - /** - * Wait state for the SATA PHY notification - */ - SCI_PHY_SUB_AWAIT_SATA_PHY_EN, - - /** - * Wait for the SATA PHY speed notification - */ - SCI_PHY_SUB_AWAIT_SATA_SPEED_EN, - - /** - * Wait state for the SIGNATURE FIS unsolicited frame notification - */ - SCI_PHY_SUB_AWAIT_SIG_FIS_UF, - - /** - * Exit state for this state machine - */ - SCI_PHY_SUB_FINAL, - - /** - * This state indicates the the phy is now ready. Thus, the user - * is able to perform IO operations utilizing this phy as long as it - * is currently part of a valid port. - * This state is entered from the STARTING state. - */ - SCI_PHY_READY, - - /** - * This state indicates that the phy is in the process of being reset. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the READY state. - */ - SCI_PHY_RESETTING, - - /** - * Simply the final state for the base phy state machine. - */ - SCI_PHY_FINAL, -}; +/** + * enum sci_phy_states - phy state machine states + * @SCI_PHY_INITIAL: Simply the initial state for the base domain state + * machine. + * @SCI_PHY_STOPPED: phy has successfully been stopped. In this state + * no new IO operations are permitted on this phy. + * @SCI_PHY_STARTING: the phy is in the process of becomming ready. In + * this state no new IO operations are permitted on + * this phy. + * @SCI_PHY_SUB_INITIAL: Initial state + * @SCI_PHY_SUB_AWAIT_OSSP_EN: Wait state for the hardware OSSP event + * type notification + * @SCI_PHY_SUB_AWAIT_SAS_SPEED_EN: Wait state for the PHY speed + * notification + * @SCI_PHY_SUB_AWAIT_IAF_UF: Wait state for the IAF Unsolicited frame + * notification + * @SCI_PHY_SUB_AWAIT_SAS_POWER: Wait state for the request to consume + * power + * @SCI_PHY_SUB_AWAIT_SATA_POWER: Wait state for request to consume + * power + * @SCI_PHY_SUB_AWAIT_SATA_PHY_EN: Wait state for the SATA PHY + * notification + * @SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: Wait for the SATA PHY speed + * notification + * @SCI_PHY_SUB_AWAIT_SIG_FIS_UF: Wait state for the SIGNATURE FIS + * unsolicited frame notification + * @SCI_PHY_SUB_FINAL: Exit state for this state machine + * @SCI_PHY_READY: phy is now ready. Thus, the user is able to perform + * IO operations utilizing this phy as long as it is + * currently part of a valid port. This state is + * entered from the STARTING state. + * @SCI_PHY_RESETTING: phy is in the process of being reset. In this + * state no new IO operations are permitted on this + * phy. This state is entered from the READY state. + * @SCI_PHY_FINAL: Simply the final state for the base phy state + * machine. + */ +#define PHY_STATES {\ + C(PHY_INITIAL),\ + C(PHY_STOPPED),\ + C(PHY_STARTING),\ + C(PHY_SUB_INITIAL),\ + C(PHY_SUB_AWAIT_OSSP_EN),\ + C(PHY_SUB_AWAIT_SAS_SPEED_EN),\ + C(PHY_SUB_AWAIT_IAF_UF),\ + C(PHY_SUB_AWAIT_SAS_POWER),\ + C(PHY_SUB_AWAIT_SATA_POWER),\ + C(PHY_SUB_AWAIT_SATA_PHY_EN),\ + C(PHY_SUB_AWAIT_SATA_SPEED_EN),\ + C(PHY_SUB_AWAIT_SIG_FIS_UF),\ + C(PHY_SUB_FINAL),\ + C(PHY_READY),\ + C(PHY_RESETTING),\ + C(PHY_FINAL),\ + } +#undef C +#define C(a) SCI_##a +enum sci_phy_states PHY_STATES; +#undef C void sci_phy_construct( struct isci_phy *iphy, diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 7c6ac58a5c4..5fada73b71f 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -60,18 +60,29 @@ #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) -static void isci_port_change_state(struct isci_port *iport, enum isci_status status) +#undef C +#define C(a) (#a) +const char *port_state_name(enum sci_port_states state) { - unsigned long flags; + static const char * const strings[] = PORT_STATES; + + return strings[state]; +} +#undef C + +static struct device *sciport_to_dev(struct isci_port *iport) +{ + int i = iport->physical_port_index; + struct isci_port *table; + struct isci_host *ihost; + + if (i == SCIC_SDS_DUMMY_PORT) + i = SCI_MAX_PORTS+1; - dev_dbg(&iport->isci_host->pdev->dev, - "%s: iport = %p, state = 0x%x\n", - __func__, iport, status); + table = iport - i; + ihost = container_of(table, typeof(*ihost), ports[0]); - /* XXX pointless lock */ - spin_lock_irqsave(&iport->state_lock, flags); - iport->status = status; - spin_unlock_irqrestore(&iport->state_lock, flags); + return &ihost->pdev->dev; } static void sci_port_get_protocols(struct isci_port *iport, struct sci_phy_proto *proto) @@ -165,18 +176,12 @@ static void isci_port_link_up(struct isci_host *isci_host, struct sci_port_properties properties; unsigned long success = true; - BUG_ON(iphy->isci_port != NULL); - - iphy->isci_port = iport; - dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, iport); spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); - isci_port_change_state(iphy->isci_port, isci_starting); - sci_port_get_properties(iport, &properties); if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { @@ -258,7 +263,6 @@ static void isci_port_link_down(struct isci_host *isci_host, __func__, isci_device); set_bit(IDEV_GONE, &isci_device->flags); } - isci_port_change_state(isci_port, isci_stopping); } } @@ -269,52 +273,10 @@ static void isci_port_link_down(struct isci_host *isci_host, isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, PHYE_LOSS_OF_SIGNAL); - isci_phy->isci_port = NULL; - dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p - Done\n", __func__, isci_port); } - -/** - * isci_port_ready() - This function is called by the sci core when a link - * becomes ready. - * @isci_host: This parameter specifies the isci host object. - * @port: This parameter specifies the sci port with the active link. - * - */ -static void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port) -{ - dev_dbg(&isci_host->pdev->dev, - "%s: isci_port = %p\n", __func__, isci_port); - - complete_all(&isci_port->start_complete); - isci_port_change_state(isci_port, isci_ready); - return; -} - -/** - * isci_port_not_ready() - This function is called by the sci core when a link - * is not ready. All remote devices on this link will be removed if they are - * in the stopping state. - * @isci_host: This parameter specifies the isci host object. - * @port: This parameter specifies the sci port with the active link. - * - */ -static void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_port) -{ - dev_dbg(&isci_host->pdev->dev, - "%s: isci_port = %p\n", __func__, isci_port); -} - -static void isci_port_stop_complete(struct isci_host *ihost, - struct isci_port *iport, - enum sci_status completion_status) -{ - dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); -} - - static bool is_port_ready_state(enum sci_port_states state) { switch (state) { @@ -353,7 +315,9 @@ static void port_state_machine_change(struct isci_port *iport, static void isci_port_hard_reset_complete(struct isci_port *isci_port, enum sci_status completion_status) { - dev_dbg(&isci_port->isci_host->pdev->dev, + struct isci_host *ihost = isci_port->owning_controller; + + dev_dbg(&ihost->pdev->dev, "%s: isci_port = %p, completion_status=%x\n", __func__, isci_port, completion_status); @@ -364,23 +328,24 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port, /* The reset failed. The port state is now SCI_PORT_FAILED. */ if (isci_port->active_phy_mask == 0) { + int phy_idx = isci_port->last_active_phy; + struct isci_phy *iphy = &ihost->phys[phy_idx]; /* Generate the link down now to the host, since it * was intercepted by the hard reset state machine when * it really happened. */ - isci_port_link_down(isci_port->isci_host, - &isci_port->isci_host->phys[ - isci_port->last_active_phy], - isci_port); + isci_port_link_down(ihost, iphy, isci_port); } /* Advance the port state so that link state changes will be - * noticed. - */ + * noticed. + */ port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING); } - complete_all(&isci_port->hard_reset_complete); + clear_bit(IPORT_RESET_PENDING, &isci_port->state); + wake_up(&ihost->eventq); + } /* This method will return a true value if the specified phy can be assigned to @@ -835,10 +800,9 @@ static void port_timeout(unsigned long data) __func__, iport); } else if (current_state == SCI_PORT_STOPPING) { - /* if the port is still stopping then the stop has not completed */ - isci_port_stop_complete(iport->owning_controller, - iport, - SCI_FAILURE_TIMEOUT); + dev_dbg(sciport_to_dev(iport), + "%s: port%d: stop complete timeout\n", + __func__, iport->physical_port_index); } else { /* The port is in the ready state and we have a timer * reporting a timeout this should not happen. @@ -1003,7 +967,8 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach struct isci_port *iport = container_of(sm, typeof(*iport), sm); struct isci_host *ihost = iport->owning_controller; - isci_port_ready(ihost, iport); + dev_dbg(&ihost->pdev->dev, "%s: port%d ready\n", + __func__, iport->physical_port_index); for (index = 0; index < SCI_MAX_PHYS; index++) { if (iport->phy_table[index]) { @@ -1069,7 +1034,8 @@ static void sci_port_ready_substate_operational_exit(struct sci_base_state_machi */ sci_port_abort_dummy_request(iport); - isci_port_not_ready(ihost, iport); + dev_dbg(&ihost->pdev->dev, "%s: port%d !ready\n", + __func__, iport->physical_port_index); if (iport->ready_exit) sci_port_invalidate_dummy_remote_node(iport); @@ -1081,7 +1047,8 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach struct isci_host *ihost = iport->owning_controller; if (iport->active_phy_mask == 0) { - isci_port_not_ready(ihost, iport); + dev_dbg(&ihost->pdev->dev, "%s: port%d !ready\n", + __func__, iport->physical_port_index); port_state_machine_change(iport, SCI_PORT_SUB_WAITING); } else @@ -1097,8 +1064,8 @@ enum sci_status sci_port_start(struct isci_port *iport) state = iport->sm.current_state_id; if (state != SCI_PORT_STOPPED) { - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -1172,8 +1139,8 @@ enum sci_status sci_port_stop(struct isci_port *iport) SCI_PORT_STOPPING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -1187,8 +1154,8 @@ static enum sci_status sci_port_hard_reset(struct isci_port *iport, u32 timeout) state = iport->sm.current_state_id; if (state != SCI_PORT_SUB_OPERATIONAL) { - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } @@ -1282,8 +1249,8 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -1332,8 +1299,8 @@ enum sci_status sci_port_remove_phy(struct isci_port *iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -1375,8 +1342,8 @@ enum sci_status sci_port_link_up(struct isci_port *iport, sci_port_general_link_up_handler(iport, iphy, PF_RESUME); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); return SCI_FAILURE_INVALID_STATE; } } @@ -1405,8 +1372,8 @@ enum sci_status sci_port_link_down(struct isci_port *iport, sci_port_deactivate_phy(iport, iphy, false); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(iport), - "%s: in wrong state: %d\n", __func__, state); + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n", + __func__, port_state_name(state)); |