cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sas_phy.c (4189B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Serial Attached SCSI (SAS) Phy class
      4 *
      5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
      6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
      7 */
      8
      9#include "sas_internal.h"
     10#include <scsi/scsi_host.h>
     11#include <scsi/scsi_transport.h>
     12#include <scsi/scsi_transport_sas.h>
     13#include "scsi_sas_internal.h"
     14
     15/* ---------- Phy events ---------- */
     16
     17static void sas_phye_loss_of_signal(struct work_struct *work)
     18{
     19	struct asd_sas_event *ev = to_asd_sas_event(work);
     20	struct asd_sas_phy *phy = ev->phy;
     21
     22	phy->error = 0;
     23	sas_deform_port(phy, 1);
     24}
     25
     26static void sas_phye_oob_done(struct work_struct *work)
     27{
     28	struct asd_sas_event *ev = to_asd_sas_event(work);
     29	struct asd_sas_phy *phy = ev->phy;
     30
     31	phy->error = 0;
     32}
     33
     34static void sas_phye_oob_error(struct work_struct *work)
     35{
     36	struct asd_sas_event *ev = to_asd_sas_event(work);
     37	struct asd_sas_phy *phy = ev->phy;
     38	struct sas_ha_struct *sas_ha = phy->ha;
     39	struct asd_sas_port *port = phy->port;
     40	struct sas_internal *i =
     41		to_sas_internal(sas_ha->core.shost->transportt);
     42
     43	sas_deform_port(phy, 1);
     44
     45	if (!port && phy->enabled && i->dft->lldd_control_phy) {
     46		phy->error++;
     47		switch (phy->error) {
     48		case 1:
     49		case 2:
     50			i->dft->lldd_control_phy(phy, PHY_FUNC_HARD_RESET,
     51						 NULL);
     52			break;
     53		case 3:
     54		default:
     55			phy->error = 0;
     56			phy->enabled = 0;
     57			i->dft->lldd_control_phy(phy, PHY_FUNC_DISABLE, NULL);
     58			break;
     59		}
     60	}
     61}
     62
     63static void sas_phye_spinup_hold(struct work_struct *work)
     64{
     65	struct asd_sas_event *ev = to_asd_sas_event(work);
     66	struct asd_sas_phy *phy = ev->phy;
     67	struct sas_ha_struct *sas_ha = phy->ha;
     68	struct sas_internal *i =
     69		to_sas_internal(sas_ha->core.shost->transportt);
     70
     71	phy->error = 0;
     72	i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL);
     73}
     74
     75static void sas_phye_resume_timeout(struct work_struct *work)
     76{
     77	struct asd_sas_event *ev = to_asd_sas_event(work);
     78	struct asd_sas_phy *phy = ev->phy;
     79
     80	/* phew, lldd got the phy back in the nick of time */
     81	if (!phy->suspended) {
     82		dev_info(&phy->phy->dev, "resume timeout cancelled\n");
     83		return;
     84	}
     85
     86	phy->error = 0;
     87	phy->suspended = 0;
     88	sas_deform_port(phy, 1);
     89}
     90
     91
     92static void sas_phye_shutdown(struct work_struct *work)
     93{
     94	struct asd_sas_event *ev = to_asd_sas_event(work);
     95	struct asd_sas_phy *phy = ev->phy;
     96	struct sas_ha_struct *sas_ha = phy->ha;
     97	struct sas_internal *i =
     98		to_sas_internal(sas_ha->core.shost->transportt);
     99
    100	if (phy->enabled) {
    101		int ret;
    102
    103		phy->error = 0;
    104		phy->enabled = 0;
    105		ret = i->dft->lldd_control_phy(phy, PHY_FUNC_DISABLE, NULL);
    106		if (ret)
    107			pr_notice("lldd disable phy%d returned %d\n", phy->id,
    108				  ret);
    109	} else
    110		pr_notice("phy%d is not enabled, cannot shutdown\n", phy->id);
    111	phy->in_shutdown = 0;
    112}
    113
    114/* ---------- Phy class registration ---------- */
    115
    116int sas_register_phys(struct sas_ha_struct *sas_ha)
    117{
    118	int i;
    119
    120	/* Now register the phys. */
    121	for (i = 0; i < sas_ha->num_phys; i++) {
    122		struct asd_sas_phy *phy = sas_ha->sas_phy[i];
    123
    124		phy->error = 0;
    125		atomic_set(&phy->event_nr, 0);
    126		INIT_LIST_HEAD(&phy->port_phy_el);
    127
    128		phy->port = NULL;
    129		phy->ha = sas_ha;
    130		spin_lock_init(&phy->frame_rcvd_lock);
    131		spin_lock_init(&phy->sas_prim_lock);
    132		phy->frame_rcvd_size = 0;
    133
    134		phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev, i);
    135		if (!phy->phy)
    136			return -ENOMEM;
    137
    138		phy->phy->identify.initiator_port_protocols =
    139			phy->iproto;
    140		phy->phy->identify.target_port_protocols = phy->tproto;
    141		phy->phy->identify.sas_address = SAS_ADDR(sas_ha->sas_addr);
    142		phy->phy->identify.phy_identifier = i;
    143		phy->phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
    144		phy->phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
    145		phy->phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN;
    146		phy->phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN;
    147		phy->phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
    148
    149		sas_phy_add(phy->phy);
    150	}
    151
    152	return 0;
    153}
    154
    155const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
    156	[PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
    157	[PHYE_OOB_DONE] = sas_phye_oob_done,
    158	[PHYE_OOB_ERROR] = sas_phye_oob_error,
    159	[PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
    160	[PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
    161	[PHYE_SHUTDOWN] = sas_phye_shutdown,
    162};