^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Aic94xx SAS/SATA driver SCB management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "aic94xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "aic94xx_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "aic94xx_hwi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "aic94xx_seq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "aic94xx_dump.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* ---------- EMPTY SCB ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DL_PHY_MASK 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define BYTES_DMAED 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PRIMITIVE_RECVD 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PHY_EVENT 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define LINK_RESET_ERROR 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define TIMER_EVENT 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define REQ_TASK_ABORT 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define REQ_DEVICE_RESET 0xF1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SIGNAL_NCQ_ERROR 0xF2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CLEAR_NCQ_ERROR 0xF3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PHY_EVENTS_STATUS (CURRENT_LOSS_OF_SIGNAL | CURRENT_OOB_DONE \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) | CURRENT_OOB_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct sas_phy *sas_phy = phy->sas_phy.phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) switch (oob_mode & 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) case PHY_SPEED_60:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* FIXME: sas transport class doesn't have this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) phy->sas_phy.linkrate = SAS_LINK_RATE_6_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case PHY_SPEED_30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) phy->sas_phy.linkrate = SAS_LINK_RATE_3_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case PHY_SPEED_15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) phy->sas_phy.linkrate = SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) sas_phy->negotiated_linkrate = phy->sas_phy.linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) sas_phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) sas_phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) sas_phy->maximum_linkrate = phy->phy_desc->max_sas_lrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) sas_phy->minimum_linkrate = phy->phy_desc->min_sas_lrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (oob_mode & SAS_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) phy->sas_phy.oob_mode = SAS_OOB_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) else if (oob_mode & SATA_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) phy->sas_phy.oob_mode = SATA_OOB_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void asd_phy_event_tasklet(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct done_list_struct *dl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct asd_ha_struct *asd_ha = ascb->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int phy_id = dl->status_block[0] & DL_PHY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct asd_phy *phy = &asd_ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u8 oob_status = dl->status_block[1] & PHY_EVENTS_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 oob_mode = dl->status_block[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch (oob_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case CURRENT_LOSS_OF_SIGNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* directly attached device was removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) sas_phy_disconnected(&phy->sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case CURRENT_OOB_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* hot plugged device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) asd_turn_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) get_lrate_mode(phy, oob_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case CURRENT_SPINUP_HOLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* hot plug SATA, no COMWAKE sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) asd_turn_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case CURRENT_GTO_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case CURRENT_OOB_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ASD_DPRINTK("phy%d error while OOB: oob status:0x%x\n", phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dl->status_block[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) sas_phy_disconnected(&phy->sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* If phys are enabled sparsely, this will do the right thing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u8 enabled_mask = asd_ha->hw_prof.enabled_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int i, k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for_each_phy(enabled_mask, enabled_mask, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (&asd_ha->phys[i] == phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * asd_get_attached_sas_addr -- extract/generate attached SAS address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @phy: pointer to asd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @sas_addr: pointer to buffer where the SAS address is to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * This function extracts the SAS address from an IDENTIFY frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * received. If OOB is SATA, then a SAS address is generated from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * HA tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (phy->sas_phy.frame_rcvd[0] == 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) && phy->sas_phy.oob_mode == SATA_OOB_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct asd_ha_struct *asd_ha = phy->sas_phy.ha->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* FIS device-to-host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u64 addr = be64_to_cpu(*(__be64 *)phy->phy_desc->sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) addr += asd_ha->hw_prof.sata_name_base + ord_phy(asd_ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *(__be64 *)sas_addr = cpu_to_be64(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct sas_identify_frame *idframe =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) (void *) phy->sas_phy.frame_rcvd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) memcpy(sas_addr, idframe->sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct asd_port *free_port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct asd_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct asd_sas_phy *sas_phy = &phy->sas_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) spin_lock_irqsave(&asd_ha->asd_ports_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!phy->asd_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) port = &asd_ha->asd_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Check for wide port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (port->num_phys > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) memcmp(port->sas_addr, sas_phy->sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) SAS_ADDR_SIZE) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) memcmp(port->attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) sas_phy->attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) SAS_ADDR_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* Find a free port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (port->num_phys == 0 && free_port == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) free_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Use a free port if this doesn't form a wide port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (i >= ASD_MAX_PHYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) port = free_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) BUG_ON(!port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) memcpy(port->sas_addr, sas_phy->sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) memcpy(port->attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sas_phy->attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) port->num_phys++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) port->phy_mask |= (1U << sas_phy->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) phy->asd_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) __func__, phy->asd_port->phy_mask, sas_phy->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) asd_update_port_links(asd_ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct asd_port *port = phy->asd_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct asd_sas_phy *sas_phy = &phy->sas_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) spin_lock_irqsave(&asd_ha->asd_ports_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) port->num_phys--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) port->phy_mask &= ~(1U << sas_phy->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) phy->asd_port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct done_list_struct *dl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int edb_id, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int edb_el = edb_id + ascb->edb_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct asd_phy *phy = &ascb->ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) size = min(size, (u16) sizeof(phy->frame_rcvd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) memcpy(phy->sas_phy.frame_rcvd, edb->vaddr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) phy->sas_phy.frame_rcvd_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) asd_dump_frame_rcvd(phy, dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) asd_form_port(ascb->ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sas_notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct done_list_struct *dl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct asd_ha_struct *asd_ha = ascb->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct asd_phy *phy = &asd_ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u8 lr_error = dl->status_block[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u8 retries_left = dl->status_block[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) switch (lr_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ASD_DPRINTK("phy%d: Receive ID timer expired\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ASD_DPRINTK("phy%d: Loss of signal\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ASD_DPRINTK("phy%d: Loss of dword sync\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ASD_DPRINTK("phy%d: Receive FIS timeout\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ASD_DPRINTK("phy%d: unknown link reset error code: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) phy_id, lr_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sas_phy_disconnected(sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) asd_deform_port(asd_ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (retries_left == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct asd_ascb *cp = asd_ascb_alloc_list(ascb->ha, &num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) asd_printk("%s: out of memory\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ASD_DPRINTK("phy%d: retries:0 performing link reset seq\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) asd_build_control_phy(cp, phy_id, ENABLE_PHY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (asd_post_ascb_list(ascb->ha, cp, 1) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) asd_ascb_free(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct done_list_struct *dl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct asd_ha_struct *asd_ha = ascb->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct asd_phy *phy = &asd_ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u8 reg = dl->status_block[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u32 cont = dl->status_block[2] << ((reg & 3)*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) reg &= ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) case LmPRMSTAT0BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) switch (cont) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case LmBROADCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case LmBROADRVCH0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case LmBROADRVCH1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case LmBROADSES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ASD_DPRINTK("phy%d: BROADCAST change received:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) phy_id, cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) sas_phy->sas_prim = ffs(cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case LmUNKNOWNP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ASD_DPRINTK("phy%d: unknown BREAK\n", phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ASD_DPRINTK("phy%d: primitive reg:0x%x, cont:0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) phy_id, reg, cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case LmPRMSTAT1BYTE0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) switch (cont) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case LmHARDRST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ASD_DPRINTK("phy%d: HARD_RESET primitive rcvd\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* The sequencer disables all phys on that port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * We have to re-enable the phys ourselves. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) asd_deform_port(asd_ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ASD_DPRINTK("phy%d: primitive reg:0x%x, cont:0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) phy_id, reg, cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ASD_DPRINTK("unknown primitive register:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dl->status_block[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * asd_invalidate_edb -- invalidate an EDB and if necessary post the ESCB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @ascb: pointer to Empty SCB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @edb_id: index [0,6] to the empty data buffer which is to be invalidated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * After an EDB has been invalidated, if all EDBs in this ESCB have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * invalidated, the ESCB is posted back to the sequencer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * Context is tasklet/IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct asd_seq_data *seq = &ascb->ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct empty_scb *escb = &ascb->scb->escb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct sg_el *eb = &escb->eb[edb_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct asd_dma_tok *edb = seq->edb_arr[ascb->edb_index + edb_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) memset(edb->vaddr, 0, ASD_EDB_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) eb->flags |= ELEMENT_NOT_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) escb->num_valid--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (escb->num_valid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* ASD_DPRINTK("reposting escb: vaddr: 0x%p, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) "dma_handle: 0x%08llx, next: 0x%08llx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) "index:%d, opcode:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ascb->dma_scb.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) (u64)ascb->dma_scb.dma_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) le64_to_cpu(ascb->scb->header.next_scb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) le16_to_cpu(ascb->scb->header.index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ascb->scb->header.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) escb->num_valid = ASD_EDBS_PER_SCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) for (i = 0; i < ASD_EDBS_PER_SCB; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) escb->eb[i].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!list_empty(&ascb->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) list_del_init(&ascb->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) i = asd_post_escb_list(ascb->ha, ascb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) asd_printk("couldn't post escb, err:%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void escb_tasklet_complete(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct done_list_struct *dl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct asd_ha_struct *asd_ha = ascb->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int edb = (dl->opcode & DL_PHY_MASK) - 1; /* [0xc1,0xc7] -> [0,6] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) u8 sb_opcode = dl->status_block[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int phy_id = sb_opcode & DL_PHY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct asd_phy *phy = &asd_ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (edb > 6 || edb < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) edb, dl->opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ASD_DPRINTK("sb_opcode : 0x%x, phy_id: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) sb_opcode, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ASD_DPRINTK("escb: vaddr: 0x%p, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) "dma_handle: 0x%llx, next: 0x%llx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) "index:%d, opcode:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ascb->dma_scb.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) (unsigned long long)ascb->dma_scb.dma_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) (unsigned long long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) le64_to_cpu(ascb->scb->header.next_scb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) le16_to_cpu(ascb->scb->header.index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ascb->scb->header.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* Catch these before we mask off the sb_opcode bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) switch (sb_opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case REQ_TASK_ABORT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct asd_ascb *a, *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u16 tc_abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct domain_device *failed_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) __func__, dl->status_block[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Find the task that caused the abort and abort it first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * The sequencer won't put anything on the done list until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * that happens.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) tc_abort = *((u16*)(&dl->status_block[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) tc_abort = le16_to_cpu(tc_abort);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct sas_task *task = a->uldd_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (a->tc_index != tc_abort)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) failed_dev = task->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sas_task_abort(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ASD_DPRINTK("R_T_A for non TASK scb 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) a->scb->header.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (!failed_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) __func__, tc_abort);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * Now abort everything else for that device (hba?) so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * that the EH will wake up and do something.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct sas_task *task = a->uldd_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (task &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) task->dev == failed_dev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) a->tc_index != tc_abort)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) sas_task_abort(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case REQ_DEVICE_RESET: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct asd_ascb *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) u16 conn_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct sas_task *last_dev_task = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) conn_handle = *((u16*)(&dl->status_block[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) conn_handle = le16_to_cpu(conn_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dl->status_block[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Find the last pending task for the device... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) u16 x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct sas_task *task = a->uldd_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dev = task->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) x = (unsigned long)dev->lldd_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (x == conn_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) last_dev_task = task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!last_dev_task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ASD_DPRINTK("%s: Device reset for idle device %d?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) __func__, conn_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* ...and set the reset flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spin_lock_irqsave(&last_dev_task->task_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* Kill all pending tasks for the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) u16 x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct sas_task *task = a->uldd_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) dev = task->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) x = (unsigned long)dev->lldd_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (x == conn_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) sas_task_abort(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case SIGNAL_NCQ_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case CLEAR_NCQ_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) sb_opcode &= ~DL_PHY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) switch (sb_opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) case BYTES_DMAED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __func__, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) asd_bytes_dmaed_tasklet(ascb, dl, edb, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case PRIMITIVE_RECVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) asd_primitive_rcvd_tasklet(ascb, dl, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case PHY_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __func__, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) asd_phy_event_tasklet(ascb, dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case LINK_RESET_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) asd_link_reset_err_tasklet(ascb, dl, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case TIMER_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ASD_DPRINTK("%s: phy%d: TIMER_EVENT, lost dw sync\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) __func__, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* the device is gone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) sas_phy_disconnected(sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) asd_deform_port(asd_ha, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) phy_id, sb_opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) edb, dl->opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ASD_DPRINTK("sb_opcode : 0x%x, phy_id: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) sb_opcode, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ASD_DPRINTK("escb: vaddr: 0x%p, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) "dma_handle: 0x%llx, next: 0x%llx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) "index:%d, opcode:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ascb->dma_scb.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) (unsigned long long)ascb->dma_scb.dma_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) (unsigned long long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) le64_to_cpu(ascb->scb->header.next_scb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) le16_to_cpu(ascb->scb->header.index),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ascb->scb->header.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) asd_invalidate_edb(ascb, edb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int asd_init_post_escbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) for (i = 0; i < seq->num_escbs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) seq->escb_arr[i]->tasklet_complete = escb_tasklet_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ASD_DPRINTK("posting %d escbs\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return asd_post_escb_list(asd_ha, seq->escb_arr[0], seq->num_escbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* ---------- CONTROL PHY ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) #define CONTROL_PHY_STATUS (CURRENT_DEVICE_PRESENT | CURRENT_OOB_DONE \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) | CURRENT_OOB_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * control_phy_tasklet_complete -- tasklet complete for CONTROL PHY ascb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * @ascb: pointer to an ascb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @dl: pointer to the done list entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * This function completes a CONTROL PHY scb and frees the ascb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * A note on LEDs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * - an LED blinks if there is IO though it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * - if a device is connected to the LED, it is lit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * - if no device is connected to the LED, is is dimmed (off).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static void control_phy_tasklet_complete(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct done_list_struct *dl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct asd_ha_struct *asd_ha = ascb->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct scb *scb = ascb->scb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct control_phy *control_phy = &scb->control_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) u8 phy_id = control_phy->phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct asd_phy *phy = &ascb->ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u8 status = dl->status_block[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) u8 oob_status = dl->status_block[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) u8 oob_mode = dl->status_block[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* u8 oob_signals= dl->status_block[3]; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ASD_DPRINTK("%s: phy%d status block opcode:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) __func__, phy_id, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) switch (control_phy->sub_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case DISABLE_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) asd_ha->hw_prof.enabled_phys &= ~(1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) asd_control_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ASD_DPRINTK("%s: disable phy%d\n", __func__, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case ENABLE_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) asd_control_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (oob_status & CURRENT_OOB_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) get_lrate_mode(phy, oob_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) asd_turn_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ASD_DPRINTK("%s: phy%d, lrate:0x%x, proto:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) __func__, phy_id,phy->sas_phy.linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) phy->sas_phy.iproto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else if (oob_status & CURRENT_SPINUP_HOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) asd_turn_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ASD_DPRINTK("%s: phy%d, spinup hold\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) } else if (oob_status & CURRENT_ERR_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ASD_DPRINTK("%s: phy%d: error: oob status:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) __func__, phy_id, oob_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) } else if (oob_status & (CURRENT_HOT_PLUG_CNCT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) | CURRENT_DEVICE_PRESENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) asd_turn_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) ASD_DPRINTK("%s: phy%d: hot plug or device present\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) __func__, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) asd_turn_led(asd_ha, phy_id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ASD_DPRINTK("%s: phy%d: no device present: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) "oob_status:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) __func__, phy_id, oob_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) case RELEASE_SPINUP_HOLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case PHY_NO_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) case EXECUTE_HARD_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) phy_id, control_phy->sub_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* XXX finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) phy_id, control_phy->sub_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) asd_ascb_free(ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* disable all speeds, then enable defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *speed_mask = SAS_SPEED_60_DIS | SAS_SPEED_30_DIS | SAS_SPEED_15_DIS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) | SATA_SPEED_30_DIS | SATA_SPEED_15_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) switch (pd->max_sas_lrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case SAS_LINK_RATE_6_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) *speed_mask &= ~SAS_SPEED_60_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) case SAS_LINK_RATE_3_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) *speed_mask &= ~SAS_SPEED_30_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case SAS_LINK_RATE_1_5_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) *speed_mask &= ~SAS_SPEED_15_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) switch (pd->min_sas_lrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) case SAS_LINK_RATE_6_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) *speed_mask |= SAS_SPEED_30_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case SAS_LINK_RATE_3_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) *speed_mask |= SAS_SPEED_15_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case SAS_LINK_RATE_1_5_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) switch (pd->max_sata_lrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) case SAS_LINK_RATE_3_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) *speed_mask &= ~SATA_SPEED_30_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case SAS_LINK_RATE_1_5_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) *speed_mask &= ~SATA_SPEED_15_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) switch (pd->min_sata_lrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) case SAS_LINK_RATE_3_0_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) *speed_mask |= SATA_SPEED_15_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case SAS_LINK_RATE_1_5_GBPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * asd_build_control_phy -- build a CONTROL PHY SCB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * @ascb: pointer to an ascb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @phy_id: phy id to control, integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * @subfunc: subfunction, what to actually to do the phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * This function builds a CONTROL PHY scb. No allocation of any kind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * is performed. @ascb is allocated with the list function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * The caller can override the ascb->tasklet_complete to point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * to its own callback function. It must call asd_ascb_free()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * at its tasklet complete function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * See the default implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct asd_phy *phy = &ascb->ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct scb *scb = ascb->scb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct control_phy *control_phy = &scb->control_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) scb->header.opcode = CONTROL_PHY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) control_phy->phy_id = (u8) phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) control_phy->sub_func = subfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) switch (subfunc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case EXECUTE_HARD_RESET: /* 0x81 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case ENABLE_PHY: /* 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* decide hot plug delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) control_phy->hot_plug_delay = HOTPLUG_DELAY_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* decide speed mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) set_speed_mask(&control_phy->speed_mask, phy->phy_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* initiator port settings are in the hi nibble */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (phy->sas_phy.role == PHY_ROLE_INITIATOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) control_phy->port_type = SAS_PROTOCOL_ALL << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) else if (phy->sas_phy.role == PHY_ROLE_TARGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) control_phy->port_type = SAS_PROTOCOL_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) control_phy->port_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) (SAS_PROTOCOL_ALL << 4) | SAS_PROTOCOL_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* link reset retries, this should be nominal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) control_phy->link_reset_retries = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case RELEASE_SPINUP_HOLD: /* 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* decide the func_mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) control_phy->func_mask = FUNCTION_MASK_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (phy->phy_desc->flags & ASD_SATA_SPINUP_HOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) control_phy->func_mask &= ~SPINUP_HOLD_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) control_phy->func_mask |= SPINUP_HOLD_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) control_phy->conn_handle = cpu_to_le16(0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) ascb->tasklet_complete = control_phy_tasklet_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* ---------- INITIATE LINK ADM TASK ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static void link_adm_tasklet_complete(struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct done_list_struct *dl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) u8 opcode = dl->opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct initiate_link_adm *link_adm = &ascb->scb->link_adm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) u8 phy_id = link_adm->phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (opcode != TC_NO_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) asd_printk("phy%d: link adm task 0x%x completed with error "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) "0x%x\n", phy_id, link_adm->sub_func, opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ASD_DPRINTK("phy%d: link adm task 0x%x: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) phy_id, link_adm->sub_func, opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) asd_ascb_free(ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) u8 subfunc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct scb *scb = ascb->scb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct initiate_link_adm *link_adm = &scb->link_adm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) scb->header.opcode = INITIATE_LINK_ADM_TASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) link_adm->phy_id = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) link_adm->sub_func = subfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) link_adm->conn_handle = cpu_to_le16(0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ascb->tasklet_complete = link_adm_tasklet_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) #endif /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* ---------- SCB timer ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * asd_ascb_timedout -- called when a pending SCB's timer has expired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @t: Timer context used to fetch the SCB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * This is the default timeout function which does the most necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * Upper layers can implement their own timeout function, say to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * resources they have with this SCB, and then call this one at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * end of their timeout function. To do this, one should initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * the ascb->timer.{function, expires} prior to calling the post
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * function. The timer is started by the post function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) void asd_ascb_timedout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) struct asd_ascb *ascb = from_timer(ascb, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct asd_seq_data *seq = &ascb->ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ASD_DPRINTK("scb:0x%x timed out\n", ascb->scb->header.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) spin_lock_irqsave(&seq->pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) seq->pending--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) list_del_init(&ascb->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) spin_unlock_irqrestore(&seq->pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) asd_ascb_free(ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* ---------- CONTROL PHY ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /* Given the spec value, return a driver value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static const int phy_func_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) [PHY_FUNC_NOP] = PHY_NO_OP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) [PHY_FUNC_LINK_RESET] = ENABLE_PHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) [PHY_FUNC_HARD_RESET] = EXECUTE_HARD_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) [PHY_FUNC_DISABLE] = DISABLE_PHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) [PHY_FUNC_RELEASE_SPINUP_HOLD] = RELEASE_SPINUP_HOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct asd_ha_struct *asd_ha = phy->ha->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct asd_phy_desc *pd = asd_ha->phys[phy->id].phy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct asd_ascb *ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct sas_phy_linkrates *rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) int res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case PHY_FUNC_CLEAR_ERROR_LOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) case PHY_FUNC_GET_EVENTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case PHY_FUNC_SET_LINK_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) rates = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (rates->minimum_linkrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) pd->min_sas_lrate = rates->minimum_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) pd->min_sata_lrate = rates->minimum_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (rates->maximum_linkrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) pd->max_sas_lrate = rates->maximum_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) pd->max_sata_lrate = rates->maximum_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) func = PHY_FUNC_LINK_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!ascb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) asd_build_control_phy(ascb, phy->id, phy_func_table[func]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) res = asd_post_ascb_list(asd_ha, ascb , 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) asd_ascb_free(ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }