/* fill task_status_struct based on SSP response frame */ void sas_ssp_task_response(struct device *dev, struct sas_task *task, struct ssp_response_iu *iu) { struct task_status_struct *tstat = &task->task_status; tstat->resp = SAS_TASK_COMPLETE; if (iu->datapres == 0) tstat->stat = iu->status; else if (iu->datapres == 1) tstat->stat = iu->resp_data[3]; else if (iu->datapres == 2) { tstat->stat = SAM_CHECK_COND; tstat->buf_valid_size = min_t(int, SAS_STATUS_BUF_SIZE, be32_to_cpu(iu->sense_data_len)); memcpy(tstat->buf, iu->sense_data, tstat->buf_valid_size); if (iu->status != SAM_CHECK_COND) dev_printk(KERN_WARNING, dev, "dev %llx sent sense data, but " "stat(%x) is not CHECK CONDITION\n", SAS_ADDR(task->dev->sas_addr), iu->status); }
int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy) { if (phy->attached_tproto & SAS_PROTOCOL_STP) dev->tproto = phy->attached_tproto; if (phy->attached_sata_dev) dev->tproto |= SATA_DEV; if (phy->attached_dev_type == SATA_PENDING) dev->dev_type = SATA_PENDING; else { int res; dev->dev_type = SATA_DEV; res = sas_get_report_phy_sata(dev->parent, phy->phy_id, &dev->sata_dev.rps_resp); if (res) { SAS_DPRINTK("report phy sata to %016llx:0x%x returned " "0x%x\n", SAS_ADDR(dev->parent->sas_addr), phy->phy_id, res); return res; } memcpy(dev->frame_rcvd, &dev->sata_dev.rps_resp.rps.fis, sizeof(struct dev_to_host_fis)); /* TODO switch to ata_dev_classify() */ sas_get_ata_command_set(dev); } return 0; }
static void sci_remote_node_context_construct_buffer(struct sci_remote_node_context *sci_rnc) { struct isci_remote_device *idev = rnc_to_dev(sci_rnc); struct domain_device *dev = idev->domain_dev; int rni = sci_rnc->remote_node_index; union scu_remote_node_context *rnc; struct isci_host *ihost; __le64 sas_addr; ihost = idev->owning_port->owning_controller; rnc = sci_rnc_by_id(ihost, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) * sci_remote_device_node_count(idev)); rnc->ssp.remote_node_index = rni; rnc->ssp.remote_node_port_width = idev->device_port_width; rnc->ssp.logical_port_index = idev->owning_port->physical_port_index; /* sas address is __be64, context ram format is __le64 */ sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr)); rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr); rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr); rnc->ssp.nexus_loss_timer_enable = true; rnc->ssp.check_bit = false; rnc->ssp.is_valid = false; rnc->ssp.is_remote_node_context = true; rnc->ssp.function_number = 0; rnc->ssp.arbitration_wait_time = 0; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { rnc->ssp.connection_occupancy_timeout = ihost->user_parameters.stp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = ihost->user_parameters.stp_inactivity_timeout; } else { rnc->ssp.connection_occupancy_timeout = ihost->user_parameters.ssp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = ihost->user_parameters.ssp_inactivity_timeout; } rnc->ssp.initial_arbitration_wait_time = 0; /* Open Address Frame Parameters */ rnc->ssp.oaf_connection_rate = idev->connection_rate; rnc->ssp.oaf_features = 0; rnc->ssp.oaf_source_zone_group = 0; rnc->ssp.oaf_more_compatibility_features = 0; }
int sas_notify_lldd_dev_found(struct domain_device *dev) { int res = 0; struct sas_ha_struct *sas_ha = dev->port->ha; struct Scsi_Host *shost = sas_ha->core.shost; struct sas_internal *i = to_sas_internal(shost->transportt); if (i->dft->lldd_dev_found) { res = i->dft->lldd_dev_found(dev); if (res) { printk("sas: driver on pcidev %s cannot handle " "device %llx, error:%d\n", dev_name(sas_ha->dev), SAS_ADDR(dev->sas_addr), res); } } return res; }
static int pm8001_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) { struct domain_device *dev = task->dev; struct pm8001_hba_info *pm8001_ha; struct pm8001_device *pm8001_dev; struct pm8001_port *port = NULL; struct sas_task *t = task; struct pm8001_ccb_info *ccb; u32 tag = 0xdeadbeef, rc, n_elem = 0; u32 n = num; unsigned long flags = 0, flags_libsas = 0; if (!dev->port) { struct task_status_struct *tsm = &t->task_status; tsm->resp = SAS_TASK_UNDELIVERED; tsm->stat = SAS_PHY_DOWN; if (dev->dev_type != SATA_DEV) t->task_done(t); return 0; } pm8001_ha = pm8001_find_ha_by_dev(task->dev); PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n ")); spin_lock_irqsave(&pm8001_ha->lock, flags); do { dev = t->dev; pm8001_dev = dev->lldd_dev; if (DEV_IS_GONE(pm8001_dev)) { if (pm8001_dev) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("device %d not ready.\n", pm8001_dev->device_id)); } else { PM8001_IO_DBG(pm8001_ha, pm8001_printk("device %016llx not " "ready.\n", SAS_ADDR(dev->sas_addr))); } rc = SAS_PHY_DOWN; goto out_done; } port = &pm8001_ha->port[sas_find_local_port_id(dev)]; if (!port->port_attached) { if (sas_protocol_ata(t->task_proto)) { struct task_status_struct *ts = &t->task_status; ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; spin_unlock_irqrestore(&pm8001_ha->lock, flags); spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags_libsas); t->task_done(t); spin_lock_irqsave(dev->sata_dev.ap->lock, flags_libsas); spin_lock_irqsave(&pm8001_ha->lock, flags); if (n > 1) t = list_entry(t->list.next, struct sas_task, list); continue; } else { struct task_status_struct *ts = &t->task_status; ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; t->task_done(t); if (n > 1) t = list_entry(t->list.next, struct sas_task, list); continue; } } rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) goto err_out; ccb = &pm8001_ha->ccb_info[tag]; if (!sas_protocol_ata(t->task_proto)) { if (t->num_scatter) { n_elem = dma_map_sg(pm8001_ha->dev, t->scatter, t->num_scatter, t->data_dir); if (!n_elem) { rc = -ENOMEM; goto err_out_tag; } } } else { n_elem = t->num_scatter; } t->lldd_task = ccb; ccb->n_elem = n_elem; ccb->ccb_tag = tag; ccb->task = t; switch (t->task_proto) { case SAS_PROTOCOL_SMP: rc = pm8001_task_prep_smp(pm8001_ha, ccb); break; case SAS_PROTOCOL_SSP: if (is_tmf) rc = pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf); else rc = pm8001_task_prep_ssp(pm8001_ha, ccb); break; case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: rc = pm8001_task_prep_ata(pm8001_ha, ccb); break; default: dev_printk(KERN_ERR, pm8001_ha->dev, "unknown sas_task proto: 0x%x\n", t->task_proto); rc = -EINVAL; break; } if (rc) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("rc is %x\n", rc)); goto err_out_tag; } /* TODO: select normal or high priority */ spin_lock(&t->task_state_lock); t->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock(&t->task_state_lock); pm8001_dev->running_req++; if (n > 1) t = list_entry(t->list.next, struct sas_task, list); } while (--n);
static void asd_get_response_tasklet(struct asd_ascb *ascb, struct done_list_struct *dl) { struct asd_ha_struct *asd_ha = ascb->ha; struct sas_task *task = ascb->uldd_task; struct task_status_struct *ts = &task->task_status; unsigned long flags; struct tc_resp_sb_struct { __le16 index_escb; u8 len_lsb; u8 flags; } __attribute__ ((packed)) *resp_sb = (void *) dl->status_block; /* int size = ((resp_sb->flags & 7) << 8) | resp_sb->len_lsb; */ int edb_id = ((resp_sb->flags & 0x70) >> 4)-1; struct asd_ascb *escb; struct asd_dma_tok *edb; void *r; spin_lock_irqsave(&asd_ha->seq.tc_index_lock, flags); escb = asd_tc_index_find(&asd_ha->seq, (int)le16_to_cpu(resp_sb->index_escb)); spin_unlock_irqrestore(&asd_ha->seq.tc_index_lock, flags); if (!escb) { ASD_DPRINTK("Uh-oh! No escb for this dl?!\n"); return; } ts->buf_valid_size = 0; edb = asd_ha->seq.edb_arr[edb_id + escb->edb_index]; r = edb->vaddr; if (task->task_proto == SAS_PROTO_SSP) { struct ssp_response_iu *iu = r + 16 + sizeof(struct ssp_frame_hdr); ts->residual = le32_to_cpu(*(__le32 *)r); ts->resp = SAS_TASK_COMPLETE; if (iu->datapres == 0) ts->stat = iu->status; else if (iu->datapres == 1) ts->stat = iu->resp_data[3]; else if (iu->datapres == 2) { ts->stat = SAM_CHECK_COND; ts->buf_valid_size = min((u32) SAS_STATUS_BUF_SIZE, be32_to_cpu(iu->sense_data_len)); memcpy(ts->buf, iu->sense_data, ts->buf_valid_size); if (iu->status != SAM_CHECK_COND) { ASD_DPRINTK("device %llx sent sense data, but " "stat(0x%x) is not CHECK_CONDITION" "\n", SAS_ADDR(task->dev->sas_addr), ts->stat); } } } else { struct ata_task_resp *resp = (void *) &ts->buf[0]; ts->residual = le32_to_cpu(*(__le32 *)r); if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { resp->frame_len = le16_to_cpu(*(__le16 *)(r+6)); memcpy(&resp->ending_fis[0], r+16, 24); ts->buf_valid_size = sizeof(*resp); } } asd_invalidate_edb(escb, edb_id); }
void sas_dprint_porte(int phyid, enum port_event pe) { SAS_DPRINTK("phy%d: port event: %s\n", phyid, sas_porte_str[pe]); } void sas_dprint_phye(int phyid, enum phy_event pe) { SAS_DPRINTK("phy%d: phy event: %s\n", phyid, sas_phye_str[pe]); } void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he) { SAS_DPRINTK("ha %s: %s event\n", dev_name(sas_ha->dev), sas_hae_str[he]); } void sas_dump_port(struct asd_sas_port *port) { SAS_DPRINTK("port%d: class:0x%x\n", port->id, port->class); SAS_DPRINTK("port%d: sas_addr:%llx\n", port->id, SAS_ADDR(port->sas_addr)); SAS_DPRINTK("port%d: attached_sas_addr:%llx\n", port->id, SAS_ADDR(port->attached_sas_addr)); SAS_DPRINTK("port%d: iproto:0x%x\n", port->id, port->iproto); SAS_DPRINTK("port%d: tproto:0x%x\n", port->id, port->tproto); SAS_DPRINTK("port%d: oob_mode:0x%x\n", port->id, port->oob_mode); SAS_DPRINTK("port%d: num_phys:%d\n", port->id, port->num_phys); } #endif /* SAS_DEBUG */