/* 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; }
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; }
/* * 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; }
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; }