162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2008-2009 USI Co., Ltd. 562306a36Sopenharmony_ci * All rights reserved. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 862306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 962306a36Sopenharmony_ci * are met: 1062306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1162306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1262306a36Sopenharmony_ci * without modification. 1362306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1462306a36Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 1562306a36Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 1662306a36Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 1762306a36Sopenharmony_ci * binary redistribution. 1862306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 1962306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2062306a36Sopenharmony_ci * from this software without specific prior written permission. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 2362306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 2462306a36Sopenharmony_ci * Software Foundation. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * NO WARRANTY 2762306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2862306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2962306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3062306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3162306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3262306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3362306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3462306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3562306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3662306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3762306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#ifndef _PM8001_SAS_H_ 4262306a36Sopenharmony_ci#define _PM8001_SAS_H_ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include <linux/kernel.h> 4562306a36Sopenharmony_ci#include <linux/module.h> 4662306a36Sopenharmony_ci#include <linux/spinlock.h> 4762306a36Sopenharmony_ci#include <linux/delay.h> 4862306a36Sopenharmony_ci#include <linux/types.h> 4962306a36Sopenharmony_ci#include <linux/ctype.h> 5062306a36Sopenharmony_ci#include <linux/dma-mapping.h> 5162306a36Sopenharmony_ci#include <linux/pci.h> 5262306a36Sopenharmony_ci#include <linux/interrupt.h> 5362306a36Sopenharmony_ci#include <linux/workqueue.h> 5462306a36Sopenharmony_ci#include <scsi/libsas.h> 5562306a36Sopenharmony_ci#include <scsi/scsi_tcq.h> 5662306a36Sopenharmony_ci#include <scsi/sas_ata.h> 5762306a36Sopenharmony_ci#include <linux/atomic.h> 5862306a36Sopenharmony_ci#include <linux/blk-mq.h> 5962306a36Sopenharmony_ci#include <linux/blk-mq-pci.h> 6062306a36Sopenharmony_ci#include "pm8001_defs.h" 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define DRV_NAME "pm80xx" 6362306a36Sopenharmony_ci#define DRV_VERSION "0.1.40" 6462306a36Sopenharmony_ci#define PM8001_FAIL_LOGGING 0x01 /* Error message logging */ 6562306a36Sopenharmony_ci#define PM8001_INIT_LOGGING 0x02 /* driver init logging */ 6662306a36Sopenharmony_ci#define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */ 6762306a36Sopenharmony_ci#define PM8001_IO_LOGGING 0x08 /* I/O path logging */ 6862306a36Sopenharmony_ci#define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/ 6962306a36Sopenharmony_ci#define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */ 7062306a36Sopenharmony_ci#define PM8001_MSG_LOGGING 0x40 /* misc message logging */ 7162306a36Sopenharmony_ci#define PM8001_DEV_LOGGING 0x80 /* development message logging */ 7262306a36Sopenharmony_ci#define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ 7362306a36Sopenharmony_ci#define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ 7462306a36Sopenharmony_ci#define PM8001_EVENT_LOGGING 0x400 /* HW event logging */ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define pm8001_info(HBA, fmt, ...) \ 7762306a36Sopenharmony_ci pr_info("%s:: %s %d: " fmt, \ 7862306a36Sopenharmony_ci (HBA)->name, __func__, __LINE__, ##__VA_ARGS__) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define pm8001_dbg(HBA, level, fmt, ...) \ 8162306a36Sopenharmony_cido { \ 8262306a36Sopenharmony_ci if (unlikely((HBA)->logging_level & PM8001_##level##_LOGGING)) \ 8362306a36Sopenharmony_ci pm8001_info(HBA, fmt, ##__VA_ARGS__); \ 8462306a36Sopenharmony_ci} while (0) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define PM8001_USE_TASKLET 8762306a36Sopenharmony_ci#define PM8001_USE_MSIX 8862306a36Sopenharmony_ci#define PM8001_READ_VPD 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ 9262306a36Sopenharmony_ci || (dev->device == 0X8076) \ 9362306a36Sopenharmony_ci || (dev->device == 0X8077) \ 9462306a36Sopenharmony_ci || (dev->device == 0X8070) \ 9562306a36Sopenharmony_ci || (dev->device == 0X8072)) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define PM8001_NAME_LENGTH 32/* generic length of strings */ 9862306a36Sopenharmony_ciextern struct list_head hba_list; 9962306a36Sopenharmony_ciextern const struct pm8001_dispatch pm8001_8001_dispatch; 10062306a36Sopenharmony_ciextern const struct pm8001_dispatch pm8001_80xx_dispatch; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct pm8001_hba_info; 10362306a36Sopenharmony_cistruct pm8001_ccb_info; 10462306a36Sopenharmony_cistruct pm8001_device; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistruct pm8001_ioctl_payload { 10762306a36Sopenharmony_ci u32 signature; 10862306a36Sopenharmony_ci u16 major_function; 10962306a36Sopenharmony_ci u16 minor_function; 11062306a36Sopenharmony_ci u16 status; 11162306a36Sopenharmony_ci u16 offset; 11262306a36Sopenharmony_ci u16 id; 11362306a36Sopenharmony_ci u32 wr_length; 11462306a36Sopenharmony_ci u32 rd_length; 11562306a36Sopenharmony_ci u8 *func_specific; 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define MPI_FATAL_ERROR_TABLE_OFFSET_MASK 0xFFFFFF 11962306a36Sopenharmony_ci#define MPI_FATAL_ERROR_TABLE_SIZE(value) ((0xFF000000 & value) >> SHIFT24) 12062306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_LO_OFFSET 0x00 /* HNFBUFL */ 12162306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_HI_OFFSET 0x04 /* HNFBUFH */ 12262306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_LENGTH 0x08 /* HNFBLEN */ 12362306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */ 12462306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */ 12562306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */ 12662306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18 /* TOTALLEN */ 12762306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C /* SIGNITURE */ 12862306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1 12962306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0 13062306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0 13162306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED 0x1 13262306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA 0x2 13362306a36Sopenharmony_ci#define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE 0x3 13462306a36Sopenharmony_ci#define TYPE_GSM_SPACE 1 13562306a36Sopenharmony_ci#define TYPE_QUEUE 2 13662306a36Sopenharmony_ci#define TYPE_FATAL 3 13762306a36Sopenharmony_ci#define TYPE_NON_FATAL 4 13862306a36Sopenharmony_ci#define TYPE_INBOUND 1 13962306a36Sopenharmony_ci#define TYPE_OUTBOUND 2 14062306a36Sopenharmony_cistruct forensic_data { 14162306a36Sopenharmony_ci u32 data_type; 14262306a36Sopenharmony_ci union { 14362306a36Sopenharmony_ci struct { 14462306a36Sopenharmony_ci u32 direct_len; 14562306a36Sopenharmony_ci u32 direct_offset; 14662306a36Sopenharmony_ci void *direct_data; 14762306a36Sopenharmony_ci } gsm_buf; 14862306a36Sopenharmony_ci struct { 14962306a36Sopenharmony_ci u16 queue_type; 15062306a36Sopenharmony_ci u16 queue_index; 15162306a36Sopenharmony_ci u32 direct_len; 15262306a36Sopenharmony_ci void *direct_data; 15362306a36Sopenharmony_ci } queue_buf; 15462306a36Sopenharmony_ci struct { 15562306a36Sopenharmony_ci u32 direct_len; 15662306a36Sopenharmony_ci u32 direct_offset; 15762306a36Sopenharmony_ci u32 read_len; 15862306a36Sopenharmony_ci void *direct_data; 15962306a36Sopenharmony_ci } data_buf; 16062306a36Sopenharmony_ci }; 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/* bit31-26 - mask bar */ 16462306a36Sopenharmony_ci#define SCRATCH_PAD0_BAR_MASK 0xFC000000 16562306a36Sopenharmony_ci/* bit25-0 - offset mask */ 16662306a36Sopenharmony_ci#define SCRATCH_PAD0_OFFSET_MASK 0x03FFFFFF 16762306a36Sopenharmony_ci/* if AAP error state */ 16862306a36Sopenharmony_ci#define SCRATCH_PAD0_AAPERR_MASK 0xFFFFFFFF 16962306a36Sopenharmony_ci/* Inbound doorbell bit7 */ 17062306a36Sopenharmony_ci#define SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP 0x80 17162306a36Sopenharmony_ci/* Inbound doorbell bit7 SPCV */ 17262306a36Sopenharmony_ci#define SPCV_MSGU_CFG_TABLE_TRANSFER_DEBUG_INFO 0x80 17362306a36Sopenharmony_ci#define MAIN_MERRDCTO_MERRDCES 0xA0/* DWORD 0x28) */ 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistruct pm8001_dispatch { 17662306a36Sopenharmony_ci char *name; 17762306a36Sopenharmony_ci int (*chip_init)(struct pm8001_hba_info *pm8001_ha); 17862306a36Sopenharmony_ci void (*chip_post_init)(struct pm8001_hba_info *pm8001_ha); 17962306a36Sopenharmony_ci int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha); 18062306a36Sopenharmony_ci void (*chip_rst)(struct pm8001_hba_info *pm8001_ha); 18162306a36Sopenharmony_ci int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha); 18262306a36Sopenharmony_ci void (*chip_iounmap)(struct pm8001_hba_info *pm8001_ha); 18362306a36Sopenharmony_ci irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha, u8 vec); 18462306a36Sopenharmony_ci u32 (*is_our_interrupt)(struct pm8001_hba_info *pm8001_ha); 18562306a36Sopenharmony_ci int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha, u8 vec); 18662306a36Sopenharmony_ci void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha, u8 vec); 18762306a36Sopenharmony_ci void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha, u8 vec); 18862306a36Sopenharmony_ci void (*make_prd)(struct scatterlist *scatter, int nr, void *prd); 18962306a36Sopenharmony_ci int (*smp_req)(struct pm8001_hba_info *pm8001_ha, 19062306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 19162306a36Sopenharmony_ci int (*ssp_io_req)(struct pm8001_hba_info *pm8001_ha, 19262306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 19362306a36Sopenharmony_ci int (*sata_req)(struct pm8001_hba_info *pm8001_ha, 19462306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 19562306a36Sopenharmony_ci int (*phy_start_req)(struct pm8001_hba_info *pm8001_ha, u8 phy_id); 19662306a36Sopenharmony_ci int (*phy_stop_req)(struct pm8001_hba_info *pm8001_ha, u8 phy_id); 19762306a36Sopenharmony_ci int (*reg_dev_req)(struct pm8001_hba_info *pm8001_ha, 19862306a36Sopenharmony_ci struct pm8001_device *pm8001_dev, u32 flag); 19962306a36Sopenharmony_ci int (*dereg_dev_req)(struct pm8001_hba_info *pm8001_ha, u32 device_id); 20062306a36Sopenharmony_ci int (*phy_ctl_req)(struct pm8001_hba_info *pm8001_ha, 20162306a36Sopenharmony_ci u32 phy_id, u32 phy_op); 20262306a36Sopenharmony_ci int (*task_abort)(struct pm8001_hba_info *pm8001_ha, 20362306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 20462306a36Sopenharmony_ci int (*ssp_tm_req)(struct pm8001_hba_info *pm8001_ha, 20562306a36Sopenharmony_ci struct pm8001_ccb_info *ccb, struct sas_tmf_task *tmf); 20662306a36Sopenharmony_ci int (*get_nvmd_req)(struct pm8001_hba_info *pm8001_ha, void *payload); 20762306a36Sopenharmony_ci int (*set_nvmd_req)(struct pm8001_hba_info *pm8001_ha, void *payload); 20862306a36Sopenharmony_ci int (*fw_flash_update_req)(struct pm8001_hba_info *pm8001_ha, 20962306a36Sopenharmony_ci void *payload); 21062306a36Sopenharmony_ci int (*set_dev_state_req)(struct pm8001_hba_info *pm8001_ha, 21162306a36Sopenharmony_ci struct pm8001_device *pm8001_dev, u32 state); 21262306a36Sopenharmony_ci int (*sas_diag_start_end_req)(struct pm8001_hba_info *pm8001_ha, 21362306a36Sopenharmony_ci u32 state); 21462306a36Sopenharmony_ci int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha, 21562306a36Sopenharmony_ci u32 state); 21662306a36Sopenharmony_ci int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha); 21762306a36Sopenharmony_ci int (*fatal_errors)(struct pm8001_hba_info *pm8001_ha); 21862306a36Sopenharmony_ci void (*hw_event_ack_req)(struct pm8001_hba_info *pm8001_ha, 21962306a36Sopenharmony_ci u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, 22062306a36Sopenharmony_ci u32 param1); 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistruct pm8001_chip_info { 22462306a36Sopenharmony_ci u32 encrypt; 22562306a36Sopenharmony_ci u32 n_phy; 22662306a36Sopenharmony_ci const struct pm8001_dispatch *dispatch; 22762306a36Sopenharmony_ci}; 22862306a36Sopenharmony_ci#define PM8001_CHIP_DISP (pm8001_ha->chip->dispatch) 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistruct pm8001_port { 23162306a36Sopenharmony_ci struct asd_sas_port sas_port; 23262306a36Sopenharmony_ci u8 port_attached; 23362306a36Sopenharmony_ci u16 wide_port_phymap; 23462306a36Sopenharmony_ci u8 port_state; 23562306a36Sopenharmony_ci u8 port_id; 23662306a36Sopenharmony_ci struct list_head list; 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistruct pm8001_phy { 24062306a36Sopenharmony_ci struct pm8001_hba_info *pm8001_ha; 24162306a36Sopenharmony_ci struct pm8001_port *port; 24262306a36Sopenharmony_ci struct asd_sas_phy sas_phy; 24362306a36Sopenharmony_ci struct sas_identify identify; 24462306a36Sopenharmony_ci struct scsi_device *sdev; 24562306a36Sopenharmony_ci u64 dev_sas_addr; 24662306a36Sopenharmony_ci u32 phy_type; 24762306a36Sopenharmony_ci struct completion *enable_completion; 24862306a36Sopenharmony_ci u32 frame_rcvd_size; 24962306a36Sopenharmony_ci u8 frame_rcvd[32]; 25062306a36Sopenharmony_ci u8 phy_attached; 25162306a36Sopenharmony_ci u8 phy_state; 25262306a36Sopenharmony_ci enum sas_linkrate minimum_linkrate; 25362306a36Sopenharmony_ci enum sas_linkrate maximum_linkrate; 25462306a36Sopenharmony_ci struct completion *reset_completion; 25562306a36Sopenharmony_ci bool port_reset_status; 25662306a36Sopenharmony_ci bool reset_success; 25762306a36Sopenharmony_ci}; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/* port reset status */ 26062306a36Sopenharmony_ci#define PORT_RESET_SUCCESS 0x00 26162306a36Sopenharmony_ci#define PORT_RESET_TMO 0x01 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistruct pm8001_device { 26462306a36Sopenharmony_ci enum sas_device_type dev_type; 26562306a36Sopenharmony_ci struct domain_device *sas_device; 26662306a36Sopenharmony_ci u32 attached_phy; 26762306a36Sopenharmony_ci u32 id; 26862306a36Sopenharmony_ci struct completion *dcompletion; 26962306a36Sopenharmony_ci struct completion *setds_completion; 27062306a36Sopenharmony_ci u32 device_id; 27162306a36Sopenharmony_ci atomic_t running_req; 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistruct pm8001_prd_imt { 27562306a36Sopenharmony_ci __le32 len; 27662306a36Sopenharmony_ci __le32 e; 27762306a36Sopenharmony_ci}; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistruct pm8001_prd { 28062306a36Sopenharmony_ci __le64 addr; /* 64-bit buffer address */ 28162306a36Sopenharmony_ci struct pm8001_prd_imt im_len; /* 64-bit length */ 28262306a36Sopenharmony_ci} __attribute__ ((packed)); 28362306a36Sopenharmony_ci/* 28462306a36Sopenharmony_ci * CCB(Command Control Block) 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_cistruct pm8001_ccb_info { 28762306a36Sopenharmony_ci struct sas_task *task; 28862306a36Sopenharmony_ci u32 n_elem; 28962306a36Sopenharmony_ci u32 ccb_tag; 29062306a36Sopenharmony_ci dma_addr_t ccb_dma_handle; 29162306a36Sopenharmony_ci struct pm8001_device *device; 29262306a36Sopenharmony_ci struct pm8001_prd *buf_prd; 29362306a36Sopenharmony_ci struct fw_control_ex *fw_control_context; 29462306a36Sopenharmony_ci u8 open_retry; 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistruct mpi_mem { 29862306a36Sopenharmony_ci void *virt_ptr; 29962306a36Sopenharmony_ci dma_addr_t phys_addr; 30062306a36Sopenharmony_ci u32 phys_addr_hi; 30162306a36Sopenharmony_ci u32 phys_addr_lo; 30262306a36Sopenharmony_ci u32 total_len; 30362306a36Sopenharmony_ci u32 num_elements; 30462306a36Sopenharmony_ci u32 element_size; 30562306a36Sopenharmony_ci u32 alignment; 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistruct mpi_mem_req { 30962306a36Sopenharmony_ci /* The number of element in the mpiMemory array */ 31062306a36Sopenharmony_ci u32 count; 31162306a36Sopenharmony_ci /* The array of structures that define memroy regions*/ 31262306a36Sopenharmony_ci struct mpi_mem region[USI_MAX_MEMCNT]; 31362306a36Sopenharmony_ci}; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistruct encrypt { 31662306a36Sopenharmony_ci u32 cipher_mode; 31762306a36Sopenharmony_ci u32 sec_mode; 31862306a36Sopenharmony_ci u32 status; 31962306a36Sopenharmony_ci u32 flag; 32062306a36Sopenharmony_ci}; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistruct sas_phy_attribute_table { 32362306a36Sopenharmony_ci u32 phystart1_16[16]; 32462306a36Sopenharmony_ci u32 outbound_hw_event_pid1_16[16]; 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ciunion main_cfg_table { 32862306a36Sopenharmony_ci struct { 32962306a36Sopenharmony_ci u32 signature; 33062306a36Sopenharmony_ci u32 interface_rev; 33162306a36Sopenharmony_ci u32 firmware_rev; 33262306a36Sopenharmony_ci u32 max_out_io; 33362306a36Sopenharmony_ci u32 max_sgl; 33462306a36Sopenharmony_ci u32 ctrl_cap_flag; 33562306a36Sopenharmony_ci u32 gst_offset; 33662306a36Sopenharmony_ci u32 inbound_queue_offset; 33762306a36Sopenharmony_ci u32 outbound_queue_offset; 33862306a36Sopenharmony_ci u32 inbound_q_nppd_hppd; 33962306a36Sopenharmony_ci u32 outbound_hw_event_pid0_3; 34062306a36Sopenharmony_ci u32 outbound_hw_event_pid4_7; 34162306a36Sopenharmony_ci u32 outbound_ncq_event_pid0_3; 34262306a36Sopenharmony_ci u32 outbound_ncq_event_pid4_7; 34362306a36Sopenharmony_ci u32 outbound_tgt_ITNexus_event_pid0_3; 34462306a36Sopenharmony_ci u32 outbound_tgt_ITNexus_event_pid4_7; 34562306a36Sopenharmony_ci u32 outbound_tgt_ssp_event_pid0_3; 34662306a36Sopenharmony_ci u32 outbound_tgt_ssp_event_pid4_7; 34762306a36Sopenharmony_ci u32 outbound_tgt_smp_event_pid0_3; 34862306a36Sopenharmony_ci u32 outbound_tgt_smp_event_pid4_7; 34962306a36Sopenharmony_ci u32 upper_event_log_addr; 35062306a36Sopenharmony_ci u32 lower_event_log_addr; 35162306a36Sopenharmony_ci u32 event_log_size; 35262306a36Sopenharmony_ci u32 event_log_option; 35362306a36Sopenharmony_ci u32 upper_iop_event_log_addr; 35462306a36Sopenharmony_ci u32 lower_iop_event_log_addr; 35562306a36Sopenharmony_ci u32 iop_event_log_size; 35662306a36Sopenharmony_ci u32 iop_event_log_option; 35762306a36Sopenharmony_ci u32 fatal_err_interrupt; 35862306a36Sopenharmony_ci u32 fatal_err_dump_offset0; 35962306a36Sopenharmony_ci u32 fatal_err_dump_length0; 36062306a36Sopenharmony_ci u32 fatal_err_dump_offset1; 36162306a36Sopenharmony_ci u32 fatal_err_dump_length1; 36262306a36Sopenharmony_ci u32 hda_mode_flag; 36362306a36Sopenharmony_ci u32 anolog_setup_table_offset; 36462306a36Sopenharmony_ci u32 rsvd[4]; 36562306a36Sopenharmony_ci } pm8001_tbl; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci struct { 36862306a36Sopenharmony_ci u32 signature; 36962306a36Sopenharmony_ci u32 interface_rev; 37062306a36Sopenharmony_ci u32 firmware_rev; 37162306a36Sopenharmony_ci u32 max_out_io; 37262306a36Sopenharmony_ci u32 max_sgl; 37362306a36Sopenharmony_ci u32 ctrl_cap_flag; 37462306a36Sopenharmony_ci u32 gst_offset; 37562306a36Sopenharmony_ci u32 inbound_queue_offset; 37662306a36Sopenharmony_ci u32 outbound_queue_offset; 37762306a36Sopenharmony_ci u32 inbound_q_nppd_hppd; 37862306a36Sopenharmony_ci u32 rsvd[8]; 37962306a36Sopenharmony_ci u32 crc_core_dump; 38062306a36Sopenharmony_ci u32 rsvd1; 38162306a36Sopenharmony_ci u32 upper_event_log_addr; 38262306a36Sopenharmony_ci u32 lower_event_log_addr; 38362306a36Sopenharmony_ci u32 event_log_size; 38462306a36Sopenharmony_ci u32 event_log_severity; 38562306a36Sopenharmony_ci u32 upper_pcs_event_log_addr; 38662306a36Sopenharmony_ci u32 lower_pcs_event_log_addr; 38762306a36Sopenharmony_ci u32 pcs_event_log_size; 38862306a36Sopenharmony_ci u32 pcs_event_log_severity; 38962306a36Sopenharmony_ci u32 fatal_err_interrupt; 39062306a36Sopenharmony_ci u32 fatal_err_dump_offset0; 39162306a36Sopenharmony_ci u32 fatal_err_dump_length0; 39262306a36Sopenharmony_ci u32 fatal_err_dump_offset1; 39362306a36Sopenharmony_ci u32 fatal_err_dump_length1; 39462306a36Sopenharmony_ci u32 gpio_led_mapping; 39562306a36Sopenharmony_ci u32 analog_setup_table_offset; 39662306a36Sopenharmony_ci u32 int_vec_table_offset; 39762306a36Sopenharmony_ci u32 phy_attr_table_offset; 39862306a36Sopenharmony_ci u32 port_recovery_timer; 39962306a36Sopenharmony_ci u32 interrupt_reassertion_delay; 40062306a36Sopenharmony_ci u32 fatal_n_non_fatal_dump; /* 0x28 */ 40162306a36Sopenharmony_ci u32 ila_version; 40262306a36Sopenharmony_ci u32 inc_fw_version; 40362306a36Sopenharmony_ci } pm80xx_tbl; 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ciunion general_status_table { 40762306a36Sopenharmony_ci struct { 40862306a36Sopenharmony_ci u32 gst_len_mpistate; 40962306a36Sopenharmony_ci u32 iq_freeze_state0; 41062306a36Sopenharmony_ci u32 iq_freeze_state1; 41162306a36Sopenharmony_ci u32 msgu_tcnt; 41262306a36Sopenharmony_ci u32 iop_tcnt; 41362306a36Sopenharmony_ci u32 rsvd; 41462306a36Sopenharmony_ci u32 phy_state[8]; 41562306a36Sopenharmony_ci u32 gpio_input_val; 41662306a36Sopenharmony_ci u32 rsvd1[2]; 41762306a36Sopenharmony_ci u32 recover_err_info[8]; 41862306a36Sopenharmony_ci } pm8001_tbl; 41962306a36Sopenharmony_ci struct { 42062306a36Sopenharmony_ci u32 gst_len_mpistate; 42162306a36Sopenharmony_ci u32 iq_freeze_state0; 42262306a36Sopenharmony_ci u32 iq_freeze_state1; 42362306a36Sopenharmony_ci u32 msgu_tcnt; 42462306a36Sopenharmony_ci u32 iop_tcnt; 42562306a36Sopenharmony_ci u32 rsvd[9]; 42662306a36Sopenharmony_ci u32 gpio_input_val; 42762306a36Sopenharmony_ci u32 rsvd1[2]; 42862306a36Sopenharmony_ci u32 recover_err_info[8]; 42962306a36Sopenharmony_ci } pm80xx_tbl; 43062306a36Sopenharmony_ci}; 43162306a36Sopenharmony_cistruct inbound_queue_table { 43262306a36Sopenharmony_ci u32 element_pri_size_cnt; 43362306a36Sopenharmony_ci u32 upper_base_addr; 43462306a36Sopenharmony_ci u32 lower_base_addr; 43562306a36Sopenharmony_ci u32 ci_upper_base_addr; 43662306a36Sopenharmony_ci u32 ci_lower_base_addr; 43762306a36Sopenharmony_ci u32 pi_pci_bar; 43862306a36Sopenharmony_ci u32 pi_offset; 43962306a36Sopenharmony_ci u32 total_length; 44062306a36Sopenharmony_ci void *base_virt; 44162306a36Sopenharmony_ci void *ci_virt; 44262306a36Sopenharmony_ci u32 reserved; 44362306a36Sopenharmony_ci __le32 consumer_index; 44462306a36Sopenharmony_ci u32 producer_idx; 44562306a36Sopenharmony_ci spinlock_t iq_lock; 44662306a36Sopenharmony_ci}; 44762306a36Sopenharmony_cistruct outbound_queue_table { 44862306a36Sopenharmony_ci u32 element_size_cnt; 44962306a36Sopenharmony_ci u32 upper_base_addr; 45062306a36Sopenharmony_ci u32 lower_base_addr; 45162306a36Sopenharmony_ci void *base_virt; 45262306a36Sopenharmony_ci u32 pi_upper_base_addr; 45362306a36Sopenharmony_ci u32 pi_lower_base_addr; 45462306a36Sopenharmony_ci u32 ci_pci_bar; 45562306a36Sopenharmony_ci u32 ci_offset; 45662306a36Sopenharmony_ci u32 total_length; 45762306a36Sopenharmony_ci void *pi_virt; 45862306a36Sopenharmony_ci u32 interrup_vec_cnt_delay; 45962306a36Sopenharmony_ci u32 dinterrup_to_pci_offset; 46062306a36Sopenharmony_ci __le32 producer_index; 46162306a36Sopenharmony_ci u32 consumer_idx; 46262306a36Sopenharmony_ci spinlock_t oq_lock; 46362306a36Sopenharmony_ci unsigned long lock_flags; 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_cistruct pm8001_hba_memspace { 46662306a36Sopenharmony_ci void __iomem *memvirtaddr; 46762306a36Sopenharmony_ci u64 membase; 46862306a36Sopenharmony_ci u32 memsize; 46962306a36Sopenharmony_ci}; 47062306a36Sopenharmony_cistruct isr_param { 47162306a36Sopenharmony_ci struct pm8001_hba_info *drv_inst; 47262306a36Sopenharmony_ci u32 irq_id; 47362306a36Sopenharmony_ci}; 47462306a36Sopenharmony_cistruct pm8001_hba_info { 47562306a36Sopenharmony_ci char name[PM8001_NAME_LENGTH]; 47662306a36Sopenharmony_ci struct list_head list; 47762306a36Sopenharmony_ci unsigned long flags; 47862306a36Sopenharmony_ci spinlock_t lock;/* host-wide lock */ 47962306a36Sopenharmony_ci spinlock_t bitmap_lock; 48062306a36Sopenharmony_ci struct pci_dev *pdev;/* our device */ 48162306a36Sopenharmony_ci struct device *dev; 48262306a36Sopenharmony_ci struct pm8001_hba_memspace io_mem[6]; 48362306a36Sopenharmony_ci struct mpi_mem_req memoryMap; 48462306a36Sopenharmony_ci struct encrypt encrypt_info; /* support encryption */ 48562306a36Sopenharmony_ci struct forensic_data forensic_info; 48662306a36Sopenharmony_ci u32 fatal_bar_loc; 48762306a36Sopenharmony_ci u32 forensic_last_offset; 48862306a36Sopenharmony_ci u32 fatal_forensic_shift_offset; 48962306a36Sopenharmony_ci u32 forensic_fatal_step; 49062306a36Sopenharmony_ci u32 forensic_preserved_accumulated_transfer; 49162306a36Sopenharmony_ci u32 evtlog_ib_offset; 49262306a36Sopenharmony_ci u32 evtlog_ob_offset; 49362306a36Sopenharmony_ci void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ 49462306a36Sopenharmony_ci void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ 49562306a36Sopenharmony_ci void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ 49662306a36Sopenharmony_ci void __iomem *inbnd_q_tbl_addr;/*Inbound Queue Config Table Addr*/ 49762306a36Sopenharmony_ci void __iomem *outbnd_q_tbl_addr;/*Outbound Queue Config Table Addr*/ 49862306a36Sopenharmony_ci void __iomem *pspa_q_tbl_addr; 49962306a36Sopenharmony_ci /*MPI SAS PHY attributes Queue Config Table Addr*/ 50062306a36Sopenharmony_ci void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ 50162306a36Sopenharmony_ci void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */ 50262306a36Sopenharmony_ci union main_cfg_table main_cfg_tbl; 50362306a36Sopenharmony_ci union general_status_table gs_tbl; 50462306a36Sopenharmony_ci struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM]; 50562306a36Sopenharmony_ci struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM]; 50662306a36Sopenharmony_ci struct sas_phy_attribute_table phy_attr_table; 50762306a36Sopenharmony_ci /* MPI SAS PHY attributes */ 50862306a36Sopenharmony_ci u8 sas_addr[SAS_ADDR_SIZE]; 50962306a36Sopenharmony_ci struct sas_ha_struct *sas;/* SCSI/SAS glue */ 51062306a36Sopenharmony_ci struct Scsi_Host *shost; 51162306a36Sopenharmony_ci u32 chip_id; 51262306a36Sopenharmony_ci const struct pm8001_chip_info *chip; 51362306a36Sopenharmony_ci struct completion *nvmd_completion; 51462306a36Sopenharmony_ci unsigned long *rsvd_tags; 51562306a36Sopenharmony_ci struct pm8001_phy phy[PM8001_MAX_PHYS]; 51662306a36Sopenharmony_ci struct pm8001_port port[PM8001_MAX_PHYS]; 51762306a36Sopenharmony_ci u32 id; 51862306a36Sopenharmony_ci u32 irq; 51962306a36Sopenharmony_ci u32 iomb_size; /* SPC and SPCV IOMB size */ 52062306a36Sopenharmony_ci struct pm8001_device *devices; 52162306a36Sopenharmony_ci struct pm8001_ccb_info *ccb_info; 52262306a36Sopenharmony_ci u32 ccb_count; 52362306a36Sopenharmony_ci#ifdef PM8001_USE_MSIX 52462306a36Sopenharmony_ci int number_of_intr;/*will be used in remove()*/ 52562306a36Sopenharmony_ci char intr_drvname[PM8001_MAX_MSIX_VEC] 52662306a36Sopenharmony_ci [PM8001_NAME_LENGTH+1+3+1]; 52762306a36Sopenharmony_ci#endif 52862306a36Sopenharmony_ci#ifdef PM8001_USE_TASKLET 52962306a36Sopenharmony_ci struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC]; 53062306a36Sopenharmony_ci#endif 53162306a36Sopenharmony_ci u32 logging_level; 53262306a36Sopenharmony_ci u32 link_rate; 53362306a36Sopenharmony_ci u32 fw_status; 53462306a36Sopenharmony_ci u32 smp_exp_mode; 53562306a36Sopenharmony_ci bool controller_fatal_error; 53662306a36Sopenharmony_ci const struct firmware *fw_image; 53762306a36Sopenharmony_ci struct isr_param irq_vector[PM8001_MAX_MSIX_VEC]; 53862306a36Sopenharmony_ci u32 non_fatal_count; 53962306a36Sopenharmony_ci u32 non_fatal_read_length; 54062306a36Sopenharmony_ci u32 max_q_num; 54162306a36Sopenharmony_ci u32 ib_offset; 54262306a36Sopenharmony_ci u32 ob_offset; 54362306a36Sopenharmony_ci u32 ci_offset; 54462306a36Sopenharmony_ci u32 pi_offset; 54562306a36Sopenharmony_ci u32 max_memcnt; 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistruct pm8001_work { 54962306a36Sopenharmony_ci struct work_struct work; 55062306a36Sopenharmony_ci struct pm8001_hba_info *pm8001_ha; 55162306a36Sopenharmony_ci void *data; 55262306a36Sopenharmony_ci int handler; 55362306a36Sopenharmony_ci}; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistruct pm8001_fw_image_header { 55662306a36Sopenharmony_ci u8 vender_id[8]; 55762306a36Sopenharmony_ci u8 product_id; 55862306a36Sopenharmony_ci u8 hardware_rev; 55962306a36Sopenharmony_ci u8 dest_partition; 56062306a36Sopenharmony_ci u8 reserved; 56162306a36Sopenharmony_ci u8 fw_rev[4]; 56262306a36Sopenharmony_ci __be32 image_length; 56362306a36Sopenharmony_ci __be32 image_crc; 56462306a36Sopenharmony_ci __be32 startup_entry; 56562306a36Sopenharmony_ci} __attribute__((packed, aligned(4))); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci/** 56962306a36Sopenharmony_ci * FW Flash Update status values 57062306a36Sopenharmony_ci */ 57162306a36Sopenharmony_ci#define FLASH_UPDATE_COMPLETE_PENDING_REBOOT 0x00 57262306a36Sopenharmony_ci#define FLASH_UPDATE_IN_PROGRESS 0x01 57362306a36Sopenharmony_ci#define FLASH_UPDATE_HDR_ERR 0x02 57462306a36Sopenharmony_ci#define FLASH_UPDATE_OFFSET_ERR 0x03 57562306a36Sopenharmony_ci#define FLASH_UPDATE_CRC_ERR 0x04 57662306a36Sopenharmony_ci#define FLASH_UPDATE_LENGTH_ERR 0x05 57762306a36Sopenharmony_ci#define FLASH_UPDATE_HW_ERR 0x06 57862306a36Sopenharmony_ci#define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10 57962306a36Sopenharmony_ci#define FLASH_UPDATE_DISABLED 0x11 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci/* Device states */ 58262306a36Sopenharmony_ci#define DS_OPERATIONAL 0x01 58362306a36Sopenharmony_ci#define DS_PORT_IN_RESET 0x02 58462306a36Sopenharmony_ci#define DS_IN_RECOVERY 0x03 58562306a36Sopenharmony_ci#define DS_IN_ERROR 0x04 58662306a36Sopenharmony_ci#define DS_NON_OPERATIONAL 0x07 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/** 58962306a36Sopenharmony_ci * brief param structure for firmware flash update. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_cistruct fw_flash_updata_info { 59262306a36Sopenharmony_ci u32 cur_image_offset; 59362306a36Sopenharmony_ci u32 cur_image_len; 59462306a36Sopenharmony_ci u32 total_image_len; 59562306a36Sopenharmony_ci struct pm8001_prd sgl; 59662306a36Sopenharmony_ci}; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistruct fw_control_info { 59962306a36Sopenharmony_ci u32 retcode;/*ret code (status)*/ 60062306a36Sopenharmony_ci u32 phase;/*ret code phase*/ 60162306a36Sopenharmony_ci u32 phaseCmplt;/*percent complete for the current 60262306a36Sopenharmony_ci update phase */ 60362306a36Sopenharmony_ci u32 version;/*Hex encoded firmware version number*/ 60462306a36Sopenharmony_ci u32 offset;/*Used for downloading firmware */ 60562306a36Sopenharmony_ci u32 len; /*len of buffer*/ 60662306a36Sopenharmony_ci u32 size;/* Used in OS VPD and Trace get size 60762306a36Sopenharmony_ci operations.*/ 60862306a36Sopenharmony_ci u32 reserved;/* padding required for 64 bit 60962306a36Sopenharmony_ci alignment */ 61062306a36Sopenharmony_ci u8 buffer[];/* Start of buffer */ 61162306a36Sopenharmony_ci}; 61262306a36Sopenharmony_cistruct fw_control_ex { 61362306a36Sopenharmony_ci struct fw_control_info *fw_control; 61462306a36Sopenharmony_ci void *buffer;/* keep buffer pointer to be 61562306a36Sopenharmony_ci freed when the response comes*/ 61662306a36Sopenharmony_ci void *virtAddr;/* keep virtual address of the data */ 61762306a36Sopenharmony_ci void *usrAddr;/* keep virtual address of the 61862306a36Sopenharmony_ci user data */ 61962306a36Sopenharmony_ci dma_addr_t phys_addr; 62062306a36Sopenharmony_ci u32 len; /* len of buffer */ 62162306a36Sopenharmony_ci void *payload; /* pointer to IOCTL Payload */ 62262306a36Sopenharmony_ci u8 inProgress;/*if 1 - the IOCTL request is in 62362306a36Sopenharmony_ci progress */ 62462306a36Sopenharmony_ci void *param1; 62562306a36Sopenharmony_ci void *param2; 62662306a36Sopenharmony_ci void *param3; 62762306a36Sopenharmony_ci}; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci/* pm8001 workqueue */ 63062306a36Sopenharmony_ciextern struct workqueue_struct *pm8001_wq; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci/******************** function prototype *********************/ 63362306a36Sopenharmony_ciint pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out); 63462306a36Sopenharmony_ciu32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag); 63562306a36Sopenharmony_civoid pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, 63662306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 63762306a36Sopenharmony_ciint pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, 63862306a36Sopenharmony_ci void *funcdata); 63962306a36Sopenharmony_civoid pm8001_scan_start(struct Scsi_Host *shost); 64062306a36Sopenharmony_ciint pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time); 64162306a36Sopenharmony_ciint pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags); 64262306a36Sopenharmony_ciint pm8001_abort_task(struct sas_task *task); 64362306a36Sopenharmony_ciint pm8001_clear_task_set(struct domain_device *dev, u8 *lun); 64462306a36Sopenharmony_ciint pm8001_dev_found(struct domain_device *dev); 64562306a36Sopenharmony_civoid pm8001_dev_gone(struct domain_device *dev); 64662306a36Sopenharmony_ciint pm8001_lu_reset(struct domain_device *dev, u8 *lun); 64762306a36Sopenharmony_ciint pm8001_I_T_nexus_reset(struct domain_device *dev); 64862306a36Sopenharmony_ciint pm8001_I_T_nexus_event_handler(struct domain_device *dev); 64962306a36Sopenharmony_ciint pm8001_query_task(struct sas_task *task); 65062306a36Sopenharmony_civoid pm8001_port_formed(struct asd_sas_phy *sas_phy); 65162306a36Sopenharmony_civoid pm8001_open_reject_retry( 65262306a36Sopenharmony_ci struct pm8001_hba_info *pm8001_ha, 65362306a36Sopenharmony_ci struct sas_task *task_to_close, 65462306a36Sopenharmony_ci struct pm8001_device *device_to_close); 65562306a36Sopenharmony_ciint pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, 65662306a36Sopenharmony_ci dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, 65762306a36Sopenharmony_ci u32 mem_size, u32 align); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_civoid pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha); 66062306a36Sopenharmony_ciint pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, 66162306a36Sopenharmony_ci u32 q_index, u32 opCode, void *payload, size_t nb, 66262306a36Sopenharmony_ci u32 responseQueue); 66362306a36Sopenharmony_ciint pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, 66462306a36Sopenharmony_ci u16 messageSize, void **messagePtr); 66562306a36Sopenharmony_ciu32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, 66662306a36Sopenharmony_ci struct outbound_queue_table *circularQ, u8 bc); 66762306a36Sopenharmony_ciu32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, 66862306a36Sopenharmony_ci struct outbound_queue_table *circularQ, 66962306a36Sopenharmony_ci void **messagePtr1, u8 *pBC); 67062306a36Sopenharmony_ciint pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, 67162306a36Sopenharmony_ci struct pm8001_device *pm8001_dev, u32 state); 67262306a36Sopenharmony_ciint pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, 67362306a36Sopenharmony_ci void *payload); 67462306a36Sopenharmony_ciint pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, 67562306a36Sopenharmony_ci void *fw_flash_updata_info, u32 tag); 67662306a36Sopenharmony_ciint pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); 67762306a36Sopenharmony_ciint pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); 67862306a36Sopenharmony_ciint pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, 67962306a36Sopenharmony_ci struct pm8001_ccb_info *ccb, 68062306a36Sopenharmony_ci struct sas_tmf_task *tmf); 68162306a36Sopenharmony_ciint pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, 68262306a36Sopenharmony_ci struct pm8001_ccb_info *ccb); 68362306a36Sopenharmony_ciint pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id); 68462306a36Sopenharmony_civoid pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd); 68562306a36Sopenharmony_civoid pm8001_work_fn(struct work_struct *work); 68662306a36Sopenharmony_ciint pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, 68762306a36Sopenharmony_ci void *data, int handler); 68862306a36Sopenharmony_civoid pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, 68962306a36Sopenharmony_ci void *piomb); 69062306a36Sopenharmony_civoid pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, 69162306a36Sopenharmony_ci void *piomb); 69262306a36Sopenharmony_civoid pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, 69362306a36Sopenharmony_ci void *piomb); 69462306a36Sopenharmony_ciint pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, 69562306a36Sopenharmony_ci void *piomb); 69662306a36Sopenharmony_civoid pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate); 69762306a36Sopenharmony_civoid pm8001_get_attached_sas_addr(struct pm8001_phy *phy, u8 *sas_addr); 69862306a36Sopenharmony_civoid pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i); 69962306a36Sopenharmony_ciint pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); 70062306a36Sopenharmony_ciint pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); 70162306a36Sopenharmony_ciint pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, 70262306a36Sopenharmony_ci void *piomb); 70362306a36Sopenharmony_ciint pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha, void *piomb); 70462306a36Sopenharmony_ciint pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); 70562306a36Sopenharmony_civoid pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); 70662306a36Sopenharmony_cistruct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, 70762306a36Sopenharmony_ci u32 device_id); 70862306a36Sopenharmony_ciint pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ciint pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); 71162306a36Sopenharmony_civoid pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, 71262306a36Sopenharmony_ci u32 length, u8 *buf); 71362306a36Sopenharmony_civoid pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, 71462306a36Sopenharmony_ci u32 phy, u32 length, u32 *buf); 71562306a36Sopenharmony_ciint pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); 71662306a36Sopenharmony_cissize_t pm80xx_get_fatal_dump(struct device *cdev, 71762306a36Sopenharmony_ci struct device_attribute *attr, char *buf); 71862306a36Sopenharmony_cissize_t pm80xx_get_non_fatal_dump(struct device *cdev, 71962306a36Sopenharmony_ci struct device_attribute *attr, char *buf); 72062306a36Sopenharmony_cissize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf); 72162306a36Sopenharmony_ciint pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha); 72262306a36Sopenharmony_civoid pm8001_free_dev(struct pm8001_device *pm8001_dev); 72362306a36Sopenharmony_ci/* ctl shared API */ 72462306a36Sopenharmony_ciextern const struct attribute_group *pm8001_host_groups[]; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci#define PM8001_INVALID_TAG ((u32)-1) 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci/* 72962306a36Sopenharmony_ci * Allocate a new tag and return the corresponding ccb after initializing it. 73062306a36Sopenharmony_ci */ 73162306a36Sopenharmony_cistatic inline struct pm8001_ccb_info * 73262306a36Sopenharmony_cipm8001_ccb_alloc(struct pm8001_hba_info *pm8001_ha, 73362306a36Sopenharmony_ci struct pm8001_device *dev, struct sas_task *task) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci struct pm8001_ccb_info *ccb; 73662306a36Sopenharmony_ci struct request *rq = NULL; 73762306a36Sopenharmony_ci u32 tag; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (task) 74062306a36Sopenharmony_ci rq = sas_task_find_rq(task); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (rq) { 74362306a36Sopenharmony_ci tag = rq->tag + PM8001_RESERVE_SLOT; 74462306a36Sopenharmony_ci } else if (pm8001_tag_alloc(pm8001_ha, &tag)) { 74562306a36Sopenharmony_ci pm8001_dbg(pm8001_ha, FAIL, "Failed to allocate a tag\n"); 74662306a36Sopenharmony_ci return NULL; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci ccb = &pm8001_ha->ccb_info[tag]; 75062306a36Sopenharmony_ci ccb->task = task; 75162306a36Sopenharmony_ci ccb->n_elem = 0; 75262306a36Sopenharmony_ci ccb->ccb_tag = tag; 75362306a36Sopenharmony_ci ccb->device = dev; 75462306a36Sopenharmony_ci ccb->fw_control_context = NULL; 75562306a36Sopenharmony_ci ccb->open_retry = 0; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return ccb; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci/* 76162306a36Sopenharmony_ci * Free the tag of an initialized ccb. 76262306a36Sopenharmony_ci */ 76362306a36Sopenharmony_cistatic inline void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, 76462306a36Sopenharmony_ci struct pm8001_ccb_info *ccb) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci u32 tag = ccb->ccb_tag; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci /* 76962306a36Sopenharmony_ci * Cleanup the ccb to make sure that a manual scan of the adapter 77062306a36Sopenharmony_ci * ccb_info array can detect ccb's that are in use. 77162306a36Sopenharmony_ci * C.f. pm8001_open_reject_retry() 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_ci ccb->task = NULL; 77462306a36Sopenharmony_ci ccb->ccb_tag = PM8001_INVALID_TAG; 77562306a36Sopenharmony_ci ccb->device = NULL; 77662306a36Sopenharmony_ci ccb->fw_control_context = NULL; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci pm8001_tag_free(pm8001_ha, tag); 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic inline void pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, 78262306a36Sopenharmony_ci struct pm8001_ccb_info *ccb) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci struct sas_task *task = ccb->task; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci pm8001_ccb_task_free(pm8001_ha, ccb); 78762306a36Sopenharmony_ci smp_mb(); /*in order to force CPU ordering*/ 78862306a36Sopenharmony_ci task->task_done(task); 78962306a36Sopenharmony_ci} 79062306a36Sopenharmony_civoid pm8001_setds_completion(struct domain_device *dev); 79162306a36Sopenharmony_civoid pm8001_tmf_aborted(struct sas_task *task); 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci#endif 79462306a36Sopenharmony_ci 795