^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 hardware interface.
^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/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "aic94xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "aic94xx_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "aic94xx_hwi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "aic94xx_seq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "aic94xx_dump.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u32 MBAR0_SWB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* ---------- Initialization ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* adapter came with a sas address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (asd_ha->hw_prof.sas_addr[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return sas_request_addr(asd_ha->sas_ha.core.shost,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) asd_ha->hw_prof.sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (asd_ha->hw_prof.phy_desc[i].sas_addr[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Set a phy's address only if it has none.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ASD_DPRINTK("setting phy%d addr to %llx\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) SAS_ADDR(asd_ha->hw_prof.sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) memcpy(asd_ha->hw_prof.phy_desc[i].sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) asd_ha->hw_prof.sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* ---------- PHY initialization ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void asd_init_phy_identify(struct asd_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) phy->identify_frame = phy->id_frm_tok->vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) memset(phy->identify_frame, 0, sizeof(*phy->identify_frame));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) phy->identify_frame->dev_type = SAS_END_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (phy->sas_phy.role & PHY_ROLE_INITIATOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) phy->identify_frame->initiator_bits = phy->sas_phy.iproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (phy->sas_phy.role & PHY_ROLE_TARGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) phy->identify_frame->target_bits = phy->sas_phy.tproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) memcpy(phy->identify_frame->sas_addr, phy->phy_desc->sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) phy->identify_frame->phy_id = phy->sas_phy.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int asd_init_phy(struct asd_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct asd_ha_struct *asd_ha = phy->sas_phy.ha->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct asd_sas_phy *sas_phy = &phy->sas_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) sas_phy->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) sas_phy->class = SAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) sas_phy->iproto = SAS_PROTOCOL_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) sas_phy->tproto = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) sas_phy->type = PHY_TYPE_PHYSICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sas_phy->role = PHY_ROLE_INITIATOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sas_phy->oob_mode = OOB_NOT_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) phy->id_frm_tok = asd_alloc_coherent(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sizeof(*phy->identify_frame),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!phy->id_frm_tok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) asd_printk("no mem for IDENTIFY for phy%d\n", sas_phy->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) asd_init_phy_identify(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memset(phy->frame_rcvd, 0, sizeof(phy->frame_rcvd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void asd_init_ports(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spin_lock_init(&asd_ha->asd_ports_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct asd_port *asd_port = &asd_ha->asd_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) memset(asd_port->sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) memset(asd_port->attached_sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) asd_port->phy_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) asd_port->num_phys = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int asd_init_phys(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u8 phy_mask = asd_ha->hw_prof.enabled_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct asd_phy *phy = &asd_ha->phys[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) phy->phy_desc = &asd_ha->hw_prof.phy_desc[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) phy->asd_port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) phy->sas_phy.enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) phy->sas_phy.id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) phy->sas_phy.sas_addr = &phy->phy_desc->sas_addr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) phy->sas_phy.frame_rcvd = &phy->frame_rcvd[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) phy->sas_phy.ha = &asd_ha->sas_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) phy->sas_phy.lldd_phy = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Now enable and initialize only the enabled phys. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) for_each_phy(phy_mask, phy_mask, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int err = asd_init_phy(&asd_ha->phys[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* ---------- Sliding windows ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int asd_init_sw(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct pci_dev *pcidev = asd_ha->pcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Unlock MBARs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err = pci_read_config_dword(pcidev, PCI_CONF_MBAR_KEY, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) asd_printk("couldn't access conf. space of %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pci_name(pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) err = pci_write_config_dword(pcidev, PCI_CONF_MBAR_KEY, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) asd_printk("couldn't write to MBAR_KEY of %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) pci_name(pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* Set sliding windows A, B and C to point to proper internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * memory regions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pci_write_config_dword(pcidev, PCI_CONF_MBAR0_SWA, REG_BASE_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) pci_write_config_dword(pcidev, PCI_CONF_MBAR0_SWB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) REG_BASE_ADDR_CSEQCIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) pci_write_config_dword(pcidev, PCI_CONF_MBAR0_SWC, REG_BASE_ADDR_EXSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) asd_ha->io_handle[0].swa_base = REG_BASE_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) asd_ha->io_handle[0].swb_base = REG_BASE_ADDR_CSEQCIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) asd_ha->io_handle[0].swc_base = REG_BASE_ADDR_EXSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) MBAR0_SWB_SIZE = asd_ha->io_handle[0].len - 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!asd_ha->iospace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* MBAR1 will point to OCM (On Chip Memory) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pci_write_config_dword(pcidev, PCI_CONF_MBAR1, OCM_BASE_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) asd_ha->io_handle[1].swa_base = OCM_BASE_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) spin_lock_init(&asd_ha->iolock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* ---------- SCB initialization ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * asd_init_scbs - manually allocate the first SCB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * This allocates the very first SCB which would be sent to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * sequencer for execution. Its bus address is written to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * CSEQ_Q_NEW_POINTER, mode page 2, mode 8. Since the bus address of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * the _next_ scb to be DMA-ed to the host adapter is read from the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * SCB DMA-ed to the host adapter, we have to always stay one step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * ahead of the sequencer and keep one SCB already allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int asd_init_scbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int bitmap_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* allocate the index array and bitmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) asd_ha->seq.tc_index_bitmap_bits = asd_ha->hw_prof.max_scbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) asd_ha->seq.tc_index_array = kcalloc(asd_ha->seq.tc_index_bitmap_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!asd_ha->seq.tc_index_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) bitmap_bytes = (asd_ha->seq.tc_index_bitmap_bits+7)/8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bitmap_bytes = BITS_TO_LONGS(bitmap_bytes*8)*sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) asd_ha->seq.tc_index_bitmap = kzalloc(bitmap_bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!asd_ha->seq.tc_index_bitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) kfree(asd_ha->seq.tc_index_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) asd_ha->seq.tc_index_array = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) spin_lock_init(&seq->tc_index_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) seq->next_scb.size = sizeof(struct scb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) seq->next_scb.vaddr = dma_pool_alloc(asd_ha->scb_pool, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) &seq->next_scb.dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!seq->next_scb.vaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) kfree(asd_ha->seq.tc_index_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) kfree(asd_ha->seq.tc_index_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) asd_ha->seq.tc_index_bitmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) asd_ha->seq.tc_index_array = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) seq->pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) spin_lock_init(&seq->pend_q_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) INIT_LIST_HEAD(&seq->pend_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) asd_ha->hw_prof.max_scbs = asd_get_cmdctx_size(asd_ha)/ASD_SCB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) asd_ha->hw_prof.max_ddbs = asd_get_devctx_size(asd_ha)/ASD_DDB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ASD_DPRINTK("max_scbs:%d, max_ddbs:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) asd_ha->hw_prof.max_scbs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) asd_ha->hw_prof.max_ddbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* ---------- Done List initialization ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static void asd_dl_tasklet_handler(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static int asd_init_dl(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) asd_ha->seq.actual_dl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) = asd_alloc_coherent(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ASD_DL_SIZE * sizeof(struct done_list_struct),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!asd_ha->seq.actual_dl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) asd_ha->seq.dl = asd_ha->seq.actual_dl->vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) asd_ha->seq.dl_toggle = ASD_DEF_DL_TOGGLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) asd_ha->seq.dl_next = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) tasklet_init(&asd_ha->seq.dl_tasklet, asd_dl_tasklet_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) (unsigned long) asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* ---------- EDB and ESCB init ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int asd_alloc_edbs(struct asd_ha_struct *asd_ha, gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) seq->edb_arr = kmalloc_array(seq->num_edbs, sizeof(*seq->edb_arr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!seq->edb_arr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for (i = 0; i < seq->num_edbs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) seq->edb_arr[i] = asd_alloc_coherent(asd_ha, ASD_EDB_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!seq->edb_arr[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) goto Err_unroll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) memset(seq->edb_arr[i]->vaddr, 0, ASD_EDB_SIZE);
^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) ASD_DPRINTK("num_edbs:%d\n", seq->num_edbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) Err_unroll:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) for (i-- ; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) asd_free_coherent(asd_ha, seq->edb_arr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) kfree(seq->edb_arr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) seq->edb_arr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static int asd_alloc_escbs(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct asd_ascb *escb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int i, escbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) seq->escb_arr = kmalloc_array(seq->num_escbs, sizeof(*seq->escb_arr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!seq->escb_arr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) escbs = seq->num_escbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) escb = asd_ascb_alloc_list(asd_ha, &escbs, gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!escb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) asd_printk("couldn't allocate list of escbs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) seq->num_escbs -= escbs; /* subtract what was not allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ASD_DPRINTK("num_escbs:%d\n", seq->num_escbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) for (i = 0; i < seq->num_escbs; i++, escb = list_entry(escb->list.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct asd_ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) seq->escb_arr[i] = escb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) escb->scb->header.opcode = EMPTY_SCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) kfree(seq->escb_arr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) seq->escb_arr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void asd_assign_edbs2escbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int i, k, z = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) for (i = 0; i < seq->num_escbs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct asd_ascb *ascb = seq->escb_arr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct empty_scb *escb = &ascb->scb->escb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ascb->edb_index = z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) escb->num_valid = ASD_EDBS_PER_SCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) for (k = 0; k < ASD_EDBS_PER_SCB; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct sg_el *eb = &escb->eb[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct asd_dma_tok *edb = seq->edb_arr[z++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) memset(eb, 0, sizeof(*eb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) eb->bus_addr = cpu_to_le64(((u64) edb->dma_handle));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) eb->size = cpu_to_le32(((u32) edb->size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * asd_init_escbs -- allocate and initialize empty scbs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * An empty SCB has sg_elements of ASD_EDBS_PER_SCB (7) buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * They transport sense data, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int asd_init_escbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Allocate two empty data buffers (edb) per sequencer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int edbs = 2*(1+asd_ha->hw_prof.num_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) seq->num_escbs = (edbs+ASD_EDBS_PER_SCB-1)/ASD_EDBS_PER_SCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) seq->num_edbs = seq->num_escbs * ASD_EDBS_PER_SCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err = asd_alloc_edbs(asd_ha, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) asd_printk("couldn't allocate edbs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) err = asd_alloc_escbs(asd_ha, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) asd_printk("couldn't allocate escbs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) asd_assign_edbs2escbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* In order to insure that normal SCBs do not overfill sequencer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * memory and leave no space for escbs (halting condition),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * we increment pending here by the number of escbs. However,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * escbs are never pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) seq->pending = seq->num_escbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) seq->can_queue = 1 + (asd_ha->hw_prof.max_scbs - seq->pending)/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* ---------- HW initialization ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * asd_chip_hardrst -- hard reset the chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * This takes 16 cycles and is synchronous to CFCLK, which runs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * at 200 MHz, so this should take at most 80 nanoseconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int asd_chip_hardrst(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int count = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) for (i = 0 ; i < 4 ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) asd_write_reg_dword(asd_ha, COMBIST, HARDRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) reg = asd_read_reg_dword(asd_ha, CHIMINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (reg & HARDRSTDET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) asd_write_reg_dword(asd_ha, CHIMINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) HARDRSTDET|PORRSTDET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) } while (--count > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * asd_init_chip -- initialize the chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * Hard resets the chip, disables HA interrupts, downloads the sequnecer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * microcode and starts the sequencers. The caller has to explicitly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * enable HA interrupts with asd_enable_ints(asd_ha).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int asd_init_chip(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) err = asd_chip_hardrst(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) asd_printk("couldn't hard reset %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto out;
^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) asd_disable_ints(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) err = asd_init_seqs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) asd_printk("couldn't init seqs for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err = asd_start_seqs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) asd_printk("couldn't start seqs for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return err;
^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) #define MAX_DEVS ((OCM_MAX_SIZE) / (ASD_DDB_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int max_devs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) module_param_named(max_devs, max_devs, int, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) MODULE_PARM_DESC(max_devs, "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) "\tMaximum number of SAS devices to support (not LUs).\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "\tDefault: 2176, Maximum: 65663.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int max_cmnds = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) module_param_named(max_cmnds, max_cmnds, int, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) MODULE_PARM_DESC(max_cmnds, "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) "\tMaximum number of commands queuable.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) "\tDefault: 512, Maximum: 66047.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static void asd_extend_devctx_ocm(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) unsigned long dma_addr = OCM_BASE_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) u32 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dma_addr -= asd_ha->hw_prof.max_ddbs * ASD_DDB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) asd_write_reg_addr(asd_ha, DEVCTXBASE, (dma_addr_t) dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) d = asd_read_reg_dword(asd_ha, CTXDOMAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) d |= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) asd_write_reg_dword(asd_ha, CTXDOMAIN, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) asd_ha->hw_prof.max_ddbs += MAX_DEVS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int asd_extend_devctx(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dma_addr_t dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned long dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) u32 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) asd_extend_devctx_ocm(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) asd_ha->hw_prof.ddb_ext = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (max_devs <= asd_ha->hw_prof.max_ddbs || max_devs > 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) max_devs = asd_ha->hw_prof.max_ddbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) size = (max_devs - asd_ha->hw_prof.max_ddbs + 1) * ASD_DDB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) asd_ha->hw_prof.ddb_ext = asd_alloc_coherent(asd_ha, size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (!asd_ha->hw_prof.ddb_ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) asd_printk("couldn't allocate memory for %d devices\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) max_devs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) max_devs = asd_ha->hw_prof.max_ddbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) dma_handle = asd_ha->hw_prof.ddb_ext->dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dma_addr = ALIGN((unsigned long) dma_handle, ASD_DDB_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) dma_addr -= asd_ha->hw_prof.max_ddbs * ASD_DDB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dma_handle = (dma_addr_t) dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) asd_write_reg_addr(asd_ha, DEVCTXBASE, dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) d = asd_read_reg_dword(asd_ha, CTXDOMAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) d &= ~4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) asd_write_reg_dword(asd_ha, CTXDOMAIN, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) asd_ha->hw_prof.max_ddbs = max_devs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^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) static int asd_extend_cmdctx(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dma_addr_t dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned long dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) u32 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) asd_ha->hw_prof.scb_ext = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (max_cmnds <= asd_ha->hw_prof.max_scbs || max_cmnds > 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) max_cmnds = asd_ha->hw_prof.max_scbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) size = (max_cmnds - asd_ha->hw_prof.max_scbs + 1) * ASD_SCB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) asd_ha->hw_prof.scb_ext = asd_alloc_coherent(asd_ha, size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!asd_ha->hw_prof.scb_ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) asd_printk("couldn't allocate memory for %d commands\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) max_cmnds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) max_cmnds = asd_ha->hw_prof.max_scbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dma_handle = asd_ha->hw_prof.scb_ext->dma_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) dma_addr = ALIGN((unsigned long) dma_handle, ASD_SCB_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dma_addr -= asd_ha->hw_prof.max_scbs * ASD_SCB_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dma_handle = (dma_addr_t) dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) asd_write_reg_addr(asd_ha, CMDCTXBASE, dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) d = asd_read_reg_dword(asd_ha, CTXDOMAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) d &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) asd_write_reg_dword(asd_ha, CTXDOMAIN, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) asd_ha->hw_prof.max_scbs = max_cmnds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * asd_init_ctxmem -- initialize context memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * This function sets the maximum number of SCBs and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * DDBs which can be used by the sequencer. This is normally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * 512 and 128 respectively. If support for more SCBs or more DDBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * is required then CMDCTXBASE, DEVCTXBASE and CTXDOMAIN are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * initialized here to extend context memory to point to host memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * thus allowing unlimited support for SCBs and DDBs -- only limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * by host memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int asd_init_ctxmem(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int bitmap_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) asd_get_max_scb_ddb(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) asd_extend_devctx(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) asd_extend_cmdctx(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* The kernel wants bitmaps to be unsigned long sized. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) bitmap_bytes = (asd_ha->hw_prof.max_ddbs+7)/8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bitmap_bytes = BITS_TO_LONGS(bitmap_bytes*8)*sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) asd_ha->hw_prof.ddb_bitmap = kzalloc(bitmap_bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!asd_ha->hw_prof.ddb_bitmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) spin_lock_init(&asd_ha->hw_prof.ddb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int asd_init_hw(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) err = asd_init_sw(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) err = pci_read_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) asd_printk("couldn't read PCIC_HSTPCIX_CNTRL of %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) err = pci_write_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) v | SC_TMR_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) asd_printk("couldn't disable split completion timer of %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) err = asd_read_ocm(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) asd_printk("couldn't read ocm(%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* While suspicios, it is not an error that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * couldn't read the OCM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) err = asd_read_flash(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) asd_printk("couldn't read flash(%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* While suspicios, it is not an error that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * couldn't read FLASH memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) asd_init_ctxmem(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (asd_get_user_sas_addr(asd_ha)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) asd_printk("No SAS Address provided for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) asd_propagate_sas_addr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) err = asd_init_phys(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) asd_printk("couldn't initialize phys for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) asd_init_ports(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) err = asd_init_scbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) asd_printk("couldn't initialize scbs for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) err = asd_init_dl(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) asd_printk("couldn't initialize the done list:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) err = asd_init_escbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) asd_printk("couldn't initialize escbs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) err = asd_init_chip(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) asd_printk("couldn't init the chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) goto Out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) Out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* ---------- Chip reset ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * asd_chip_reset -- reset the host adapter, etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * @asd_ha: pointer to host adapter structure of interest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * Called from the ISR. Hard reset the chip. Let everything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * timeout. This should be no different than hot-unplugging the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * host adapter. Once everything times out we'll init the chip with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * a call to asd_init_chip() and enable interrupts with asd_enable_ints().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * XXX finish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static void asd_chip_reset(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ASD_DPRINTK("chip reset for %s\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) asd_chip_hardrst(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* ---------- Done List Routines ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static void asd_dl_tasklet_handler(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct asd_ha_struct *asd_ha = (struct asd_ha_struct *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct done_list_struct *dl = &seq->dl[seq->dl_next];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct asd_ascb *ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if ((dl->toggle & DL_TOGGLE_MASK) != seq->dl_toggle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* find the aSCB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) spin_lock_irqsave(&seq->tc_index_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ascb = asd_tc_index_find(seq, (int)le16_to_cpu(dl->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) spin_unlock_irqrestore(&seq->tc_index_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (unlikely(!ascb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ASD_DPRINTK("BUG:sequencer:dl:no ascb?!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) goto next_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) } else if (ascb->scb->header.opcode == EMPTY_SCB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) } else if (!ascb->uldd_timer && !del_timer(&ascb->timer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) goto next_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) spin_lock_irqsave(&seq->pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) list_del_init(&ascb->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) seq->pending--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) spin_unlock_irqrestore(&seq->pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ascb->tasklet_complete(ascb, dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) next_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) seq->dl_next = (seq->dl_next + 1) & (ASD_DL_SIZE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!seq->dl_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) seq->dl_toggle ^= DL_TOGGLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* ---------- Interrupt Service Routines ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * asd_process_donelist_isr -- schedule processing of done list entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) tasklet_schedule(&asd_ha->seq.dl_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * asd_com_sas_isr -- process device communication interrupt (COMINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) u32 comstat = asd_read_reg_dword(asd_ha, COMSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* clear COMSTAT int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) asd_write_reg_dword(asd_ha, COMSTAT, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (comstat & CSBUFPERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) asd_printk("%s: command/status buffer dma parity error\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) } else if (comstat & CSERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) u32 dmaerr = asd_read_reg_dword(asd_ha, DMAERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) dmaerr &= 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) asd_printk("%s: command/status dma error, DMAERR: 0x%02x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) "CSDMAADR: 0x%04x, CSDMAADR+4: 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dmaerr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) asd_read_reg_dword(asd_ha, CSDMAADR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) asd_read_reg_dword(asd_ha, CSDMAADR+4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) asd_printk("CSBUFFER:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) asd_printk("%08x %08x %08x %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) asd_read_reg_dword(asd_ha, CSBUFFER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) asd_read_reg_dword(asd_ha, CSBUFFER+4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) asd_read_reg_dword(asd_ha, CSBUFFER+8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) asd_read_reg_dword(asd_ha, CSBUFFER+12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) asd_dump_seq_state(asd_ha, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) } else if (comstat & OVLYERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) u32 dmaerr = asd_read_reg_dword(asd_ha, DMAERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dmaerr = (dmaerr >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) asd_printk("%s: overlay dma error:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dmaerr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) asd_chip_reset(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static const char *halt_code[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) "UNEXPECTED_INTERRUPT0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) "UNEXPECTED_INTERRUPT1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) "UNEXPECTED_INTERRUPT2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) "UNEXPECTED_INTERRUPT3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) "UNEXPECTED_INTERRUPT4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) "UNEXPECTED_INTERRUPT5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) "UNEXPECTED_INTERRUPT6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) "UNEXPECTED_INTERRUPT7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) "UNEXPECTED_INTERRUPT8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) "UNEXPECTED_INTERRUPT9",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) "UNEXPECTED_INTERRUPT10",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) [11 ... 19] = "unknown[11,19]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) "NO_FREE_SCB_AVAILABLE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) "INVALID_SCB_OPCODE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) "INVALID_MBX_OPCODE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) "INVALID_ATA_STATE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) "ATA_QUEUE_FULL",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) "ATA_TAG_TABLE_FAULT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) "ATA_TAG_MASK_FAULT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) "BAD_LINK_QUEUE_STATE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) "DMA2CHIM_QUEUE_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) "EMPTY_SCB_LIST_FULL",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) "unknown[30]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) "IN_USE_SCB_ON_FREE_LIST",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) "BAD_OPEN_WAIT_STATE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) "INVALID_STP_AFFILIATION",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) "unknown[34]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) "EXEC_QUEUE_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) "TOO_MANY_EMPTIES_NEEDED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) "EMPTY_REQ_QUEUE_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) "Q_MONIRTT_MGMT_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) "TARGET_MODE_FLOW_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) "DEVICE_QUEUE_NOT_FOUND",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) "START_IRTT_TIMER_ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) "ABORT_TASK_ILLEGAL_REQ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) [43 ... 255] = "unknown[43,255]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (dchstatus & CSEQINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) u32 arp2int = asd_read_reg_dword(asd_ha, CARP2INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (arp2int & (ARP2WAITTO|ARP2ILLOPC|ARP2PERR|ARP2CIOPERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) asd_printk("%s: CSEQ arp2int:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) arp2int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) } else if (arp2int & ARP2HALTC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) asd_printk("%s: CSEQ halted: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) halt_code[(arp2int>>16)&0xFF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) asd_printk("%s: CARP2INT:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) arp2int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (dchstatus & LSEQINT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) int lseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) u8 lseq_mask = dchstatus & LSEQINT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) for_each_sequencer(lseq_mask, lseq_mask, lseq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) u32 arp2int = asd_read_reg_dword(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) LmARP2INT(lseq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (arp2int & (ARP2WAITTO | ARP2ILLOPC | ARP2PERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) | ARP2CIOPERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) asd_printk("%s: LSEQ%d arp2int:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) lseq, arp2int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* XXX we should only do lseq reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) } else if (arp2int & ARP2HALTC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) asd_printk("%s: LSEQ%d halted: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) lseq,halt_code[(arp2int>>16)&0xFF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) asd_printk("%s: LSEQ%d ARP2INT:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) pci_name(asd_ha->pcidev), lseq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) arp2int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) asd_chip_reset(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * asd_dch_sas_isr -- process device channel interrupt (DEVINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) u32 dchstatus = asd_read_reg_dword(asd_ha, DCHSTATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (dchstatus & CFIFTOERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) asd_printk("%s: CFIFTOERR\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) asd_chip_reset(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) asd_arp2_err(asd_ha, dchstatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * ads_rbi_exsi_isr -- process external system interface interrupt (INITERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!(stat0r & ASIERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) asd_printk("hmm, EXSI interrupted but no error?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (stat0r & ASIFMTERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) asd_printk("ASI SEEPROM format error for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) } else if (stat0r & ASISEECHKERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) u32 stat1r = asd_read_reg_dword(asd_ha, ASISTAT1R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) asd_printk("ASI SEEPROM checksum 0x%x error for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) stat1r & CHECKSUM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) u32 statr = asd_read_reg_dword(asd_ha, ASIERRSTATR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (!(statr & CPI2ASIMSTERR_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) ASD_DPRINTK("hmm, ASIERR?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) u32 addr = asd_read_reg_dword(asd_ha, ASIERRADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 data = asd_read_reg_dword(asd_ha, ASIERRDATAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) asd_printk("%s: CPI2 xfer err: addr: 0x%x, wdata: 0x%x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) "count: 0x%x, byteen: 0x%x, targerr: 0x%x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) "master id: 0x%x, master err: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) addr, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) (statr & CPI2ASIBYTECNT_MASK) >> 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (statr & CPI2ASIBYTEEN_MASK) >> 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) (statr & CPI2ASITARGERR_MASK) >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) (statr & CPI2ASITARGMID_MASK) >> 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) (statr & CPI2ASIMSTERR_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) asd_chip_reset(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * asd_hst_pcix_isr -- process host interface interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * Asserted on PCIX errors: target abort, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) static void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) u32 pcix_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) u32 ecc_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) pci_read_config_word(asd_ha->pcidev, PCI_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) pci_read_config_dword(asd_ha->pcidev, PCIX_STATUS, &pcix_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) pci_read_config_dword(asd_ha->pcidev, ECC_CTRL_STAT, &ecc_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (status & PCI_STATUS_DETECTED_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) asd_printk("parity error for %s\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) else if (status & PCI_STATUS_REC_MASTER_ABORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) asd_printk("master abort for %s\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) else if (status & PCI_STATUS_REC_TARGET_ABORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) asd_printk("target abort for %s\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) else if (status & PCI_STATUS_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) asd_printk("data parity for %s\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) else if (pcix_status & RCV_SCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) asd_printk("received split completion error for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) pci_write_config_dword(asd_ha->pcidev,PCIX_STATUS,pcix_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* XXX: Abort task? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) } else if (pcix_status & UNEXP_SC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) asd_printk("unexpected split completion for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) pci_write_config_dword(asd_ha->pcidev,PCIX_STATUS,pcix_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) /* ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) } else if (pcix_status & SC_DISCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) asd_printk("split completion discarded for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) else if (ecc_status & UNCOR_ECCERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) asd_printk("uncorrectable ECC error for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) asd_chip_reset(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * asd_hw_isr -- host adapter interrupt service routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * @irq: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * @dev_id: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * The ISR processes done list entries and level 3 error handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) irqreturn_t asd_hw_isr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct asd_ha_struct *asd_ha = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) u32 chimint = asd_read_reg_dword(asd_ha, CHIMINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (!chimint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) asd_write_reg_dword(asd_ha, CHIMINT, chimint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) (void) asd_read_reg_dword(asd_ha, CHIMINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (chimint & DLAVAIL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) asd_process_donelist_isr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (chimint & COMINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) asd_com_sas_isr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (chimint & DEVINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) asd_dch_sas_isr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (chimint & INITERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) asd_rbi_exsi_isr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (chimint & HOSTERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) asd_hst_pcix_isr(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* ---------- SCB handling ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) extern struct kmem_cache *asd_ascb_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct asd_ascb *ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) ascb = kmem_cache_zalloc(asd_ascb_cache, gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (ascb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) ascb->dma_scb.size = sizeof(struct scb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ascb->dma_scb.vaddr = dma_pool_zalloc(asd_ha->scb_pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) gfp_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) &ascb->dma_scb.dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!ascb->dma_scb.vaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) kmem_cache_free(asd_ascb_cache, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) asd_init_ascb(asd_ha, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) spin_lock_irqsave(&seq->tc_index_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) ascb->tc_index = asd_tc_index_get(seq, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) spin_unlock_irqrestore(&seq->tc_index_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (ascb->tc_index == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) goto undo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) ascb->scb->header.index = cpu_to_le16((u16)ascb->tc_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) undo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) dma_pool_free(asd_ha->scb_pool, ascb->dma_scb.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ascb->dma_scb.dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) kmem_cache_free(asd_ascb_cache, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ASD_DPRINTK("no index for ascb\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * asd_ascb_alloc_list -- allocate a list of aSCBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * @num: pointer to integer number of aSCBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * @gfp_flags: GFP_ flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * This is the only function which is used to allocate aSCBs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * It can allocate one or many. If more than one, then they form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * a linked list in two ways: by their list field of the ascb struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * and by the next_scb field of the scb_header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * Returns NULL if no memory was available, else pointer to a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * of ascbs. When this function returns, @num would be the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * of SCBs which were not able to be allocated, 0 if all requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * were able to be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) *asd_ha, int *num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct asd_ascb *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) for ( ; *num > 0; --*num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct asd_ascb *ascb = asd_ascb_alloc(asd_ha, gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (!ascb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) else if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) first = ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct asd_ascb *last = list_entry(first->list.prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) struct asd_ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) list_add_tail(&ascb->list, &first->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) last->scb->header.next_scb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) cpu_to_le64(((u64)ascb->dma_scb.dma_handle));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * asd_swap_head_scb -- swap the head scb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * @ascb: pointer to the head of an ascb list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * The sequencer knows the DMA address of the next SCB to be DMAed to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * the host adapter, from initialization or from the last list DMAed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * seq->next_scb keeps the address of this SCB. The sequencer will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * DMA to the host adapter this list of SCBs. But the head (first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * element) of this list is not known to the sequencer. Here we swap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * the head of the list with the known SCB (memcpy()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * Only one memcpy() is required per list so it is in our interest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * to keep the list of SCB as long as possible so that the ratio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * of number of memcpy calls to the number of SCB DMA-ed is as small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * as possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * LOCKING: called with the pending list lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct asd_ascb *ascb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct asd_ascb *last = list_entry(ascb->list.prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct asd_ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct asd_dma_tok t = ascb->dma_scb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) memcpy(seq->next_scb.vaddr, ascb->scb, sizeof(*ascb->scb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) ascb->dma_scb = seq->next_scb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ascb->scb = ascb->dma_scb.vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) seq->next_scb = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) last->scb->header.next_scb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) cpu_to_le64(((u64)seq->next_scb.dma_handle));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * asd_start_timers -- (add and) start timers of SCBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * @list: pointer to struct list_head of the scbs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * If an SCB in the @list has no timer function, assign the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * one, then start the timer of the SCB. This function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * intended to be called from asd_post_ascb_list(), just prior to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * posting the SCBs to the sequencer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static void asd_start_scb_timers(struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) struct asd_ascb *ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) list_for_each_entry(ascb, list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (!ascb->uldd_timer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ascb->timer.function = asd_ascb_timedout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ascb->timer.expires = jiffies + AIC94XX_SCB_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) add_timer(&ascb->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * asd_post_ascb_list -- post a list of 1 or more aSCBs to the host adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * @asd_ha: pointer to a host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * @ascb: pointer to the first aSCB in the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * @num: number of aSCBs in the list (to be posted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * See queueing comment in asd_post_escb_list().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * Additional note on queuing: In order to minimize the ratio of memcpy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * to the number of ascbs sent, we try to batch-send as many ascbs as possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * in one go.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * Two cases are possible:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * A) can_queue >= num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * B) can_queue < num.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) * Case A: we can send the whole batch at once. Increment "pending"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * in the beginning of this function, when it is checked, in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * eliminate races when this function is called by multiple processes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) * Case B: should never happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) LIST_HEAD(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) int can_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) spin_lock_irqsave(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) can_queue = asd_ha->hw_prof.max_scbs - asd_ha->seq.pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (can_queue >= num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) asd_ha->seq.pending += num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) can_queue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (!can_queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) spin_unlock_irqrestore(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) asd_printk("%s: scb queue full\n", pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return -SAS_QUEUE_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) asd_swap_head_scb(asd_ha, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) __list_add(&list, ascb->list.prev, &ascb->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) asd_start_scb_timers(&list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) asd_ha->seq.scbpro += num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) list_splice_init(&list, asd_ha->seq.pend_q.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) asd_write_reg_dword(asd_ha, SCBPRO, (u32)asd_ha->seq.scbpro);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) spin_unlock_irqrestore(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * asd_post_escb_list -- post a list of 1 or more empty scb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * @asd_ha: pointer to a host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * @ascb: pointer to the first empty SCB in the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * @num: number of aSCBs in the list (to be posted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * This is essentially the same as asd_post_ascb_list, but we do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * increment pending, add those to the pending list or get indexes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * See asd_init_escbs() and asd_init_post_escbs().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * Since sending a list of ascbs is a superset of sending a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * ascb, this function exists to generalize this. More specifically,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * when sending a list of those, we want to do only a _single_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * memcpy() at swap head, as opposed to for each ascb sent (in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * case of sending them one by one). That is, we want to minimize the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * ratio of memcpy() operations to the number of ascbs sent. The same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * logic applies to asd_post_ascb_list().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) int asd_post_escb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) spin_lock_irqsave(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) asd_swap_head_scb(asd_ha, ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) asd_ha->seq.scbpro += num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) asd_write_reg_dword(asd_ha, SCBPRO, (u32)asd_ha->seq.scbpro);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) spin_unlock_irqrestore(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) /* ---------- LED ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * asd_turn_led -- turn on/off an LED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * @phy_id: the PHY id whose LED we want to manupulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * @op: 1 to turn on, 0 to turn off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (phy_id < ASD_MAX_PHYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) u32 v = asd_read_reg_dword(asd_ha, LmCONTROL(phy_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) v |= LEDPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) v &= ~LEDPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) asd_write_reg_dword(asd_ha, LmCONTROL(phy_id), v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * asd_control_led -- enable/disable an LED on the board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * @phy_id: integer, the phy id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * @op: integer, 1 to enable, 0 to disable the LED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * First we output enable the LED, then we set the source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * to be an external module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (phy_id < ASD_MAX_PHYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) v = asd_read_reg_dword(asd_ha, GPIOOER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) v |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) v &= ~(1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) asd_write_reg_dword(asd_ha, GPIOOER, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) v = asd_read_reg_dword(asd_ha, GPIOCNFGR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) v |= (1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) v &= ~(1 << phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) asd_write_reg_dword(asd_ha, GPIOCNFGR, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) /* ---------- PHY enable ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static int asd_enable_phy(struct asd_ha_struct *asd_ha, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct asd_phy *phy = &asd_ha->phys[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, INT_ENABLE_2), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, HOT_PLUG_DELAY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) HOTPLUG_DELAY_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* Get defaults from manuf. sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) /* XXX we need defaults for those in case MS is broken. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, PHY_CONTROL_0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) phy->phy_desc->phy_control_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, PHY_CONTROL_1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) phy->phy_desc->phy_control_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, PHY_CONTROL_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) phy->phy_desc->phy_control_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) asd_write_reg_byte(asd_ha, LmSEQ_OOB_REG(phy_id, PHY_CONTROL_3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) phy->phy_desc->phy_control_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) asd_write_reg_dword(asd_ha, LmSEQ_TEN_MS_COMINIT_TIMEOUT(phy_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) ASD_COMINIT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) asd_write_reg_addr(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(phy_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) phy->id_frm_tok->dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) asd_control_led(asd_ha, phy_id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) u8 phy_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) int num = 0, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct asd_ascb *ascb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) struct asd_ascb *ascb_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!phy_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) asd_printk("%s called with phy_mask of 0!?\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) for_each_phy(phy_mask, phy_m, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) asd_enable_phy(asd_ha, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) k = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ascb_list = asd_ascb_alloc_list(asd_ha, &k, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (!ascb_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) asd_printk("no memory for control phy ascb list\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) num -= k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ascb = ascb_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) for_each_phy(phy_mask, phy_m, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) asd_build_control_phy(ascb, i, ENABLE_PHY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) ascb = list_entry(ascb->list.next, struct asd_ascb, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) ASD_DPRINTK("posting %d control phy scbs\n", num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) k = asd_post_ascb_list(asd_ha, ascb_list, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) asd_ascb_free_list(ascb_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }