aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
AgeCommit message (Collapse)AuthorFilesLines
2021-01-22scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()Ahmed S. Darwish1-1/+2
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. libsas sas_notify_port_event() is called from isci_port_bc_change_received(). Below is the context analysis for all of its call chains: host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [1] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [2] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() [1] Call chains for entering state: *SCI_PHY_STOPPED* ----------------------------------------------------- host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED) init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED) phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED) [2] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------ phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING) host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: Enter SCI state *SCI_PHY_SUB_FINAL* # Cont. from [2A] -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING) [2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------ host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas port event notifier. Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-8-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: isci: Pass gfp_t flags in isci_port_link_up()Ahmed S. Darwish1-1/+2
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. libsas sas_notify_port_event() is called from isci_port_link_up(). Below is the context analysis for all of its call chains: host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1] -> phy.c: sci_phy_starting_final_substate_enter() -> phy.c: sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> phy.c: sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> .link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) [A] port.c: sci_port_link_up() -> sci_port_activate_phy() -> isci_port_link_up() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() [1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ----------------------------------------------------------- host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) As can be seen from the "(*)" markers above, all the call-chains are atomic. Pass GFP_ATOMIC to libsas port event notifier. Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-7-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: isci: Pass gfp_t flags in isci_port_link_down()Ahmed S. Darwish1-2/+2
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. sas_notify_phy_event() is exclusively called by isci_port_link_down(). Below is the context analysis for all of its call chains: port.c: port_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> port_state_machine_change(..., SCI_PORT_FAILED) -> enter SCI port state: *SCI_PORT_FAILED* -> sci_port_failed_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down() port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> port.c: sci_port_deactivate_phy() -> isci_port_link_down() port.c: enter SCI port state: *SCI_PORT_READY* # Cont. from [1] -> sci_port_ready_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down() phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [2] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_deactivate_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down() phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [3] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down() [1] Call chains for 'enter SCI port state: *SCI_PORT_READY*' ------------------------------------------------------------ host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> host.c: sci_controller_start(), atomic (*) -> host.c: sci_port_start() -> port.c: port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port.c: sci_apc_agent_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* phy.c: enter SCI state: SCI_PHY_SUB_FINAL # Cont. from [1A] -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> port_agent.link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* [1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------ host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) [2] Call chains for entering state: *SCI_PHY_STOPPED* ----------------------------------------------------- host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED) init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED) phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED) [3] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------ phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING) host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed (*) -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING) As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas phy event notifier. Note, The now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-6-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: mvsas: Pass gfp_t flags to libsas event notifiersAhmed S. Darwish1-9/+10
mvsas calls the non _gfp version of the libsas event notifiers API, leading to the buggy call chains below: mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation Use the new event notifiers API instead, which requires callers to explicitly pass the gfp_t memory allocation flags. Below are context analysis for the modified functions: => mvs_bytes_dmaed(): Since it is invoked from both process and atomic contexts, let its callers pass the gfp_t flags. Call chains: scsi_scan.c: do_scsi_scan_host() [has msleep()] -> shost->hostt->scan_start() -> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = mvs_scan_start()] -> mvsas/mv_sas.c: mvs_scan_start() -> mvs_bytes_dmaed(..., GFP_KERNEL) mvsas/mv_sas.c: mvs_work_queue() spin_lock_irqsave(mvs_info::lock,) -> mvs_bytes_dmaed(..., GFP_ATOMIC) mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr() -> mvsas/mv_chips.h: mvs_int_full() -> mvsas/mv_sas.c: mvs_int_port() -> mvs_bytes_dmaed(..., GFP_ATOMIC); => mvs_work_queue(): Invoked from process context, but it calls all the libsas event notifier APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC. Link: https://lore.kernel.org/r/20210118100955.1761652-5-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: libsas: Introduce a _gfp() variant of event notifiersAhmed S. Darwish3-17/+73
sas_alloc_event() uses in_interrupt() to decide which allocation should be used. The usage of in_interrupt() in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated or the context be conveyed in an argument passed by the caller, which usually knows the context. The in_interrupt() check is also only partially correct, because it fails to choose the correct code path when just preemption or interrupts are disabled. For example, as in the following call chain: mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and sas_notify_phy_event_gfp(), which all behave like the non _gfp() variants but use a caller-passed GFP mask for allocations. For bisectability, all callers will be modified first to pass GFP context, then the non _gfp() libsas API variants will be modified to take a gfp_t by default. Link: https://lore.kernel.org/r/20210118100955.1761652-4-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: libsas: Remove notifier indirectionJohn Garry13-100/+64
LLDDs report events to libsas with .notify_port_event and .notify_phy_event callbacks. These callbacks are fixed and so there is no reason why the functions cannot be called directly, so do that. This neatens the code slightly, makes it more obvious, and reduces function pointer usage, which is generally a good thing. Downside is that there are 2x more symbol exports. [a.darwish@linutronix.de: Remove the now unused "sas_ha" local variables] Link: https://lore.kernel.org/r/20210118100955.1761652-3-a.darwish@linutronix.de Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: ncr53c8xx: Use SAM status valuesHannes Reinecke2-53/+46
Use SAM status values instead of the driver-defined ones. This also fixes a potential bug as the driver-defined values declare 'COMMAND TERMINATED' with a value of 0x20, whereas SCSI-II defines it with a value of 0x22. Link: https://lore.kernel.org/r/20210113090500.129644-36-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: advansys: Kill driver-defined status byte accessorsHannes Reinecke1-60/+24
Replace the driver-defined status byte accessors with the mid-layer defined ones. Link: https://lore.kernel.org/r/20210113090500.129644-35-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: qla2xxx: fc_remote_port_chkready() returns a SCSI result valueHannes Reinecke1-1/+1
fc_remote_port_chkready() returns a SCSI result value, not the port status. Fix the value returned when the remote port isn't set. Link: https://lore.kernel.org/r/20210113090500.129644-34-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: storvsc: Return DID_ERROR for invalid commandsHannes Reinecke1-1/+1
ILLEGAL_COMMAND is a sense code, not a driver byte. Link: https://lore.kernel.org/r/20210113090500.129644-33-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: ips: Use correct command completion on errorHannes Reinecke1-2/+7
A non-zero queuecommand() return code means 'busy', i.e. the command hasn't been submitted. So any command which should be failed need to be completed via the ->scsi_done() callback with the appropriate result code set. Link: https://lore.kernel.org/r/20210113090500.129644-32-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: wd33c93: Use SCSI statusHannes Reinecke1-3/+3
Use standard SCSI status and drop usage of the linux-specific ones. Link: https://lore.kernel.org/r/20210113090500.129644-31-hare@suse.de Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: esp_scsi: Do not set SCSI message byteHannes Reinecke1-4/+1
The message byte setting always devolves to COMMAND_COMPLETE so we can drop setting the message byte in the SCSI result. Link: https://lore.kernel.org/r/20210113090500.129644-30-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: esp_scsi: Use host byte as last argument to esp_cmd_is_done()Hannes Reinecke1-14/+10
Just pass in the host byte to esp_cmd_is_done() and set the status or message bytes if the host byte is DID_OK. Link: https://lore.kernel.org/r/20210113090500.129644-29-hare@suse.de Acked-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: dpt_i2o: Use DID_ERROR instead of INITIATOR_ERROR messageHannes Reinecke1-1/+1
Change the error code for an invalid SCSI opcode to DID_ERROR. INITIATOR_ERROR is a scsi parallel message which doesn't apply for RAID HBAs. Link: https://lore.kernel.org/r/20210113090500.129644-27-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: mac53c94: Do not set invalid command resultHannes Reinecke1-1/+0
CMD_ACCEPT_MSG is an internal definition and most certainly not a SCSI status. As the latter gets set during command completion we can drop the assignment here. Link: https://lore.kernel.org/r/20210113090500.129644-26-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: atp870u: Use standard definitionsHannes Reinecke1-24/+30
Use standard definitions for SCSI commands and return status instead of the hardcoded values. Link: https://lore.kernel.org/r/20210113090500.129644-25-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: ufs: ufshcd: Do not set COMMAND_COMPLETEHannes Reinecke1-3/+1
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-24-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: scsi_debug: Do not set COMMAND_COMPLETEHannes Reinecke1-1/+1
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-23-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: initio: Drop internal SCSI message definitionHannes Reinecke2-56/+33
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-22-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: dc395x: Drop internal SCSI message definitionsHannes Reinecke3-39/+12
Drop the internal SCSI message definitions and use the functions provided by the SPI transport class. Link: https://lore.kernel.org/r/20210113090500.129644-21-hare@suse.de Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: aic7xxx: aic79xx: Drop internal SCSI message definitionHannes Reinecke5-177/+137
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-20-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: nsp_cs: Drop internal SCSI message definitionHannes Reinecke2-17/+6
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-19-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: stex: Do not set COMMAND_COMPLETEHannes Reinecke1-12/+13
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-18-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: hpsa: Do not set COMMAND_COMPLETEHannes Reinecke1-3/+1
COMMAND_COMPLETE is defined as '0', and it is a SCSI parallel message to boot. Drop the call to set_msg_byte(). Link: https://lore.kernel.org/r/20210113090500.129644-17-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Don Brace <don.brace@microchip.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: aacraid: Avoid setting message byte on completionHannes Reinecke1-109/+64
The aacraid controller is a RAID controller and the driver will never see any SCSI messages. Plus it's quite pointless to set the message byte if the host byte is already set, as the latter takes precedence during error recovery. Drop the message byte values for the final result. Link: https://lore.kernel.org/r/20210113090500.129644-16-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: qla4xxx: Use standard SAM status definitionsHannes Reinecke2-2/+1
Use standard SAM status definitions and drop the driver-defined ones. Link: https://lore.kernel.org/r/20210113090500.129644-14-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: dc395: Drop private SAM status code definitionsHannes Reinecke1-16/+0
We don't need to duplicate definitions from the common include files. Link: https://lore.kernel.org/r/20210113090500.129644-13-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: nsp32: Fixup status handlingHannes Reinecke1-1/+1
SCp.status is always the SAM-defined status value, not the Linux ones. Fixup the one wrong definition. Link: https://lore.kernel.org/r/20210113090500.129644-12-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: acornscsi: Use standard definesHannes Reinecke1-12/+2
Use midlayer-defined values and drop the non-existing QUEUE_FULL case; we are checking the SCSI messages in the switch statement, and QUEUE_FULL is a SCSI status hence it can never occur here. Link: https://lore.kernel.org/r/20210113090500.129644-11-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: bfa: Drop driver-defined SCSI status codesHannes Reinecke3-17/+2
Drop the driver-defined SCSI status codes and use the generic ones instead. Link: https://lore.kernel.org/r/20210113090500.129644-10-hare@suse.de Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: aic7xxx: aic79xx: Remove driver-defined SAM status definitionsHannes Reinecke5-36/+21
Replace the driver-defined SAM status definitions with the standard mid-layer defined ones. Link: https://lore.kernel.org/r/20210113090500.129644-9-hare@suse.de Reviewed-by: Bart van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: aic7xxx: aic79xx: Kill pointless forward declarationsHannes Reinecke2-46/+0
Link: https://lore.kernel.org/r/20210113090500.129644-8-hare@suse.de Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: aic7xxx: aic79xx: Whitespace cleanupHannes Reinecke10-209/+208
Link: https://lore.kernel.org/r/20210113090500.129644-7-hare@suse.de Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: atp870u: Whitespace cleanupHannes Reinecke2-187/+258
Link: https://lore.kernel.org/r/20210113090500.129644-6-hare@suse.de Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: 3w-sas: Whitespace cleanupHannes Reinecke2-77/+93
Link: https://lore.kernel.org/r/20210113090500.129644-5-hare@suse.de Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: 3w-9xxx: Whitespace cleanupHannes Reinecke2-99/+113
Link: https://lore.kernel.org/r/20210113090500.129644-4-hare@suse.de Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: 3w-xxxx: Whitespace cleanupHannes Reinecke2-212/+220
Link: https://lore.kernel.org/r/20210113090500.129644-3-hare@suse.de Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-22scsi: Drop gdth driverHannes Reinecke7-6174/+0
The gdth driver refers to a SCSI parallel, PCI-only HBA RAID adapter which was manufactured by the now-defunct ICP Vortex company, later acquired by Adaptec and superseded by the aacraid series of controllers. The driver itself would require a major overhaul before any modifications can be attempted, but seeing that it's unlikely to have any users left it should rather be removed completely. Link: https://lore.kernel.org/r/20210113090500.129644-2-hare@suse.de Cautiously-Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Clean up and refactor clk-scaling featureStanley Chu1-31/+32
Manipulate clock scaling related stuff only if the host capability supports clock scaling feature to avoid redundant code execution. Link: https://lore.kernel.org/r/20210120150142.5049-4-stanley.chu@mediatek.com Reviewed-by: Can Guo <cang@codeaurora.org> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Remove redundant null checking of devfreq instanceStanley Chu1-8/+7
hba->devfreq is zero-initialized thus it is not required to check its existence in ufshcd_add_lus() function which is invoked during initialization only. Link: https://lore.kernel.org/r/20210120150142.5049-3-stanley.chu@mediatek.com Reviewed-by: Can Guo <cang@codeaurora.org> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Refactor cancelling clkscaling worksStanley Chu1-11/+6
Cancelling suspend_work and resume_work is only required while suspending clk-scaling. Move these two invocations into ufshcd_suspend_clkscaling() function. Link: https://lore.kernel.org/r/20210120150142.5049-2-stanley.chu@mediatek.com Reviewed-by: Can Guo <cang@codeaurora.org> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20Revert "Make sure clk scaling happens only when HBA is runtime ACTIVE"Can Guo1-7/+0
Commit 73cc291c2702 ("scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE") is no longer needed since commit 0e9d4ca43ba8 ("scsi: ufs: Protect some contexts from unexpected clock scaling") is a more mature fix to protect UFS LLD stability from clock scaling invoked through sysfs nodes by users. Link: https://lore.kernel.org/r/1611137065-14266-4-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Can Guo <cang@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Refactor ufshcd_init/exit_clk_scaling/gating()Can Guo2-60/+74
ufshcd_hba_exit() is always called after ufshcd_exit_clk_scaling() and ufshcd_exit_clk_gating(). Move ufshcd_exit_clk_scaling/gating() to ufshcd_hba_exit(). Meanwhile, add dedicated functions to initialize and remove sysfs nodes of clock scaling/gating to make the code more readable. Overall functionality remains same. Link: https://lore.kernel.org/r/1611137065-14266-3-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Can Guo <cang@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Protect some contexts from unexpected clock scalingCan Guo2-32/+54
In contexts like suspend, shutdown, and error handling we need to suspend devfreq to make sure these contexts won't be disturbed by clock scaling. However, suspending devfreq is not enough since users can still trigger a clock scaling by manipulating the devfreq sysfs nodes like min/max_freq and governor even after devfreq is suspended. Moreover, mere suspending devfreq cannot synchroinze a clock scaling which has already been invoked through these sysfs nodes. Add one more flag in struct clk_scaling and wrap the entire func ufshcd_devfreq_scale() with the clk_scaling_lock, so that we can use this flag and clk_scaling_lock to control and synchronize clock scaling invoked through devfreq sysfs nodes. Link: https://lore.kernel.org/r/1611137065-14266-2-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Can Guo <cang@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Group UFS WB related flags in struct ufs_dev_infoBean Huo4-26/+28
UFS device-related flags should be grouped in ufs_dev_info. Move wb_enabled and wb_buf_flush_enabled out from struct ufs_hba, group them in struct ufs_dev_info, and align the names of the structure members vertically. Link: https://lore.kernel.org/r/20210119163847.20165-6-huobean@gmail.com Reviewed-by: Can Guo <cang@codeaurora.org> Acked-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Bean Huo <beanhuo@micron.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Remove two WB related fields from struct ufs_dev_infoBean Huo2-10/+6
d_wb_alloc_units and d_ext_ufs_feature_sup are only used during WB probe. They are used to confirm the condition that "if bWriteBoosterBufferType is set to 01h but dNumSharedWriteBoosterBufferAllocUnits is set to zero, the WriteBooster feature is disabled", and if UFS device supports WB. No need to keep them after probing is complete. Link: https://lore.kernel.org/r/20210119163847.20165-5-huobean@gmail.com Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Bean Huo <beanhuo@micron.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Update comment in the function ufshcd_wb_probe()Bean Huo1-4/+3
USFHCD supports both WriteBooster "LU dedicated buffer" mode and "shared buffer" mode. Update the comment accordingly in the function ufshcd_wb_probe(). Link: https://lore.kernel.org/r/20210119163847.20165-4-huobean@gmail.com Reviewed-by: Can Guo <cang@codeaurora.org> Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Bean Huo <beanhuo@micron.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: Add "wb_on" sysfs node to control WB on/offBean Huo3-2/+49
Currently UFS WriteBooster driver uses clock scaling up/down to set WB on/off. For the platforms which don't support UFSHCD_CAP_CLK_SCALING, WB will be always on. Provide a sysfs attribute to enable/disable WB during runtime. Write 1/0 to "wb_on" sysfs node to enable/disable UFS WB. Link: https://lore.kernel.org/r/20210119163847.20165-2-huobean@gmail.com Reviewed-by: Avri Altman <avri.altman@wdc.com> Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Bean Huo <beanhuo@micron.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2021-01-20scsi: ufs: ufs-exynos: Use UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZEKiwoong Kim1-1/+2
Exynos needs scatterlist entries aligned to page size because it isn't capable of transferring data contained in one DATA IN operation to seversal areas in memory. Link: https://lore.kernel.org/r/80d7e27d6ec537e650a6bd74897b6c60618efcdc.1611026909.git.kwmad.kim@samsung.com Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>