xref: /titanic_51/usr/src/uts/sun4u/os/plat_ecc_dimm.c (revision 07d06da50d310a325b457d6330165aebab1e0064)
103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
503831d35Sstevel  * Common Development and Distribution License (the "License").
603831d35Sstevel  * You may not use this file except in compliance with the License.
703831d35Sstevel  *
803831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel  * See the License for the specific language governing permissions
1103831d35Sstevel  * and limitations under the License.
1203831d35Sstevel  *
1303831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel  *
1903831d35Sstevel  * CDDL HEADER END
2003831d35Sstevel  */
21*07d06da5SSurya Prakki 
2203831d35Sstevel /*
23*07d06da5SSurya Prakki  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2403831d35Sstevel  * Use is subject to license terms.
2503831d35Sstevel  */
2603831d35Sstevel 
2703831d35Sstevel #include <sys/ddi.h>
2803831d35Sstevel #include <sys/plat_ecc_dimm.h>
2903831d35Sstevel 
3003831d35Sstevel extern int plat_max_mc_units_per_board(void);
3103831d35Sstevel extern int plat_ecc_dispatch_task(plat_ecc_message_t *);
3203831d35Sstevel 
3303831d35Sstevel /* Platform specific function to get DIMM offset information */
3403831d35Sstevel int (*p2get_mem_offset)(uint64_t, uint64_t *);
3503831d35Sstevel 
3603831d35Sstevel /* Platform specific function to get dimm serial id information */
3703831d35Sstevel int (*p2get_mem_sid)(int, int, char *, int, int *);
3803831d35Sstevel 
3903831d35Sstevel /*
4003831d35Sstevel  * Platform specific function to convert a DIMM location/serial id and
4103831d35Sstevel  * offset into a physical address.
4203831d35Sstevel  */
4303831d35Sstevel int (*p2get_mem_addr)(int, char *, uint64_t, uint64_t *);
4403831d35Sstevel 
4503831d35Sstevel /*
4603831d35Sstevel  * Timeouts variable for determining when to give up waiting for a
4703831d35Sstevel  * response from the SC.  The value is in seconds and the default is
4803831d35Sstevel  * based on the current default mailbox timeout used for Serengeti
4903831d35Sstevel  * mailbox requests which is 30 seconds (Starcat uses a smaller value).
5003831d35Sstevel  */
5103831d35Sstevel int plat_dimm_req_timeout = 30;
5203831d35Sstevel int plat_dimm_req_min_timeout = 6;
5303831d35Sstevel 
5403831d35Sstevel /* Number of times to retries DIMM serial id requests */
5503831d35Sstevel int plat_dimm_req_max_retries = 1;
5603831d35Sstevel 
5703831d35Sstevel static void  plat_request_all_mem_sids(uint32_t);
5803831d35Sstevel 
5903831d35Sstevel int
6003831d35Sstevel plat_get_mem_sid(char *unum, char *buf, int buflen, int *lenp)
6103831d35Sstevel {
6203831d35Sstevel 	int	board, pos, bank, dimm, jnumber;
6303831d35Sstevel 	int	mcid;
6403831d35Sstevel 
6503831d35Sstevel 	if (p2get_mem_sid == NULL ||
6603831d35Sstevel 	    (plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE) == 0))
6703831d35Sstevel 		return (ENOTSUP);
6803831d35Sstevel 
6903831d35Sstevel 	if (parse_unum_memory(unum, &board, &pos, &bank, &dimm,
7003831d35Sstevel 	    &jnumber) != 0)
7103831d35Sstevel 		return (EINVAL);
7203831d35Sstevel 
7303831d35Sstevel 	if (dimm < 0)
7403831d35Sstevel 		return (EINVAL);
7503831d35Sstevel 
7603831d35Sstevel 	mcid = plat_make_fru_cpuid(board, 0, pos);
7703831d35Sstevel 	dimm += (bank * 4);	/* convert dimm from 0-3 to 0-7 value */
7803831d35Sstevel 
7903831d35Sstevel 	return (p2get_mem_sid(mcid, dimm, buf, buflen, lenp));
8003831d35Sstevel }
8103831d35Sstevel 
8203831d35Sstevel int
8303831d35Sstevel plat_get_mem_offset(uint64_t paddr, uint64_t *offp)
8403831d35Sstevel {
8503831d35Sstevel 	if (p2get_mem_offset != NULL) {
8603831d35Sstevel 		return (p2get_mem_offset(paddr, offp));
8703831d35Sstevel 	} else
8803831d35Sstevel 		return (ENOTSUP);
8903831d35Sstevel }
9003831d35Sstevel 
9103831d35Sstevel int
9203831d35Sstevel plat_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *addrp)
9303831d35Sstevel {
9403831d35Sstevel 	int	board, pos, bank, dimm, jnumber;
9503831d35Sstevel 	int	mcid;
9603831d35Sstevel 
9703831d35Sstevel 	if (p2get_mem_addr == NULL ||
9803831d35Sstevel 	    (plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE) == 0))
9903831d35Sstevel 		return (ENOTSUP);
10003831d35Sstevel 
10103831d35Sstevel 	if (parse_unum_memory(unum, &board, &pos, &bank, &dimm,
10203831d35Sstevel 	    &jnumber) != 0)
10303831d35Sstevel 		return (EINVAL);
10403831d35Sstevel 
10503831d35Sstevel 	mcid = plat_make_fru_cpuid(board, 0, pos);
10603831d35Sstevel 
10703831d35Sstevel 	return (p2get_mem_addr(mcid, sid, offset, addrp));
10803831d35Sstevel }
10903831d35Sstevel 
11003831d35Sstevel dimm_sid_cache_t *
11103831d35Sstevel plat_alloc_sid_cache(int *max_entries)
11203831d35Sstevel {
11303831d35Sstevel 	dimm_sid_cache_t *cache;
11403831d35Sstevel 	int i, bd, p;
11503831d35Sstevel 	int max_mc_per_bd = plat_max_mc_units_per_board();
11603831d35Sstevel 
11703831d35Sstevel 	*max_entries = plat_max_cpumem_boards() * max_mc_per_bd;
11803831d35Sstevel 
11903831d35Sstevel 	cache = (dimm_sid_cache_t *)kmem_zalloc(sizeof (dimm_sid_cache_t) *
12003831d35Sstevel 	    *max_entries, KM_SLEEP);
12103831d35Sstevel 
12203831d35Sstevel 	for (i = 0; i < *max_entries; i++) {
12303831d35Sstevel 		bd = i / max_mc_per_bd;
12403831d35Sstevel 		p = i % max_mc_per_bd;
12503831d35Sstevel 		cache[i].mcid = plat_make_fru_cpuid(bd, 0, p);
12603831d35Sstevel 	}
12703831d35Sstevel 
12803831d35Sstevel 	return (cache);
12903831d35Sstevel }
13003831d35Sstevel 
13103831d35Sstevel static void
13203831d35Sstevel plat_populate_sid_cache_one(dimm_sid_cache_t *cache, int bd)
13303831d35Sstevel {
13403831d35Sstevel 	int		i, j;
13503831d35Sstevel 	uint8_t		valid;
13603831d35Sstevel 	dimm_sid_t	*dimmsidsp;
13703831d35Sstevel 	int		max_mc_per_bd = plat_max_mc_units_per_board();
13803831d35Sstevel 
13903831d35Sstevel 
14003831d35Sstevel 	/*
14103831d35Sstevel 	 * There must be at least one dimm on the board for this
14203831d35Sstevel 	 * code to be called.
14303831d35Sstevel 	 */
14403831d35Sstevel 	ASSERT(domain_dimm_sids[bd].pdsb_valid_bitmap);
14503831d35Sstevel 
14603831d35Sstevel 	for (i = 0; i < max_mc_per_bd; i++) {
14703831d35Sstevel 		int index = bd * max_mc_per_bd + i;
14803831d35Sstevel 
14903831d35Sstevel 		/*
15003831d35Sstevel 		 * Each entry in the cache represents one mc.
15103831d35Sstevel 		 * If state is not MC_DIMM_SIDS_REQUESTED, then that mc
15203831d35Sstevel 		 * either has no DIMMs, is not present, or already has
15303831d35Sstevel 		 * DIMM serial ids available from a previous call to this
15403831d35Sstevel 		 * function.
15503831d35Sstevel 		 */
15603831d35Sstevel 		if (cache[index].state != MC_DIMM_SIDS_REQUESTED)
15703831d35Sstevel 			continue;
15803831d35Sstevel 
15903831d35Sstevel 		valid = domain_dimm_sids[bd].pdsb_valid_bitmap >> (i * 8) &
16003831d35Sstevel 		    0xff;
16103831d35Sstevel 
16203831d35Sstevel 		dimmsidsp = cache[index].sids;
16303831d35Sstevel 
16403831d35Sstevel 		/*
16503831d35Sstevel 		 * Copy the valid DIMM serial ids.  Each mc can have up to
16603831d35Sstevel 		 * eight DIMMs.
16703831d35Sstevel 		 */
16803831d35Sstevel 		for (j = 0; j < 8; j++) {
16903831d35Sstevel 			if (((1 << j) & valid) == 0)
17003831d35Sstevel 				continue;
17103831d35Sstevel 
172*07d06da5SSurya Prakki 			(void) strncpy(dimmsidsp[j],
17303831d35Sstevel 			    domain_dimm_sids[bd].pdsb_dimm_sids[(i * 8) + j],
17403831d35Sstevel 			    PLAT_MAX_DIMM_SID_LEN);
17503831d35Sstevel 		}
17603831d35Sstevel 
17703831d35Sstevel 		cache[index].state = MC_DIMM_SIDS_AVAILABLE;
17803831d35Sstevel 	}
17903831d35Sstevel }
18003831d35Sstevel 
18103831d35Sstevel int
18203831d35Sstevel plat_populate_sid_cache(dimm_sid_cache_t *cache, int max_entries)
18303831d35Sstevel {
18403831d35Sstevel 	int		i;
18503831d35Sstevel 	int		bd;
18603831d35Sstevel 	uint32_t	bds = 0, retry_bds = 0;
18703831d35Sstevel 	int		max_mc_per_bd = plat_max_mc_units_per_board();
18803831d35Sstevel 	clock_t		start_lbolt, current_lbolt;
18903831d35Sstevel 	ulong_t		elapsed_sec;
19003831d35Sstevel 	int		max_retries = plat_dimm_req_max_retries;
19103831d35Sstevel 
19203831d35Sstevel 	for (i = 0; i < max_entries; i++) {
19303831d35Sstevel 		if (cache[i].state == MC_DIMM_SIDS_REQUESTED) {
19403831d35Sstevel 			bd = i / max_mc_per_bd;
19503831d35Sstevel 			bds |= (1 << bd);
19603831d35Sstevel 		}
19703831d35Sstevel 	}
19803831d35Sstevel 
19903831d35Sstevel retry:
20003831d35Sstevel 	plat_request_all_mem_sids(bds);
20103831d35Sstevel 
20203831d35Sstevel 	/*
20303831d35Sstevel 	 * Wait for mailbox messages from SC.
20403831d35Sstevel 	 * Keep track of elapsed time in order to avoid getting
20503831d35Sstevel 	 * stuck here if something is wrong with the SC.
20603831d35Sstevel 	 */
20703831d35Sstevel 	if (plat_dimm_req_timeout < plat_dimm_req_min_timeout) {
20803831d35Sstevel 		cmn_err(CE_WARN, "plat_dimm_req_timeout (%d secs) is less "
20903831d35Sstevel 		    "than the minimum value (%d secs).  Resetting to "
21003831d35Sstevel 		    "minimum.", plat_dimm_req_timeout,
21103831d35Sstevel 		    plat_dimm_req_min_timeout);
21203831d35Sstevel 		plat_dimm_req_timeout = plat_dimm_req_min_timeout;
21303831d35Sstevel 	}
21403831d35Sstevel 
21503831d35Sstevel 	start_lbolt = ddi_get_lbolt();
21603831d35Sstevel 
21703831d35Sstevel 	while (bds) {
21803831d35Sstevel 		for (bd = 0; bd < plat_max_cpumem_boards(); bd++) {
21903831d35Sstevel 			if (((1 << bd) & bds) == 0)
22003831d35Sstevel 				continue;
22103831d35Sstevel 
22203831d35Sstevel 			switch (domain_dimm_sids[bd].pdsb_state) {
22303831d35Sstevel 			case PDSB_STATE_STORE_IN_PROGRESS:
22403831d35Sstevel 				/* Check elapsed time for possible timeout. */
22503831d35Sstevel 				current_lbolt = ddi_get_lbolt();
22603831d35Sstevel 				elapsed_sec = TICK_TO_SEC(current_lbolt -
22703831d35Sstevel 				    start_lbolt);
22803831d35Sstevel 				if (elapsed_sec > plat_dimm_req_timeout) {
22903831d35Sstevel 					mutex_enter(&domain_dimm_sids[bd].
23003831d35Sstevel 					    pdsb_lock);
23103831d35Sstevel 					domain_dimm_sids[bd].pdsb_state =
23203831d35Sstevel 					    PDSB_STATE_FAILED_TO_STORE;
23303831d35Sstevel 					mutex_exit(&domain_dimm_sids[bd].
23403831d35Sstevel 					    pdsb_lock);
23503831d35Sstevel 				}
23603831d35Sstevel 				continue;
23703831d35Sstevel 
23803831d35Sstevel 			case PDSB_STATE_FAILED_TO_STORE:
23903831d35Sstevel 				/* Record board# for possible retry */
24003831d35Sstevel 				retry_bds |= (1 << bd);
24103831d35Sstevel 				break;
24203831d35Sstevel 
24303831d35Sstevel 			case PDSB_STATE_STORED:
24403831d35Sstevel 				/* Success! */
24503831d35Sstevel 				plat_populate_sid_cache_one(cache, bd);
24603831d35Sstevel 				break;
24703831d35Sstevel 
24803831d35Sstevel 			default:
24903831d35Sstevel 				cmn_err(CE_PANIC, "Unknown state (0x%x) for "
25003831d35Sstevel 				    "domain_dimm_sids[%d]",
25103831d35Sstevel 				    domain_dimm_sids[bd].pdsb_state, bd);
25203831d35Sstevel 			}
25303831d35Sstevel 
25403831d35Sstevel 			bds &= ~(1 << bd);
25503831d35Sstevel 		}
25603831d35Sstevel 		/*
25703831d35Sstevel 		 * If there are still outstanding requests, delay for one half
25803831d35Sstevel 		 * second to avoid excessive busy waiting.
25903831d35Sstevel 		 */
26003831d35Sstevel 		if (bds != 0)
26103831d35Sstevel 			delay(drv_usectohz(500000));
26203831d35Sstevel 	}
26303831d35Sstevel 
26403831d35Sstevel 	if (max_retries-- && retry_bds) {
26503831d35Sstevel 		bds = retry_bds;
26603831d35Sstevel 		retry_bds = 0;
26703831d35Sstevel 		goto retry;
26803831d35Sstevel 	} else if (!max_retries && retry_bds) {
26903831d35Sstevel 		cmn_err(CE_WARN, "!Unable to retrieve DIMM serial ids for "
27003831d35Sstevel 		    "boards 0x%x", retry_bds);
27103831d35Sstevel 		return (ETIMEDOUT);
27203831d35Sstevel 	}
27303831d35Sstevel 
27403831d35Sstevel 	return (0);
27503831d35Sstevel }
27603831d35Sstevel 
27703831d35Sstevel /*
27803831d35Sstevel  * Functions for requesting DIMM serial id information from the SC and
27903831d35Sstevel  * updating and storing it on the domain for use by the Memory Controller
28003831d35Sstevel  * driver.
28103831d35Sstevel  */
28203831d35Sstevel 
28303831d35Sstevel /*
28403831d35Sstevel  * Adds DIMM serial id data received from the SC to the domain_dimm_sids[]
28503831d35Sstevel  * array. Called by the Serengeti and Starcat mailbox code that handles the
28603831d35Sstevel  * reply message from the SC containing a plat_dimm_sid_board_data_t.
28703831d35Sstevel  */
28803831d35Sstevel int
28903831d35Sstevel plat_store_mem_sids(plat_dimm_sid_board_data_t *data)
29003831d35Sstevel {
29103831d35Sstevel 	int	bd;
29203831d35Sstevel 	int	i;
29303831d35Sstevel 
29403831d35Sstevel 	bd = data->pdsbd_board_num;
29503831d35Sstevel 
29603831d35Sstevel 	mutex_enter(&domain_dimm_sids[bd].pdsb_lock);
29703831d35Sstevel 
29803831d35Sstevel 	if (data->pdsbd_errno) {
29903831d35Sstevel 		domain_dimm_sids[bd].pdsb_state = PDSB_STATE_FAILED_TO_STORE;
30003831d35Sstevel 		mutex_exit(&domain_dimm_sids[bd].pdsb_lock);
30103831d35Sstevel 		cmn_err(CE_WARN, "!plat_store_mem_sids: bd %d  errno %d", bd,
30203831d35Sstevel 		    data->pdsbd_errno);
30303831d35Sstevel 		return (data->pdsbd_errno);
30403831d35Sstevel 	}
30503831d35Sstevel 
30603831d35Sstevel 	domain_dimm_sids[bd].pdsb_valid_bitmap = data->pdsbd_valid_bitmap;
30703831d35Sstevel 	for (i = 0; i < PLAT_MAX_DIMMS_PER_BOARD; i++) {
30803831d35Sstevel 		if ((1 << i) & domain_dimm_sids[bd].pdsb_valid_bitmap) {
309*07d06da5SSurya Prakki 			(void) strncpy(domain_dimm_sids[bd].pdsb_dimm_sids[i],
31003831d35Sstevel 			    data->pdsbd_dimm_sids[i], PLAT_MAX_DIMM_SID_LEN);
31103831d35Sstevel 		}
31203831d35Sstevel 	}
31303831d35Sstevel 	domain_dimm_sids[bd].pdsb_state = PDSB_STATE_STORED;
31403831d35Sstevel 
31503831d35Sstevel 	mutex_exit(&domain_dimm_sids[bd].pdsb_lock);
31603831d35Sstevel 
31703831d35Sstevel 	return (0);
31803831d35Sstevel }
31903831d35Sstevel 
32003831d35Sstevel /*
32103831d35Sstevel  * Calls plat_request_mem_sids(bd) for each board number present in the domain.
32203831d35Sstevel  * Called the first time the capability exchange is successful and the SC
32303831d35Sstevel  * capability indicates support for providing DIMM serial ids.
32403831d35Sstevel  *
32503831d35Sstevel  * The input argument is a bitmask of cpu/mem boards that are present and
32603831d35Sstevel  * have at least one memory controller configured.
32703831d35Sstevel  */
32803831d35Sstevel static void
32903831d35Sstevel plat_request_all_mem_sids(uint32_t bds)
33003831d35Sstevel {
33103831d35Sstevel 	int	bd;
33203831d35Sstevel 	int	ret;
33303831d35Sstevel 
33403831d35Sstevel 	for (bd = 0; bd < plat_max_cpumem_boards(); bd++) {
33503831d35Sstevel 		if (!((1 << bd) & bds))
33603831d35Sstevel 			continue;
33703831d35Sstevel 
33803831d35Sstevel 		ret = plat_request_mem_sids(bd);
33903831d35Sstevel 		if (ret) {
34003831d35Sstevel 			mutex_enter(&domain_dimm_sids[bd].pdsb_lock);
34103831d35Sstevel 			domain_dimm_sids[bd].pdsb_state =
34203831d35Sstevel 			    PDSB_STATE_FAILED_TO_STORE;
34303831d35Sstevel 			mutex_exit(&domain_dimm_sids[bd].pdsb_lock);
34403831d35Sstevel 		}
34503831d35Sstevel 	}
34603831d35Sstevel }
34703831d35Sstevel 
34803831d35Sstevel /*
34903831d35Sstevel  * Initiates a mailbox request to SC for DIMM serial ids for the specified
35003831d35Sstevel  * board number.  Called by DR when a CPU/Mem board is connected.  Also
35103831d35Sstevel  * called by plat_request_all_mem_sids().
35203831d35Sstevel  */
35303831d35Sstevel int
35403831d35Sstevel plat_request_mem_sids(int boardnum)
35503831d35Sstevel {
35603831d35Sstevel 	plat_ecc_message_t		*wrapperp;
35703831d35Sstevel 	plat_dimm_sid_request_data_t	*dreqp;
35803831d35Sstevel 
35903831d35Sstevel 	if (domain_dimm_sids[boardnum].pdsb_state == PDSB_STATE_STORED)
36003831d35Sstevel 		return (0);
36103831d35Sstevel 
36203831d35Sstevel 	mutex_enter(&domain_dimm_sids[boardnum].pdsb_lock);
36303831d35Sstevel 	domain_dimm_sids[boardnum].pdsb_state = PDSB_STATE_STORE_IN_PROGRESS;
36403831d35Sstevel 	mutex_exit(&domain_dimm_sids[boardnum].pdsb_lock);
36503831d35Sstevel 
36603831d35Sstevel 	wrapperp = kmem_zalloc(sizeof (plat_ecc_message_t), KM_SLEEP);
36703831d35Sstevel 
36803831d35Sstevel 	/* Initialize the wrapper */
36903831d35Sstevel 	wrapperp->ecc_msg_status = PLAT_ECC_NO_MSG_ACTIVE;
37003831d35Sstevel 	wrapperp->ecc_msg_type = PLAT_ECC_DIMM_SID_MESSAGE;
37103831d35Sstevel 	wrapperp->ecc_msg_len = sizeof (plat_dimm_sid_request_data_t);
37203831d35Sstevel 	wrapperp->ecc_msg_data = kmem_zalloc(wrapperp->ecc_msg_len, KM_SLEEP);
37303831d35Sstevel 
37403831d35Sstevel 	dreqp = (plat_dimm_sid_request_data_t *)wrapperp->ecc_msg_data;
37503831d35Sstevel 
37603831d35Sstevel 	/* Fill the header */
37703831d35Sstevel 	dreqp->pdsrd_major_version = PLAT_ECC_DIMM_SID_VERSION_MAJOR;
37803831d35Sstevel 	dreqp->pdsrd_minor_version = PLAT_ECC_DIMM_SID_VERSION_MINOR;
37903831d35Sstevel 	dreqp->pdsrd_msg_type = PLAT_ECC_DIMM_SID_MESSAGE;
38003831d35Sstevel 	dreqp->pdsrd_msg_length = wrapperp->ecc_msg_len;
38103831d35Sstevel 
38203831d35Sstevel 	/* Set board number DIMM serial ids are requested for */
38303831d35Sstevel 	dreqp->pdsrd_board_num = boardnum;
38403831d35Sstevel 
38503831d35Sstevel 	/*
38603831d35Sstevel 	 * Send the data on to the queuing function
38703831d35Sstevel 	 */
38803831d35Sstevel 	return (plat_ecc_dispatch_task(wrapperp));
38903831d35Sstevel }
39003831d35Sstevel 
39103831d35Sstevel /*
39203831d35Sstevel  * Discards DIMM serial id information from domain_dimm_sids[]
39303831d35Sstevel  * for a particular board.
39403831d35Sstevel  * Called by DR when a CPU/Mem board is disconnected.
39503831d35Sstevel  */
39603831d35Sstevel int
39703831d35Sstevel plat_discard_mem_sids(int boardnum)
39803831d35Sstevel {
39903831d35Sstevel 	mutex_enter(&domain_dimm_sids[boardnum].pdsb_lock);
40003831d35Sstevel 	domain_dimm_sids[boardnum].pdsb_state = PDSB_STATE_INVALID;
40103831d35Sstevel 	mutex_exit(&domain_dimm_sids[boardnum].pdsb_lock);
40203831d35Sstevel 
40303831d35Sstevel 	return (0);
40403831d35Sstevel }
405