Ejemplo n.º 1
0
/* Validate the cached NVRAM.  if the NVRAM is invalid, load the defaults. */
bool esas2r_nvram_validate(struct esas2r_adapter *a)
{
	struct esas2r_sas_nvram *n = a->nvram;
	bool rslt = false;

	if (n->signature[0] != 'E'
	    || n->signature[1] != 'S'
	    || n->signature[2] != 'A'
	    || n->signature[3] != 'S') {
		esas2r_hdebug("invalid NVRAM signature");
	} else if (esas2r_nvramcalc_cksum(n)) {
		esas2r_hdebug("invalid NVRAM checksum");
	} else if (n->version > SASNVR_VERSION) {
		esas2r_hdebug("invalid NVRAM version");
	} else {
		set_bit(AF_NVR_VALID, &a->flags);
		rslt = true;
	}

	if (rslt == false) {
		esas2r_hdebug("using defaults");
		esas2r_nvram_set_defaults(a);
	}

	return rslt;
}
Ejemplo n.º 2
0
static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function)
{
	u32 starttime;
	u32 timeout;
	u32 intstat;
	u32 doorbell;

	/* Disable chip interrupts awhile */
	if (function == DRBL_FLASH_REQ)
		esas2r_disable_chip_interrupts(a);

	/* Issue the request to the firmware */
	esas2r_write_register_dword(a, MU_DOORBELL_IN, function);

	/* Now wait for the firmware to process it */
	starttime = jiffies_to_msecs(jiffies);
	timeout = a->flags &
		  (AF_CHPRST_PENDING | AF_DISC_PENDING) ? 40000 : 5000;

	while (true) {
		intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT);

		if (intstat & MU_INTSTAT_DRBL) {
			/* Got a doorbell interrupt.  Check for the function */
			doorbell =
				esas2r_read_register_dword(a, MU_DOORBELL_OUT);
			esas2r_write_register_dword(a, MU_DOORBELL_OUT,
						    doorbell);
			if (doorbell & function)
				break;
		}

		schedule_timeout_interruptible(msecs_to_jiffies(100));

		if ((jiffies_to_msecs(jiffies) - starttime) > timeout) {
			/*
			 * Iimeout.  If we were requesting flash access,
			 * indicate we are done so the firmware knows we gave
			 * up.  If this was a REQ, we also need to re-enable
			 * chip interrupts.
			 */
			if (function == DRBL_FLASH_REQ) {
				esas2r_hdebug("flash access timeout");
				esas2r_write_register_dword(a, MU_DOORBELL_IN,
							    DRBL_FLASH_DONE);
				esas2r_enable_chip_interrupts(a);
			} else {
				esas2r_hdebug("flash release timeout");
			}

			return false;
		}
	}

	/* if we're done, re-enable chip interrupts */
	if (function == DRBL_FLASH_DONE)
		esas2r_enable_chip_interrupts(a);

	return true;
}
struct esas2r_target *esas2r_targ_db_add_raid(struct esas2r_adapter *a,
					      struct esas2r_disc_context *
					      dc)
{
	struct esas2r_target *t;

	esas2r_trace_enter();

	if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
		esas2r_bugon();
		esas2r_trace_exit();
		return NULL;
	}

	t = a->targetdb + dc->curr_virt_id;

	if (t->target_state == TS_PRESENT) {
		esas2r_trace_exit();
		return NULL;
	}

	esas2r_hdebug("add RAID %s, T:%d", dc->raid_grp_name,
		      esas2r_targ_get_id(
			      t,
			      a));

	if (dc->interleave == 0
	    || dc->block_size  == 0) {
		/* these are invalid values, don't create the target entry. */

		esas2r_hdebug("invalid RAID group dimensions");

		esas2r_trace_exit();

		return NULL;
	}

	t->block_size = dc->block_size;
	t->inter_byte = dc->interleave;
	t->inter_block = dc->interleave / dc->block_size;
	t->virt_targ_id = dc->curr_virt_id;
	t->phys_targ_id = ESAS2R_TARG_ID_INV;

	t->flags &= ~TF_PASS_THRU;
	t->flags |= TF_USED;

	t->identifier_len = 0;

	t->target_state = TS_PRESENT;

	return t;
}
struct esas2r_target *esas2r_targ_db_add_pthru(struct esas2r_adapter *a,
					       struct esas2r_disc_context *dc,
					       u8 *ident,
					       u8 ident_len)
{
	struct esas2r_target *t;

	esas2r_trace_enter();

	if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
		esas2r_bugon();
		esas2r_trace_exit();
		return NULL;
	}

	/* see if we found this device before. */

	t = esas2r_targ_db_find_by_ident(a, ident, ident_len);

	if (t == NULL) {
		t = a->targetdb + dc->curr_virt_id;

		if (ident_len > sizeof(t->identifier)
		    || t->target_state == TS_PRESENT) {
			esas2r_trace_exit();
			return NULL;
		}
	}

	esas2r_hdebug("add PT; T:%d, V:%d, P:%d", esas2r_targ_get_id(t, a),
		      dc->curr_virt_id,
		      dc->curr_phys_id);

	t->block_size = 0;
	t->inter_byte = 0;
	t->inter_block = 0;
	t->virt_targ_id = dc->curr_virt_id;
	t->phys_targ_id = dc->curr_phys_id;
	t->identifier_len = ident_len;

	memcpy(t->identifier, ident, ident_len);

	t->flags |= TF_PASS_THRU | TF_USED;

	t->target_state = TS_PRESENT;

	return t;
}
Ejemplo n.º 5
0
/*
 *  Read and validate current NVRAM parameters by accessing
 *  physical NVRAM directly.  if currently stored parameters are
 *  invalid, use the defaults.
 */
bool esas2r_nvram_read_direct(struct esas2r_adapter *a)
{
	bool result;

	if (down_interruptible(&a->nvram_semaphore))
		return false;

	if (!esas2r_read_flash_block(a, a->nvram, FLS_OFFSET_NVR,
				     sizeof(struct esas2r_sas_nvram))) {
		esas2r_hdebug("NVRAM read failed, using defaults");
		return false;
	}

	result = esas2r_nvram_validate(a);

	up(&a->nvram_semaphore);

	return result;
}
Ejemplo n.º 6
0
bool esas2r_print_flash_rev(struct esas2r_adapter *a)
{
	u16 year = LOWORD(a->flash_ver);
	u8 day = LOBYTE(HIWORD(a->flash_ver));
	u8 month = HIBYTE(HIWORD(a->flash_ver));

	if (day == 0
	    || month == 0
	    || day > 31
	    || month > 12
	    || year < 2006
	    || year > 9999) {
		strcpy(a->flash_rev, "not found");
		a->flash_ver = 0;
		return false;
	}

	sprintf(a->flash_rev, "%02d/%02d/%04d", month, day, year);
	esas2r_hdebug("flash version: %s", a->flash_rev);
	return true;
}