cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

esas2r_targdb.c (7599B)


      1/*
      2 *  linux/drivers/scsi/esas2r/esas2r_targdb.c
      3 *      For use with ATTO ExpressSAS R6xx SAS/SATA RAID controllers
      4 *
      5 *  Copyright (c) 2001-2013 ATTO Technology, Inc.
      6 *  (mailto:linuxdrivers@attotech.com)
      7 *
      8 * This program is free software; you can redistribute it and/or
      9 * modify it under the terms of the GNU General Public License
     10 * as published by the Free Software Foundation; either version 2
     11 * of the License, or (at your option) any later version.
     12 *
     13 * This program is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 * GNU General Public License for more details.
     17 *
     18 * NO WARRANTY
     19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
     20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
     21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
     22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
     23 * solely responsible for determining the appropriateness of using and
     24 * distributing the Program and assumes all risks associated with its
     25 * exercise of rights under this Agreement, including but not limited to
     26 * the risks and costs of program errors, damage to or loss of data,
     27 * programs or equipment, and unavailability or interruption of operations.
     28 *
     29 * DISCLAIMER OF LIABILITY
     30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
     31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
     33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
     35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
     36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
     37 *
     38 * You should have received a copy of the GNU General Public License
     39 * along with this program; if not, write to the Free Software
     40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
     41 * USA.
     42 */
     43
     44#include "esas2r.h"
     45
     46void esas2r_targ_db_initialize(struct esas2r_adapter *a)
     47{
     48	struct esas2r_target *t;
     49
     50	for (t = a->targetdb; t < a->targetdb_end; t++) {
     51		memset(t, 0, sizeof(struct esas2r_target));
     52
     53		t->target_state = TS_NOT_PRESENT;
     54		t->buffered_target_state = TS_NOT_PRESENT;
     55		t->new_target_state = TS_INVALID;
     56	}
     57}
     58
     59void esas2r_targ_db_remove_all(struct esas2r_adapter *a, bool notify)
     60{
     61	struct esas2r_target *t;
     62	unsigned long flags;
     63
     64	for (t = a->targetdb; t < a->targetdb_end; t++) {
     65		if (t->target_state != TS_PRESENT)
     66			continue;
     67
     68		spin_lock_irqsave(&a->mem_lock, flags);
     69		esas2r_targ_db_remove(a, t);
     70		spin_unlock_irqrestore(&a->mem_lock, flags);
     71
     72		if (notify) {
     73			esas2r_trace("remove id:%d", esas2r_targ_get_id(t,
     74									a));
     75			esas2r_target_state_changed(a, esas2r_targ_get_id(t,
     76									  a),
     77						    TS_NOT_PRESENT);
     78		}
     79	}
     80}
     81
     82void esas2r_targ_db_report_changes(struct esas2r_adapter *a)
     83{
     84	struct esas2r_target *t;
     85	unsigned long flags;
     86
     87	esas2r_trace_enter();
     88
     89	if (test_bit(AF_DISC_PENDING, &a->flags)) {
     90		esas2r_trace_exit();
     91		return;
     92	}
     93
     94	for (t = a->targetdb; t < a->targetdb_end; t++) {
     95		u8 state = TS_INVALID;
     96
     97		spin_lock_irqsave(&a->mem_lock, flags);
     98		if (t->buffered_target_state != t->target_state)
     99			state = t->buffered_target_state = t->target_state;
    100
    101		spin_unlock_irqrestore(&a->mem_lock, flags);
    102		if (state != TS_INVALID) {
    103			esas2r_trace("targ_db_report_changes:%d",
    104				     esas2r_targ_get_id(
    105					     t,
    106					     a));
    107			esas2r_trace("state:%d", state);
    108
    109			esas2r_target_state_changed(a,
    110						    esas2r_targ_get_id(t,
    111								       a),
    112						    state);
    113		}
    114	}
    115
    116	esas2r_trace_exit();
    117}
    118
    119struct esas2r_target *esas2r_targ_db_add_raid(struct esas2r_adapter *a,
    120					      struct esas2r_disc_context *
    121					      dc)
    122{
    123	struct esas2r_target *t;
    124
    125	esas2r_trace_enter();
    126
    127	if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
    128		esas2r_bugon();
    129		esas2r_trace_exit();
    130		return NULL;
    131	}
    132
    133	t = a->targetdb + dc->curr_virt_id;
    134
    135	if (t->target_state == TS_PRESENT) {
    136		esas2r_trace_exit();
    137		return NULL;
    138	}
    139
    140	esas2r_hdebug("add RAID %s, T:%d", dc->raid_grp_name,
    141		      esas2r_targ_get_id(
    142			      t,
    143			      a));
    144
    145	if (dc->interleave == 0
    146	    || dc->block_size  == 0) {
    147		/* these are invalid values, don't create the target entry. */
    148
    149		esas2r_hdebug("invalid RAID group dimensions");
    150
    151		esas2r_trace_exit();
    152
    153		return NULL;
    154	}
    155
    156	t->block_size = dc->block_size;
    157	t->inter_byte = dc->interleave;
    158	t->inter_block = dc->interleave / dc->block_size;
    159	t->virt_targ_id = dc->curr_virt_id;
    160	t->phys_targ_id = ESAS2R_TARG_ID_INV;
    161
    162	t->flags &= ~TF_PASS_THRU;
    163	t->flags |= TF_USED;
    164
    165	t->identifier_len = 0;
    166
    167	t->target_state = TS_PRESENT;
    168
    169	return t;
    170}
    171
    172struct esas2r_target *esas2r_targ_db_add_pthru(struct esas2r_adapter *a,
    173					       struct esas2r_disc_context *dc,
    174					       u8 *ident,
    175					       u8 ident_len)
    176{
    177	struct esas2r_target *t;
    178
    179	esas2r_trace_enter();
    180
    181	if (dc->curr_virt_id >= ESAS2R_MAX_TARGETS) {
    182		esas2r_bugon();
    183		esas2r_trace_exit();
    184		return NULL;
    185	}
    186
    187	/* see if we found this device before. */
    188
    189	t = esas2r_targ_db_find_by_ident(a, ident, ident_len);
    190
    191	if (t == NULL) {
    192		t = a->targetdb + dc->curr_virt_id;
    193
    194		if (ident_len > sizeof(t->identifier)
    195		    || t->target_state == TS_PRESENT) {
    196			esas2r_trace_exit();
    197			return NULL;
    198		}
    199	}
    200
    201	esas2r_hdebug("add PT; T:%d, V:%d, P:%d", esas2r_targ_get_id(t, a),
    202		      dc->curr_virt_id,
    203		      dc->curr_phys_id);
    204
    205	t->block_size = 0;
    206	t->inter_byte = 0;
    207	t->inter_block = 0;
    208	t->virt_targ_id = dc->curr_virt_id;
    209	t->phys_targ_id = dc->curr_phys_id;
    210	t->identifier_len = ident_len;
    211
    212	memcpy(t->identifier, ident, ident_len);
    213
    214	t->flags |= TF_PASS_THRU | TF_USED;
    215
    216	t->target_state = TS_PRESENT;
    217
    218	return t;
    219}
    220
    221void esas2r_targ_db_remove(struct esas2r_adapter *a, struct esas2r_target *t)
    222{
    223	esas2r_trace_enter();
    224
    225	t->target_state = TS_NOT_PRESENT;
    226
    227	esas2r_trace("remove id:%d", esas2r_targ_get_id(t, a));
    228
    229	esas2r_trace_exit();
    230}
    231
    232struct esas2r_target *esas2r_targ_db_find_by_sas_addr(struct esas2r_adapter *a,
    233						      u64 *sas_addr)
    234{
    235	struct esas2r_target *t;
    236
    237	for (t = a->targetdb; t < a->targetdb_end; t++)
    238		if (t->sas_addr == *sas_addr)
    239			return t;
    240
    241	return NULL;
    242}
    243
    244struct esas2r_target *esas2r_targ_db_find_by_ident(struct esas2r_adapter *a,
    245						   void *identifier,
    246						   u8 ident_len)
    247{
    248	struct esas2r_target *t;
    249
    250	for (t = a->targetdb; t < a->targetdb_end; t++) {
    251		if (ident_len == t->identifier_len
    252		    && memcmp(&t->identifier[0], identifier,
    253			      ident_len) == 0)
    254			return t;
    255	}
    256
    257	return NULL;
    258}
    259
    260u16 esas2r_targ_db_find_next_present(struct esas2r_adapter *a, u16 target_id)
    261{
    262	u16 id = target_id + 1;
    263
    264	while (id < ESAS2R_MAX_TARGETS) {
    265		struct esas2r_target *t = a->targetdb + id;
    266
    267		if (t->target_state == TS_PRESENT)
    268			break;
    269
    270		id++;
    271	}
    272
    273	return id;
    274}
    275
    276struct esas2r_target *esas2r_targ_db_find_by_virt_id(struct esas2r_adapter *a,
    277						     u16 virt_id)
    278{
    279	struct esas2r_target *t;
    280
    281	for (t = a->targetdb; t < a->targetdb_end; t++) {
    282		if (t->target_state != TS_PRESENT)
    283			continue;
    284
    285		if (t->virt_targ_id == virt_id)
    286			return t;
    287	}
    288
    289	return NULL;
    290}
    291
    292u16 esas2r_targ_db_get_tgt_cnt(struct esas2r_adapter *a)
    293{
    294	u16 devcnt = 0;
    295	struct esas2r_target *t;
    296	unsigned long flags;
    297
    298	spin_lock_irqsave(&a->mem_lock, flags);
    299	for (t = a->targetdb; t < a->targetdb_end; t++)
    300		if (t->target_state == TS_PRESENT)
    301			devcnt++;
    302
    303	spin_unlock_irqrestore(&a->mem_lock, flags);
    304
    305	return devcnt;
    306}