0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #include "esas2r.h"
0045
0046 void esas2r_targ_db_initialize(struct esas2r_adapter *a)
0047 {
0048 struct esas2r_target *t;
0049
0050 for (t = a->targetdb; t < a->targetdb_end; t++) {
0051 memset(t, 0, sizeof(struct esas2r_target));
0052
0053 t->target_state = TS_NOT_PRESENT;
0054 t->buffered_target_state = TS_NOT_PRESENT;
0055 t->new_target_state = TS_INVALID;
0056 }
0057 }
0058
0059 void esas2r_targ_db_remove_all(struct esas2r_adapter *a, bool notify)
0060 {
0061 struct esas2r_target *t;
0062 unsigned long flags;
0063
0064 for (t = a->targetdb; t < a->targetdb_end; t++) {
0065 if (t->target_state != TS_PRESENT)
0066 continue;
0067
0068 spin_lock_irqsave(&a->mem_lock, flags);
0069 esas2r_targ_db_remove(a, t);
0070 spin_unlock_irqrestore(&a->mem_lock, flags);
0071
0072 if (notify) {
0073 esas2r_trace("remove id:%d", esas2r_targ_get_id(t,
0074 a));
0075 esas2r_target_state_changed(a, esas2r_targ_get_id(t,
0076 a),
0077 TS_NOT_PRESENT);
0078 }
0079 }
0080 }
0081
0082 void esas2r_targ_db_report_changes(struct esas2r_adapter *a)
0083 {
0084 struct esas2r_target *t;
0085 unsigned long flags;
0086
0087 esas2r_trace_enter();
0088
0089 if (test_bit(AF_DISC_PENDING, &a->flags)) {
0090 esas2r_trace_exit();
0091 return;
0092 }
0093
0094 for (t = a->targetdb; t < a->targetdb_end; t++) {
0095 u8 state = TS_INVALID;
0096
0097 spin_lock_irqsave(&a->mem_lock, flags);
0098 if (t->buffered_target_state != t->target_state)
0099 state = t->buffered_target_state = t->target_state;
0100
0101 spin_unlock_irqrestore(&a->mem_lock, flags);
0102 if (state != TS_INVALID) {
0103 esas2r_trace("targ_db_report_changes:%d",
0104 esas2r_targ_get_id(
0105 t,
0106 a));
0107 esas2r_trace("state:%d", state);
0108
0109 esas2r_target_state_changed(a,
0110 esas2r_targ_get_id(t,
0111 a),
0112 state);
0113 }
0114 }
0115
0116 esas2r_trace_exit();
0117 }
0118
0119 struct esas2r_target *esas2r_targ_db_add_raid(struct esas2r_adapter *a,
0120 struct esas2r_disc_context *
0121 dc)
0122 {
0123 struct esas2r_target *t;
0124
0125 esas2r_trace_enter();
0126
0127 if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
0128 esas2r_bugon();
0129 esas2r_trace_exit();
0130 return NULL;
0131 }
0132
0133 t = a->targetdb + dc->curr_virt_id;
0134
0135 if (t->target_state == TS_PRESENT) {
0136 esas2r_trace_exit();
0137 return NULL;
0138 }
0139
0140 esas2r_hdebug("add RAID %s, T:%d", dc->raid_grp_name,
0141 esas2r_targ_get_id(
0142 t,
0143 a));
0144
0145 if (dc->interleave == 0
0146 || dc->block_size == 0) {
0147
0148
0149 esas2r_hdebug("invalid RAID group dimensions");
0150
0151 esas2r_trace_exit();
0152
0153 return NULL;
0154 }
0155
0156 t->block_size = dc->block_size;
0157 t->inter_byte = dc->interleave;
0158 t->inter_block = dc->interleave / dc->block_size;
0159 t->virt_targ_id = dc->curr_virt_id;
0160 t->phys_targ_id = ESAS2R_TARG_ID_INV;
0161
0162 t->flags &= ~TF_PASS_THRU;
0163 t->flags |= TF_USED;
0164
0165 t->identifier_len = 0;
0166
0167 t->target_state = TS_PRESENT;
0168
0169 return t;
0170 }
0171
0172 struct esas2r_target *esas2r_targ_db_add_pthru(struct esas2r_adapter *a,
0173 struct esas2r_disc_context *dc,
0174 u8 *ident,
0175 u8 ident_len)
0176 {
0177 struct esas2r_target *t;
0178
0179 esas2r_trace_enter();
0180
0181 if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
0182 esas2r_bugon();
0183 esas2r_trace_exit();
0184 return NULL;
0185 }
0186
0187
0188
0189 t = esas2r_targ_db_find_by_ident(a, ident, ident_len);
0190
0191 if (t == NULL) {
0192 t = a->targetdb + dc->curr_virt_id;
0193
0194 if (ident_len > sizeof(t->identifier)
0195 || t->target_state == TS_PRESENT) {
0196 esas2r_trace_exit();
0197 return NULL;
0198 }
0199 }
0200
0201 esas2r_hdebug("add PT; T:%d, V:%d, P:%d", esas2r_targ_get_id(t, a),
0202 dc->curr_virt_id,
0203 dc->curr_phys_id);
0204
0205 t->block_size = 0;
0206 t->inter_byte = 0;
0207 t->inter_block = 0;
0208 t->virt_targ_id = dc->curr_virt_id;
0209 t->phys_targ_id = dc->curr_phys_id;
0210 t->identifier_len = ident_len;
0211
0212 memcpy(t->identifier, ident, ident_len);
0213
0214 t->flags |= TF_PASS_THRU | TF_USED;
0215
0216 t->target_state = TS_PRESENT;
0217
0218 return t;
0219 }
0220
0221 void esas2r_targ_db_remove(struct esas2r_adapter *a, struct esas2r_target *t)
0222 {
0223 esas2r_trace_enter();
0224
0225 t->target_state = TS_NOT_PRESENT;
0226
0227 esas2r_trace("remove id:%d", esas2r_targ_get_id(t, a));
0228
0229 esas2r_trace_exit();
0230 }
0231
0232 struct esas2r_target *esas2r_targ_db_find_by_sas_addr(struct esas2r_adapter *a,
0233 u64 *sas_addr)
0234 {
0235 struct esas2r_target *t;
0236
0237 for (t = a->targetdb; t < a->targetdb_end; t++)
0238 if (t->sas_addr == *sas_addr)
0239 return t;
0240
0241 return NULL;
0242 }
0243
0244 struct esas2r_target *esas2r_targ_db_find_by_ident(struct esas2r_adapter *a,
0245 void *identifier,
0246 u8 ident_len)
0247 {
0248 struct esas2r_target *t;
0249
0250 for (t = a->targetdb; t < a->targetdb_end; t++) {
0251 if (ident_len == t->identifier_len
0252 && memcmp(&t->identifier[0], identifier,
0253 ident_len) == 0)
0254 return t;
0255 }
0256
0257 return NULL;
0258 }
0259
0260 u16 esas2r_targ_db_find_next_present(struct esas2r_adapter *a, u16 target_id)
0261 {
0262 u16 id = target_id + 1;
0263
0264 while (id < ESAS2R_MAX_TARGETS) {
0265 struct esas2r_target *t = a->targetdb + id;
0266
0267 if (t->target_state == TS_PRESENT)
0268 break;
0269
0270 id++;
0271 }
0272
0273 return id;
0274 }
0275
0276 struct esas2r_target *esas2r_targ_db_find_by_virt_id(struct esas2r_adapter *a,
0277 u16 virt_id)
0278 {
0279 struct esas2r_target *t;
0280
0281 for (t = a->targetdb; t < a->targetdb_end; t++) {
0282 if (t->target_state != TS_PRESENT)
0283 continue;
0284
0285 if (t->virt_targ_id == virt_id)
0286 return t;
0287 }
0288
0289 return NULL;
0290 }
0291
0292 u16 esas2r_targ_db_get_tgt_cnt(struct esas2r_adapter *a)
0293 {
0294 u16 devcnt = 0;
0295 struct esas2r_target *t;
0296 unsigned long flags;
0297
0298 spin_lock_irqsave(&a->mem_lock, flags);
0299 for (t = a->targetdb; t < a->targetdb_end; t++)
0300 if (t->target_state == TS_PRESENT)
0301 devcnt++;
0302
0303 spin_unlock_irqrestore(&a->mem_lock, flags);
0304
0305 return devcnt;
0306 }