/* * This is the Fusion MPT base driver providing common API layer interface * for access to MPT (Message Passing Technology) firmware. * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h * Copyright (C) 2012-2014 LSI Corporation * Copyright (C) 2013-2014 Avago Technologies * (mailto: MPT-FusionLinux.pdl@avagotech.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * NO WARRANTY * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is * solely responsible for determining the appropriateness of using and * distributing the Program and assumes all risks associated with its * exercise of rights under this Agreement, including but not limited to * the risks and costs of program errors, damage to or loss of data, * programs or equipment, and unavailability or interruption of operations.
* DISCLAIMER OF LIABILITY * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
* You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA.
*/
/* * Set MPT3SAS_SG_DEPTH value based on user input.
*/ #define MPT_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE #define MPT_MIN_PHYS_SEGMENTS 16 #define MPT_KDUMP_MIN_PHYS_SEGMENTS 32
/** * struct MPT3SAS_DEVICE - sdev private hostdata * @sas_target: starget private hostdata * @lun: lun number * @flags: MPT_DEVICE_XXX flags * @configured_lun: lun is configured * @block: device is in SDEV_BLOCK state * @tlr_snoop_check: flag used in determining whether to disable TLR * @eedp_enable: eedp support enable bit * @eedp_type: 0(type_1), 1(type_2), 2(type_3) * @eedp_block_length: block size * @ata_command_pending: SATL passthrough outstanding for device
*/ struct MPT3SAS_DEVICE { struct MPT3SAS_TARGET *sas_target; unsignedint lun;
u32 flags;
u8 configured_lun;
u8 block;
u8 tlr_snoop_check;
u8 ignore_delay_remove; /* Iopriority Command Handling */
u8 ncq_prio_enable; /* * Bug workaround for SATL handling: the mpt2/3sas firmware * doesn't return BUSY or TASK_SET_FULL for subsequent * commands while a SATL pass through is in operation as the * spec requires, it simply does nothing with them until the * pass through completes, causing them possibly to timeout if * the passthrough is a long executing command (like format or * secure erase). This variable allows us to do the right * thing while a SATL command is pending.
*/ unsignedlong ata_command_pending;
};
#define MPT3_CMD_NOT_USED 0x8000 /* free */ #define MPT3_CMD_COMPLETE 0x0001 /* completed */ #define MPT3_CMD_PENDING 0x0002 /* pending */ #define MPT3_CMD_REPLY_VALID 0x0004 /* reply is valid */ #define MPT3_CMD_RESET 0x0008 /* host reset dropped the command */ #define MPT3_CMD_COMPLETE_ASYNC 0x0010 /* tells whether cmd completes in same thread or not */
/* * struct _pcie_device - attached PCIe device information * @list: pcie device list * @starget: starget object * @wwid: device WWID * @handle: device handle * @device_info: bitfield provides detailed info about the device * @id: target id * @channel: target channel * @slot: slot number * @port_num: port number * @responding: used in _scsih_pcie_device_mark_responding * @fast_path: fast path feature enable bit * @nvme_mdts: MaximumDataTransferSize from PCIe Device Page 2 for * NVMe device only * @enclosure_handle: enclosure handle * @enclosure_logical_id: enclosure logical identifier * @enclosure_level: The level of device's enclosure from the controller * @connector_name: ASCII value of the Connector's name * @serial_number: pointer of serial number string allocated runtime * @access_status: Device's Access Status * @shutdown_latency: NVMe device's RTD3 Entry Latency * @refcount: reference count for deletion
*/ struct _pcie_device { struct list_head list; struct scsi_target *starget;
u64 wwid;
u16 handle;
u32 device_info; int id; int channel;
u16 slot;
u8 port_num;
u8 responding;
u8 fast_path;
u32 nvme_mdts;
u16 enclosure_handle;
u64 enclosure_logical_id;
u8 enclosure_level;
u8 connector_name[4];
u8 *serial_number;
u8 reset_timeout;
u8 access_status;
u16 shutdown_latency; struct kref refcount;
}; /** * pcie_device_get - Increment the pcie device reference count * * @p: pcie_device object * * When ever this function called it will increment the * reference count of the pcie device for which this function called. *
*/ staticinlinevoid pcie_device_get(struct _pcie_device *p)
{
kref_get(&p->refcount);
}
/** * pcie_device_free - Release the pcie device object * @r - kref object * * Free's the pcie device object. It will be called when reference count * reaches to zero.
*/ staticinlinevoid pcie_device_free(struct kref *r)
{
kfree(container_of(r, struct _pcie_device, refcount));
}
/** * pcie_device_put - Decrement the pcie device reference count * * @p: pcie_device object * * When ever this function called it will decrement the * reference count of the pcie device for which this function called. * * When refernce count reaches to Zero, this will call pcie_device_free to the * pcie_device object.
*/ staticinlinevoid pcie_device_put(struct _pcie_device *p)
{
kref_put(&p->refcount, pcie_device_free);
} /** * struct _raid_device - raid volume link list * @list: sas device list * @starget: starget object * @sdev: scsi device struct (volumes are single lun) * @wwid: unique identifier for the volume * @handle: device handle * @block_size: Block size of the volume * @id: target id * @channel: target channel * @volume_type: the raid level * @device_info: bitfield provides detailed info about the hidden components * @num_pds: number of hidden raid components * @responding: used in _scsih_raid_device_mark_responding * @percent_complete: resync percent complete * @direct_io_enabled: Whether direct io to PDs are allowed or not * @stripe_exponent: X where 2powX is the stripe sz in blocks * @block_exponent: X where 2powX is the block sz in bytes * @max_lba: Maximum number of LBA in the volume * @stripe_sz: Stripe Size of the volume * @device_info: Device info of the volume member disk * @pd_handle: Array of handles of the physical drives for direct I/O in le16
*/ #define MPT_MAX_WARPDRIVE_PDS 8 struct _raid_device { struct list_head list; struct scsi_target *starget; struct scsi_device *sdev;
u64 wwid;
u16 handle;
u16 block_sz; int id; int channel;
u8 volume_type;
u8 num_pds;
u8 responding;
u8 percent_complete;
u8 direct_io_enabled;
u8 stripe_exponent;
u8 block_exponent;
u64 max_lba;
u32 stripe_sz;
u32 device_info;
u16 pd_handle[MPT_MAX_WARPDRIVE_PDS];
};
/** * struct _boot_device - boot device info * * @channel: sas, raid, or pcie channel * @device: holds pointer for struct _sas_device, struct _raid_device or * struct _pcie_device
*/ struct _boot_device { int channel; void *device;
};
/** * struct _sas_port - wide/narrow sas port information * @port_list: list of ports belonging to expander * @num_phys: number of phys belonging to this port * @remote_identify: attached device identification * @rphy: sas transport rphy object * @port: sas transport wide/narrow port object * @hba_port: hba port entry containing port's port number info * @phy_list: _sas_phy list objects belonging to this port
*/ struct _sas_port { struct list_head port_list;
u8 num_phys; struct sas_identify remote_identify; struct sas_rphy *rphy; struct sas_port *port; struct hba_port *hba_port; struct list_head phy_list;
};
/** * struct _sas_phy - phy information * @port_siblings: list of phys belonging to a port * @identify: phy identification * @remote_identify: attached device identification * @phy: sas transport phy object * @phy_id: unique phy id * @handle: device handle for this phy * @attached_handle: device handle for attached device * @phy_belongs_to_port: port has been created for this phy * @port: hba port entry containing port number info
*/ struct _sas_phy { struct list_head port_siblings; struct sas_identify identify; struct sas_identify remote_identify; struct sas_phy *phy;
u8 phy_id;
u16 handle;
u16 attached_handle;
u8 phy_belongs_to_port;
u8 hba_vphy; struct hba_port *port;
};
/** * struct _sas_node - sas_host/expander information * @list: list of expanders * @parent_dev: parent device class * @num_phys: number phys belonging to this sas_host/expander * @sas_address: sas address of this sas_host/expander * @handle: handle for this sas_host/expander * @sas_address_parent: sas address of parent expander or sas host * @enclosure_handle: handle for this a member of an enclosure * @device_info: bitwise defining capabilities of this sas_host/expander * @responding: used in _scsih_expander_device_mark_responding * @nr_phys_allocated: Allocated memory for this many count phys * @phy: a list of phys that make up this sas_host/expander * @sas_port_list: list of ports attached to this sas_host/expander * @port: hba port entry containing node's port number info * @rphy: sas_rphy object of this expander
*/ struct _sas_node { struct list_head list; struct device *parent_dev;
u8 num_phys;
u64 sas_address;
u16 handle;
u64 sas_address_parent;
u16 enclosure_handle;
u64 enclosure_logical_id;
u8 responding;
u8 nr_phys_allocated; struct hba_port *port; struct _sas_phy *phy; struct list_head sas_port_list; struct sas_rphy *rphy;
};
/** * struct _enclosure_node - enclosure information * @list: list of enclosures * @pg0: enclosure pg0;
*/ struct _enclosure_node { struct list_head list;
Mpi2SasEnclosurePage0_t pg0;
};
/** * enum reset_type - reset state * @FORCE_BIG_HAMMER: issue diagnostic reset * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
*/ enum reset_type {
FORCE_BIG_HAMMER,
SOFT_RESET,
};
/** * struct _event_ack_list - delayed event acknowledgment list * @Event: Event ID * @EventContext: used to track the event uniquely
*/ struct _event_ack_list { struct list_head list;
U16 Event;
U32 EventContext;
};
/** * struct adapter_reply_queue - the reply queue struct * @ioc: per adapter object * @msix_index: msix index into vector table * @vector: irq vector * @reply_post_host_index: head index in the pool where FW completes IO * @reply_post_free: reply post base virt address * @name: the name registered to request_irq() * @busy: isr is actively processing replies on another cpu * @os_irq: irq number * @irqpoll: irq_poll object * @irq_poll_scheduled: Tells whether irq poll is scheduled or not * @is_iouring_poll_q: Tells whether reply queues is assigned * to io uring poll queues or not * @list: this list
*/ struct adapter_reply_queue { struct MPT3SAS_ADAPTER *ioc;
u8 msix_index;
u32 reply_post_host_index;
Mpi2ReplyDescriptorsUnion_t *reply_post_free; char name[MPT_NAME_LENGTH];
atomic_t busy;
u32 os_irq; struct irq_poll irqpoll; bool irq_poll_scheduled; bool irq_line_enable; bool is_iouring_poll_q; struct list_head list;
};
/** * struct io_uring_poll_queue - the io uring poll queue structure * @busy: Tells whether io uring poll queue is busy or not * @pause: Tells whether IOs are paused on io uring poll queue or not * @reply_q: reply queue mapped for io uring poll queue
*/ struct io_uring_poll_queue {
atomic_t busy;
atomic_t pause; struct adapter_reply_queue *reply_q;
};
/* To support atomic and non atomic descriptors*/ typedefvoid (*PUT_SMID_IO_FP_HIP) (struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 funcdep); typedefvoid (*PUT_SMID_DEFAULT) (struct MPT3SAS_ADAPTER *ioc, u16 smid); typedef u32 (*BASE_READ_REG) (constvoid __iomem *addr); /* * To get high iops reply queue's msix index when high iops mode is enabled * else get the msix index of general reply queues.
*/ typedef u8 (*GET_MSIX_INDEX) (struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd);
/* IOC Facts and Port Facts converted from little endian to cpu */ union mpi3_version_union {
MPI2_VERSION_STRUCT Struct;
u32 Word;
};
/** * struct htb_rel_query - diagnostic buffer release reason * @unique_id - unique id associated with this buffer. * @buffer_rel_condition - Release condition ioctl/sysfs/reset * @reserved * @trigger_type - Master/Event/scsi/MPI * @trigger_info_dwords - Data Correspondig to trigger type
*/ struct htb_rel_query {
u16 buffer_rel_condition;
u16 reserved;
u32 trigger_type;
u32 trigger_info_dwords[2];
};
/* Buffer_rel_condition bit fields */
/* Bit 0 - Diag Buffer not Released */ #define MPT3_DIAG_BUFFER_NOT_RELEASED (0x00) /* Bit 0 - Diag Buffer Released */ #define MPT3_DIAG_BUFFER_RELEASED (0x01)
/* * Bit 1 - Diag Buffer Released by IOCTL, * This bit is valid only if Bit 0 is one
*/ #define MPT3_DIAG_BUFFER_REL_IOCTL (0x02 | MPT3_DIAG_BUFFER_RELEASED)
/* * Bit 2 - Diag Buffer Released by Trigger, * This bit is valid only if Bit 0 is one
*/ #define MPT3_DIAG_BUFFER_REL_TRIGGER (0x04 | MPT3_DIAG_BUFFER_RELEASED)
/* * Bit 3 - Diag Buffer Released by SysFs, * This bit is valid only if Bit 0 is one
*/ #define MPT3_DIAG_BUFFER_REL_SYSFS (0x08 | MPT3_DIAG_BUFFER_RELEASED)
typedefvoid (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); /** * struct MPT3SAS_ADAPTER - per adapter struct * @list: ioc_list * @shost: shost object * @id: unique adapter id * @cpu_count: number online cpus * @name: generic ioc string * @tmp_string: tmp string used for logging * @pdev: pci pdev object * @pio_chip: physical io register space * @chip: memory mapped register space * @chip_phys: physical addrss prior to mapping * @logging_level: see mpt3sas_debug.h * @fwfault_debug: debuging FW timeouts * @ir_firmware: IR firmware present * @bars: bitmask of BAR's that must be configured * @mask_interrupts: ignore interrupt * @pci_access_mutex: Mutex to synchronize ioctl, sysfs show path and * pci resource handling * @fault_reset_work_q_name: fw fault work queue * @fault_reset_work_q: "" * @fault_reset_work: "" * @firmware_event_thread: fw event work queue * @fw_event_lock: * @fw_event_list: list of fw events * @current_evet: current processing firmware event * @fw_event_cleanup: set to one while cleaning up the fw events * @aen_event_read_flag: event log was read * @broadcast_aen_busy: broadcast aen waiting to be serviced * @shost_recovery: host reset in progress * @ioc_reset_in_progress_lock: * @ioc_link_reset_in_progress: phy/hard reset in progress * @ignore_loginfos: ignore loginfos during task management * @remove_host: flag for when driver unloads, to avoid sending dev resets * @pci_error_recovery: flag to prevent ioc access until slot reset completes * @wait_for_discovery_to_complete: flag set at driver load time when * waiting on reporting devices * @is_driver_loading: flag set at driver load time * @port_enable_failed: flag set when port enable has failed * @start_scan: flag set from scan_start callback, cleared from _mpt3sas_fw_work * @start_scan_failed: means port enable failed, return's the ioc_status * @msix_enable: flag indicating msix is enabled * @msix_vector_count: number msix vectors * @cpu_msix_table: table for mapping cpus to msix index * @cpu_msix_table_sz: table size * @total_io_cnt: Gives total IO count, used to load balance the interrupts * @ioc_coredump_loop: will have non-zero value when FW is in CoreDump state * @timestamp_update_count: Counter to fire timeSync command * time_sync_interval: Time sync interval read from man page 11 * @high_iops_outstanding: used to load balance the interrupts * within high iops reply queues * @msix_load_balance: Enables load balancing of interrupts across * the multiple MSIXs * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands * @thresh_hold: Max number of reply descriptors processed * before updating Host Index * @iopoll_q_start_index: starting index of io uring poll queues * in reply queue list * @drv_internal_flags: Bit map internal to driver * @drv_support_bitmap: driver's supported feature bit map * @use_32bit_dma: Flag to use 32 bit consistent dma mask * @scsi_io_cb_idx: shost generated commands * @tm_cb_idx: task management commands * @scsih_cb_idx: scsih internal commands * @transport_cb_idx: transport internal commands * @ctl_cb_idx: clt internal commands * @base_cb_idx: base internal commands * @config_cb_idx: base internal commands * @tm_tr_cb_idx : device removal target reset handshake * @tm_tr_volume_cb_idx : volume removal target reset * @base_cmds: * @transport_cmds: * @scsih_cmds: * @tm_cmds: * @ctl_cmds: * @config_cmds: * @base_add_sg_single: handler for either 32/64 bit sgl's * @event_type: bits indicating which events to log * @event_context: unique id for each logged event * @event_log: event log pointer * @event_masks: events that are masked * @max_shutdown_latency: timeout value for NVMe shutdown operation, * which is equal that NVMe drive's RTD3 Entry Latency * which has reported maximum RTD3 Entry Latency value * among attached NVMe drives. * @facts: static facts data * @prev_fw_facts: previous fw facts data * @pfacts: static port facts data * @manu_pg0: static manufacturing page 0 * @manu_pg10: static manufacturing page 10 * @manu_pg11: static manufacturing page 11 * @bios_pg2: static bios page 2 * @bios_pg3: static bios page 3 * @ioc_pg8: static ioc page 8 * @iounit_pg0: static iounit page 0 * @iounit_pg1: static iounit page 1 * @sas_hba: sas host object * @sas_expander_list: expander object list * @enclosure_list: enclosure object list * @sas_node_lock: * @sas_device_list: sas device object list * @sas_device_init_list: sas device object list (used only at init time) * @sas_device_lock: * @pcie_device_list: pcie device object list * @pcie_device_init_list: pcie device object list (used only at init time) * @pcie_device_lock: * @io_missing_delay: time for IO completed by fw when PDR enabled * @device_missing_delay: time for device missing by fw when PDR enabled * @sas_id : used for setting volume target IDs * @pcie_target_id: used for setting pcie target IDs * @blocking_handles: bitmask used to identify which devices need blocking * @pd_handles : bitmask for PD handles * @pd_handles_sz : size of pd_handle bitmask * @config_page_sz: config page size * @config_page: reserve memory for config page payload * @config_page_dma: * @hba_queue_depth: hba request queue depth * @sge_size: sg element size for either 32/64 bit * @scsiio_depth: SCSI_IO queue depth * @request_sz: per request frame size * @request: pool of request frames * @request_dma: * @request_dma_sz: * @scsi_lookup: firmware request tracker list * @scsi_lookup_lock: * @free_list: free list of request * @pending_io_count: * @reset_wq: * @chain: pool of chains * @chain_dma: * @max_sges_in_main_message: number sg elements in main message * @max_sges_in_chain_message: number sg elements per chain * @chains_needed_per_io: max chains per io * @chain_depth: total chains allocated * @chain_segment_sz: gives the max number of * SGEs accommodate on single chain buffer * @hi_priority_smid: * @hi_priority: * @hi_priority_dma: * @hi_priority_depth: * @hpr_lookup: * @hpr_free_list: * @internal_smid: * @internal: * @internal_dma: * @internal_depth: * @internal_lookup: * @internal_free_list: * @sense: pool of sense * @sense_dma: * @sense_dma_pool: * @reply_depth: hba reply queue depth: * @reply_sz: per reply frame size: * @reply: pool of replys: * @reply_dma: * @reply_dma_pool: * @reply_free_queue_depth: reply free depth * @reply_free: pool for reply free queue (32 bit addr) * @reply_free_dma: * @reply_free_dma_pool: * @reply_free_host_index: tail index in pool to insert free replys * @reply_post_queue_depth: reply post queue depth * @reply_post_struct: struct for reply_post_free physical & virt address * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init * @rdpq_array_enable: rdpq_array support is enabled in the driver * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag * is assigned only ones * @reply_queue_count: number of reply queue's * @reply_queue_list: link list contaning the reply queue info * @msix96_vector: 96 MSI-X vector support * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue * @delayed_tr_list: target reset link list * @delayed_tr_volume_list: volume target reset link list * @delayed_sc_list: * @delayed_event_ack_list: * @temp_sensors_count: flag to carry the number of temperature sensors * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and * pci resource handling. PCI resource freeing will lead to free * vital hardware/memory resource, which might be in use by cli/sysfs * path functions resulting in Null pointer reference followed by kernel * crash. To avoid the above race condition we use mutex syncrhonization * which ensures the syncrhonization between cli/sysfs_show path. * @atomic_desc_capable: Atomic Request Descriptor support. * @GET_MSIX_INDEX: Get the msix index of high iops queues. * @multipath_on_hba: flag to determine multipath on hba is enabled or not * @port_table_list: list containing HBA's wide/narrow port's info
*/ struct MPT3SAS_ADAPTER { struct list_head list; struct Scsi_Host *shost;
u8 id; int cpu_count; char name[MPT_NAME_LENGTH]; char driver_name[MPT_NAME_LENGTH - 8]; char tmp_string[MPT_STRING_LENGTH]; struct pci_dev *pdev;
Mpi2SystemInterfaceRegs_t __iomem *chip;
phys_addr_t chip_phys; int logging_level; int fwfault_debug;
u8 ir_firmware; int bars;
u8 mask_interrupts;
/* function ptr for either IEEE or MPI sg elements */
MPT_BUILD_SG_SCMD build_sg_scmd;
MPT_BUILD_SG build_sg;
MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge;
u16 sge_size_ieee;
u16 hba_mpi_version_belonged;
/* function ptr for MPI sg elements only */
MPT_BUILD_SG build_sg_mpi;
MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi;
/* function ptr for NVMe PRP elements only */
NVME_BUILD_PRP build_nvme_prp;
/* base shared API */ externstruct list_head mpt3sas_ioc_list; externchar driver_name[MPT_NAME_LENGTH]; /* spinlock on list operations over IOCs * Case: when multiple warpdrive cards(IOCs) are in use * Each IOC will added to the ioc list structure on initialization. * Watchdog threads run at regular intervals to check IOC for any * fault conditions which will trigger the dead_ioc thread to * deallocate pci resource, resulting deleting the IOC netry from list, * this deletion need to protected by spinlock to enusre that * ioc removal is syncrhonized, if not synchronized it might lead to * list_del corruption as the ioc list is traversed in cli path.
*/ extern spinlock_t gioc_lock;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.