Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }