drivers/scsi/aic94xx/aic94xx_scb.c

Source file repositories/reference/linux-study-clean/drivers/scsi/aic94xx/aic94xx_scb.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/aic94xx/aic94xx_scb.c
Extension
.c
Size
26654 bytes
Lines
929
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (port->num_phys == 0 && free_port == NULL) {
				free_port = port;
			}
		}

		/* Use a free port if this doesn't form a wide port */
		if (i >= ASD_MAX_PHYS) {
			port = free_port;
			BUG_ON(!port);
			memcpy(port->sas_addr, sas_phy->sas_addr,
			       SAS_ADDR_SIZE);
			memcpy(port->attached_sas_addr,
			       sas_phy->attached_sas_addr,
			       SAS_ADDR_SIZE);
		}
		port->num_phys++;
		port->phy_mask |= (1U << sas_phy->id);
		phy->asd_port = port;
	}
	ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n",
		    __func__, phy->asd_port->phy_mask, sas_phy->id);
	asd_update_port_links(asd_ha, phy);
	spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
}

static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
{
	struct asd_port *port = phy->asd_port;
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	unsigned long flags;

	spin_lock_irqsave(&asd_ha->asd_ports_lock, flags);
	if (port) {
		port->num_phys--;
		port->phy_mask &= ~(1U << sas_phy->id);
		phy->asd_port = NULL;
	}
	spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
}

static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
				    struct done_list_struct *dl,
				    int edb_id, int phy_id)
{
	unsigned long flags;
	int edb_el = edb_id + ascb->edb_index;
	struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
	struct asd_phy *phy = &ascb->ha->phys[phy_id];
	u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];

	size = min(size, (u16) sizeof(phy->frame_rcvd));

	spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
	memcpy(phy->sas_phy.frame_rcvd, edb->vaddr, size);
	phy->sas_phy.frame_rcvd_size = size;
	asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
	spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
	asd_dump_frame_rcvd(phy, dl);
	asd_form_port(ascb->ha, phy);
	sas_notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
}

static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
				       struct done_list_struct *dl,
				       int phy_id)
{
	struct asd_ha_struct *asd_ha = ascb->ha;
	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
	struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
	struct asd_phy *phy = &asd_ha->phys[phy_id];
	u8 lr_error = dl->status_block[1];
	u8 retries_left = dl->status_block[2];

	switch (lr_error) {
	case 0:
		ASD_DPRINTK("phy%d: Receive ID timer expired\n", phy_id);
		break;
	case 1:
		ASD_DPRINTK("phy%d: Loss of signal\n", phy_id);
		break;
	case 2:
		ASD_DPRINTK("phy%d: Loss of dword sync\n", phy_id);
		break;
	case 3:
		ASD_DPRINTK("phy%d: Receive FIS timeout\n", phy_id);
		break;
	default:
		ASD_DPRINTK("phy%d: unknown link reset error code: 0x%x\n",
			    phy_id, lr_error);
		break;

Annotation

Implementation Notes