Beispiel #1
0
/* 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;
}
Beispiel #4
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;
}
Beispiel #5
0
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);
Beispiel #6
0
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);
}
Beispiel #7
0
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 */