mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	scsi: mpi3mr: Base driver code
Implement basic pci device driver requirements: Device probing, memory allocation, mapping system registers, allocate irq lines, etc. Source is managed in mainly three different files: - mpi3mr_fw.c: Common code which interacts with underlying fw/hw. - mpi3mr_os.c: Common code which interacts with SCSI midlayer. - mpi3mr_app.c: Common code which interacts with application/ioctl. This is currently work in progress. Link: https://lore.kernel.org/r/20210520152545.2710479-3-kashyap.desai@broadcom.com Cc: sathya.prakash@broadcom.com Cc: bvanassche@acm.org Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									c4f7ac6461
								
							
						
					
					
						commit
						824a156633
					
				
					 5 changed files with 2761 additions and 0 deletions
				
			
		
							
								
								
									
										4
									
								
								drivers/scsi/mpi3mr/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								drivers/scsi/mpi3mr/Makefile
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
# mpi3mr makefile
 | 
			
		||||
obj-m += mpi3mr.o
 | 
			
		||||
mpi3mr-y +=  mpi3mr_os.o     \
 | 
			
		||||
		mpi3mr_fw.o \
 | 
			
		||||
							
								
								
									
										528
									
								
								drivers/scsi/mpi3mr/mpi3mr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										528
									
								
								drivers/scsi/mpi3mr/mpi3mr.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,528 @@
 | 
			
		|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
			
		||||
/*
 | 
			
		||||
 * Driver for Broadcom MPI3 Storage Controllers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2017-2021 Broadcom Inc.
 | 
			
		||||
 *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef MPI3MR_H_INCLUDED
 | 
			
		||||
#define MPI3MR_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <linux/blkdev.h>
 | 
			
		||||
#include <linux/blk-mq.h>
 | 
			
		||||
#include <linux/blk-mq-pci.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/dmapool.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/miscdevice.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/pci.h>
 | 
			
		||||
#include <linux/poll.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/uaccess.h>
 | 
			
		||||
#include <linux/utsname.h>
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <linux/workqueue.h>
 | 
			
		||||
#include <asm/unaligned.h>
 | 
			
		||||
#include <scsi/scsi.h>
 | 
			
		||||
#include <scsi/scsi_cmnd.h>
 | 
			
		||||
#include <scsi/scsi_dbg.h>
 | 
			
		||||
#include <scsi/scsi_device.h>
 | 
			
		||||
#include <scsi/scsi_host.h>
 | 
			
		||||
#include <scsi/scsi_tcq.h>
 | 
			
		||||
 | 
			
		||||
#include "mpi/mpi30_transport.h"
 | 
			
		||||
#include "mpi/mpi30_image.h"
 | 
			
		||||
#include "mpi/mpi30_init.h"
 | 
			
		||||
#include "mpi/mpi30_ioc.h"
 | 
			
		||||
#include "mpi3mr_debug.h"
 | 
			
		||||
 | 
			
		||||
/* Global list and lock for storing multiple adapters managed by the driver */
 | 
			
		||||
extern spinlock_t mrioc_list_lock;
 | 
			
		||||
extern struct list_head mrioc_list;
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_DRIVER_VERSION	"00.255.45.01"
 | 
			
		||||
#define MPI3MR_DRIVER_RELDATE	"12-December-2020"
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_DRIVER_NAME	"mpi3mr"
 | 
			
		||||
#define MPI3MR_DRIVER_LICENSE	"GPL"
 | 
			
		||||
#define MPI3MR_DRIVER_AUTHOR	"Broadcom Inc. <mpi3mr-linuxdrv.pdl@broadcom.com>"
 | 
			
		||||
#define MPI3MR_DRIVER_DESC	"MPI3 Storage Controller Device Driver"
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_NAME_LENGTH	32
 | 
			
		||||
#define IOCNAME			"%s: "
 | 
			
		||||
 | 
			
		||||
/* Definitions for internal SGL and Chain SGL buffers */
 | 
			
		||||
#define MPI3MR_PAGE_SIZE_4K		4096
 | 
			
		||||
#define MPI3MR_SG_DEPTH		(MPI3MR_PAGE_SIZE_4K / sizeof(struct mpi3_sge_common))
 | 
			
		||||
 | 
			
		||||
/* Definitions for MAX values for shost */
 | 
			
		||||
#define MPI3MR_MAX_CMDS_LUN	7
 | 
			
		||||
#define MPI3MR_MAX_CDB_LENGTH	32
 | 
			
		||||
 | 
			
		||||
/* Admin queue management definitions */
 | 
			
		||||
#define MPI3MR_ADMIN_REQ_Q_SIZE		(2 * MPI3MR_PAGE_SIZE_4K)
 | 
			
		||||
#define MPI3MR_ADMIN_REPLY_Q_SIZE	(4 * MPI3MR_PAGE_SIZE_4K)
 | 
			
		||||
#define MPI3MR_ADMIN_REQ_FRAME_SZ	128
 | 
			
		||||
#define MPI3MR_ADMIN_REPLY_FRAME_SZ	16
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Reserved Host Tag definitions */
 | 
			
		||||
#define MPI3MR_HOSTTAG_INVALID		0xFFFF
 | 
			
		||||
#define MPI3MR_HOSTTAG_INITCMDS		1
 | 
			
		||||
#define MPI3MR_HOSTTAG_IOCTLCMDS	2
 | 
			
		||||
#define MPI3MR_HOSTTAG_BLK_TMS		5
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_NUM_DEVRMCMD		1
 | 
			
		||||
#define MPI3MR_HOSTTAG_DEVRMCMD_MIN	(MPI3MR_HOSTTAG_BLK_TMS + 1)
 | 
			
		||||
#define MPI3MR_HOSTTAG_DEVRMCMD_MAX	(MPI3MR_HOSTTAG_DEVRMCMD_MIN + \
 | 
			
		||||
						MPI3MR_NUM_DEVRMCMD - 1)
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_INTERNAL_CMDS_RESVD     MPI3MR_HOSTTAG_DEVRMCMD_MAX
 | 
			
		||||
 | 
			
		||||
/* Reduced resource count definition for crash kernel */
 | 
			
		||||
#define MPI3MR_HOST_IOS_KDUMP		128
 | 
			
		||||
 | 
			
		||||
/* command/controller interaction timeout definitions in seconds */
 | 
			
		||||
#define MPI3MR_INTADMCMD_TIMEOUT		10
 | 
			
		||||
#define MPI3MR_RESETTM_TIMEOUT			30
 | 
			
		||||
#define MPI3MR_DEFAULT_SHUTDOWN_TIME		120
 | 
			
		||||
 | 
			
		||||
#define MPI3MR_WATCHDOG_INTERVAL		1000 /* in milli seconds */
 | 
			
		||||
 | 
			
		||||
/* Internal admin command state definitions*/
 | 
			
		||||
#define MPI3MR_CMD_NOTUSED	0x8000
 | 
			
		||||
#define MPI3MR_CMD_COMPLETE	0x0001
 | 
			
		||||
#define MPI3MR_CMD_PENDING	0x0002
 | 
			
		||||
#define MPI3MR_CMD_REPLY_VALID	0x0004
 | 
			
		||||
#define MPI3MR_CMD_RESET	0x0008
 | 
			
		||||
 | 
			
		||||
/* Definitions for Event replies and sense buffer allocated per controller */
 | 
			
		||||
#define MPI3MR_NUM_EVT_REPLIES	64
 | 
			
		||||
#define MPI3MR_SENSEBUF_SZ	256
 | 
			
		||||
#define MPI3MR_SENSEBUF_FACTOR	3
 | 
			
		||||
#define MPI3MR_CHAINBUF_FACTOR	3
 | 
			
		||||
 | 
			
		||||
/* Invalid target device handle */
 | 
			
		||||
#define MPI3MR_INVALID_DEV_HANDLE	0xFFFF
 | 
			
		||||
 | 
			
		||||
/* Controller Reset related definitions */
 | 
			
		||||
#define MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT	5
 | 
			
		||||
#define MPI3MR_MAX_RESET_RETRY_COUNT		3
 | 
			
		||||
 | 
			
		||||
/* ResponseCode definitions */
 | 
			
		||||
#define MPI3MR_RI_MASK_RESPCODE		(0x000000FF)
 | 
			
		||||
#define MPI3MR_RSP_TM_COMPLETE		0x00
 | 
			
		||||
#define MPI3MR_RSP_INVALID_FRAME	0x02
 | 
			
		||||
#define MPI3MR_RSP_TM_NOT_SUPPORTED	0x04
 | 
			
		||||
#define MPI3MR_RSP_TM_FAILED		0x05
 | 
			
		||||
#define MPI3MR_RSP_TM_SUCCEEDED		0x08
 | 
			
		||||
#define MPI3MR_RSP_TM_INVALID_LUN	0x09
 | 
			
		||||
#define MPI3MR_RSP_TM_OVERLAPPED_TAG	0x0A
 | 
			
		||||
#define MPI3MR_RSP_IO_QUEUED_ON_IOC \
 | 
			
		||||
			MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC
 | 
			
		||||
 | 
			
		||||
/* SGE Flag definition */
 | 
			
		||||
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
 | 
			
		||||
	(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
 | 
			
		||||
	MPI3_SGE_FLAGS_END_OF_LIST)
 | 
			
		||||
 | 
			
		||||
/* IOC State definitions */
 | 
			
		||||
enum mpi3mr_iocstate {
 | 
			
		||||
	MRIOC_STATE_READY = 1,
 | 
			
		||||
	MRIOC_STATE_RESET,
 | 
			
		||||
	MRIOC_STATE_FAULT,
 | 
			
		||||
	MRIOC_STATE_BECOMING_READY,
 | 
			
		||||
	MRIOC_STATE_RESET_REQUESTED,
 | 
			
		||||
	MRIOC_STATE_UNRECOVERABLE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Reset reason code definitions*/
 | 
			
		||||
enum mpi3mr_reset_reason {
 | 
			
		||||
	MPI3MR_RESET_FROM_BRINGUP = 1,
 | 
			
		||||
	MPI3MR_RESET_FROM_FAULT_WATCH = 2,
 | 
			
		||||
	MPI3MR_RESET_FROM_IOCTL = 3,
 | 
			
		||||
	MPI3MR_RESET_FROM_EH_HOS = 4,
 | 
			
		||||
	MPI3MR_RESET_FROM_TM_TIMEOUT = 5,
 | 
			
		||||
	MPI3MR_RESET_FROM_IOCTL_TIMEOUT = 6,
 | 
			
		||||
	MPI3MR_RESET_FROM_MUR_FAILURE = 7,
 | 
			
		||||
	MPI3MR_RESET_FROM_CTLR_CLEANUP = 8,
 | 
			
		||||
	MPI3MR_RESET_FROM_CIACTIV_FAULT = 9,
 | 
			
		||||
	MPI3MR_RESET_FROM_PE_TIMEOUT = 10,
 | 
			
		||||
	MPI3MR_RESET_FROM_TSU_TIMEOUT = 11,
 | 
			
		||||
	MPI3MR_RESET_FROM_DELREQQ_TIMEOUT = 12,
 | 
			
		||||
	MPI3MR_RESET_FROM_DELREPQ_TIMEOUT = 13,
 | 
			
		||||
	MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT = 14,
 | 
			
		||||
	MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT = 15,
 | 
			
		||||
	MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT = 16,
 | 
			
		||||
	MPI3MR_RESET_FROM_IOCINIT_TIMEOUT = 17,
 | 
			
		||||
	MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT = 18,
 | 
			
		||||
	MPI3MR_RESET_FROM_EVTACK_TIMEOUT = 19,
 | 
			
		||||
	MPI3MR_RESET_FROM_CIACTVRST_TIMER = 20,
 | 
			
		||||
	MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT = 21,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mpi3mr_compimg_ver - replica of component image
 | 
			
		||||
 * version defined in mpi30_image.h in host endianness
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
struct mpi3mr_compimg_ver {
 | 
			
		||||
	u16 build_num;
 | 
			
		||||
	u16 cust_id;
 | 
			
		||||
	u8 ph_minor;
 | 
			
		||||
	u8 ph_major;
 | 
			
		||||
	u8 gen_minor;
 | 
			
		||||
	u8 gen_major;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mpi3mr_ioc_facs - replica of component image version
 | 
			
		||||
 * defined in mpi30_ioc.h in host endianness
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
struct mpi3mr_ioc_facts {
 | 
			
		||||
	u32 ioc_capabilities;
 | 
			
		||||
	struct mpi3mr_compimg_ver fw_ver;
 | 
			
		||||
	u32 mpi_version;
 | 
			
		||||
	u16 max_reqs;
 | 
			
		||||
	u16 product_id;
 | 
			
		||||
	u16 op_req_sz;
 | 
			
		||||
	u16 reply_sz;
 | 
			
		||||
	u16 exceptions;
 | 
			
		||||
	u16 max_perids;
 | 
			
		||||
	u16 max_pds;
 | 
			
		||||
	u16 max_sasexpanders;
 | 
			
		||||
	u16 max_sasinitiators;
 | 
			
		||||
	u16 max_enclosures;
 | 
			
		||||
	u16 max_pcie_switches;
 | 
			
		||||
	u16 max_nvme;
 | 
			
		||||
	u16 max_vds;
 | 
			
		||||
	u16 max_hpds;
 | 
			
		||||
	u16 max_advhpds;
 | 
			
		||||
	u16 max_raidpds;
 | 
			
		||||
	u16 min_devhandle;
 | 
			
		||||
	u16 max_devhandle;
 | 
			
		||||
	u16 max_op_req_q;
 | 
			
		||||
	u16 max_op_reply_q;
 | 
			
		||||
	u16 shutdown_timeout;
 | 
			
		||||
	u8 ioc_num;
 | 
			
		||||
	u8 who_init;
 | 
			
		||||
	u16 max_msix_vectors;
 | 
			
		||||
	u8 personality;
 | 
			
		||||
	u8 dma_mask;
 | 
			
		||||
	u8 protocol_flags;
 | 
			
		||||
	u8 sge_mod_mask;
 | 
			
		||||
	u8 sge_mod_value;
 | 
			
		||||
	u8 sge_mod_shift;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct op_req_qinfo -  Operational Request Queue Information
 | 
			
		||||
 *
 | 
			
		||||
 * @ci: consumer index
 | 
			
		||||
 * @pi: producer index
 | 
			
		||||
 */
 | 
			
		||||
struct op_req_qinfo {
 | 
			
		||||
	u16 ci;
 | 
			
		||||
	u16 pi;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct op_reply_qinfo -  Operational Reply Queue Information
 | 
			
		||||
 *
 | 
			
		||||
 * @ci: consumer index
 | 
			
		||||
 * @qid: Queue Id starting from 1
 | 
			
		||||
 */
 | 
			
		||||
struct op_reply_qinfo {
 | 
			
		||||
	u16 ci;
 | 
			
		||||
	u16 qid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mpi3mr_intr_info -  Interrupt cookie information
 | 
			
		||||
 *
 | 
			
		||||
 * @mrioc: Adapter instance reference
 | 
			
		||||
 * @msix_index: MSIx index
 | 
			
		||||
 * @op_reply_q: Associated operational reply queue
 | 
			
		||||
 * @name: Dev name for the irq claiming device
 | 
			
		||||
 */
 | 
			
		||||
struct mpi3mr_intr_info {
 | 
			
		||||
	struct mpi3mr_ioc *mrioc;
 | 
			
		||||
	u16 msix_index;
 | 
			
		||||
	struct op_reply_qinfo *op_reply_q;
 | 
			
		||||
	char name[MPI3MR_NAME_LENGTH];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mpi3mr_drv_cmd - Internal command tracker
 | 
			
		||||
 *
 | 
			
		||||
 * @mutex: Command mutex
 | 
			
		||||
 * @done: Completeor for wakeup
 | 
			
		||||
 * @reply: Firmware reply for internal commands
 | 
			
		||||
 * @sensebuf: Sensebuf for SCSI IO commands
 | 
			
		||||
 * @state: Command State
 | 
			
		||||
 * @dev_handle: Firmware handle for device specific commands
 | 
			
		||||
 * @ioc_status: IOC status from the firmware
 | 
			
		||||
 * @ioc_loginfo:IOC log info from the firmware
 | 
			
		||||
 * @is_waiting: Is the command issued in block mode
 | 
			
		||||
 * @retry_count: Retry count for retriable commands
 | 
			
		||||
 * @host_tag: Host tag used by the command
 | 
			
		||||
 * @callback: Callback for non blocking commands
 | 
			
		||||
 */
 | 
			
		||||
struct mpi3mr_drv_cmd {
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
	struct completion done;
 | 
			
		||||
	void *reply;
 | 
			
		||||
	u8 *sensebuf;
 | 
			
		||||
	u16 state;
 | 
			
		||||
	u16 dev_handle;
 | 
			
		||||
	u16 ioc_status;
 | 
			
		||||
	u32 ioc_loginfo;
 | 
			
		||||
	u8 is_waiting;
 | 
			
		||||
	u8 retry_count;
 | 
			
		||||
	u16 host_tag;
 | 
			
		||||
 | 
			
		||||
	void (*callback)(struct mpi3mr_ioc *mrioc,
 | 
			
		||||
	    struct mpi3mr_drv_cmd *drv_cmd);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct chain_element - memory descriptor structure to store
 | 
			
		||||
 * virtual and dma addresses for chain elements.
 | 
			
		||||
 *
 | 
			
		||||
 * @addr: virtual address
 | 
			
		||||
 * @dma_addr: dma address
 | 
			
		||||
 */
 | 
			
		||||
struct chain_element {
 | 
			
		||||
	void *addr;
 | 
			
		||||
	dma_addr_t dma_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct scmd_priv - SCSI command private data
 | 
			
		||||
 *
 | 
			
		||||
 * @host_tag: Host tag specific to operational queue
 | 
			
		||||
 * @in_lld_scope: Command in LLD scope or not
 | 
			
		||||
 * @scmd: SCSI Command pointer
 | 
			
		||||
 * @req_q_idx: Operational request queue index
 | 
			
		||||
 * @chain_idx: Chain frame index
 | 
			
		||||
 * @mpi3mr_scsiio_req: MPI SCSI IO request
 | 
			
		||||
 */
 | 
			
		||||
struct scmd_priv {
 | 
			
		||||
	u16 host_tag;
 | 
			
		||||
	u8 in_lld_scope;
 | 
			
		||||
	struct scsi_cmnd *scmd;
 | 
			
		||||
	u16 req_q_idx;
 | 
			
		||||
	int chain_idx;
 | 
			
		||||
	u8 mpi3mr_scsiio_req[MPI3MR_ADMIN_REQ_FRAME_SZ];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct mpi3mr_ioc - Adapter anchor structure stored in shost
 | 
			
		||||
 * private data
 | 
			
		||||
 *
 | 
			
		||||
 * @list: List pointer
 | 
			
		||||
 * @pdev: PCI device pointer
 | 
			
		||||
 * @shost: Scsi_Host pointer
 | 
			
		||||
 * @id: Controller ID
 | 
			
		||||
 * @cpu_count: Number of online CPUs
 | 
			
		||||
 * @name: Controller ASCII name
 | 
			
		||||
 * @driver_name: Driver ASCII name
 | 
			
		||||
 * @sysif_regs: System interface registers virtual address
 | 
			
		||||
 * @sysif_regs_phys: System interface registers physical address
 | 
			
		||||
 * @bars: PCI BARS
 | 
			
		||||
 * @dma_mask: DMA mask
 | 
			
		||||
 * @msix_count: Number of MSIX vectors used
 | 
			
		||||
 * @intr_enabled: Is interrupts enabled
 | 
			
		||||
 * @num_admin_req: Number of admin requests
 | 
			
		||||
 * @admin_req_q_sz: Admin request queue size
 | 
			
		||||
 * @admin_req_pi: Admin request queue producer index
 | 
			
		||||
 * @admin_req_ci: Admin request queue consumer index
 | 
			
		||||
 * @admin_req_base: Admin request queue base virtual address
 | 
			
		||||
 * @admin_req_dma: Admin request queue base dma address
 | 
			
		||||
 * @admin_req_lock: Admin queue access lock
 | 
			
		||||
 * @num_admin_replies: Number of admin replies
 | 
			
		||||
 * @admin_reply_q_sz: Admin reply queue size
 | 
			
		||||
 * @admin_reply_ci: Admin reply queue consumer index
 | 
			
		||||
 * @admin_reply_ephase:Admin reply queue expected phase
 | 
			
		||||
 * @admin_reply_base: Admin reply queue base virtual address
 | 
			
		||||
 * @admin_reply_dma: Admin reply queue base dma address
 | 
			
		||||
 * @ready_timeout: Controller ready timeout
 | 
			
		||||
 * @intr_info: Interrupt cookie pointer
 | 
			
		||||
 * @intr_info_count: Number of interrupt cookies
 | 
			
		||||
 * @num_queues: Number of operational queues
 | 
			
		||||
 * @num_op_req_q: Number of operational request queues
 | 
			
		||||
 * @req_qinfo: Operational request queue info pointer
 | 
			
		||||
 * @num_op_reply_q: Number of operational reply queues
 | 
			
		||||
 * @op_reply_qinfo: Operational reply queue info pointer
 | 
			
		||||
 * @init_cmds: Command tracker for initialization commands
 | 
			
		||||
 * @facts: Cached IOC facts data
 | 
			
		||||
 * @op_reply_desc_sz: Operational reply descriptor size
 | 
			
		||||
 * @num_reply_bufs: Number of reply buffers allocated
 | 
			
		||||
 * @reply_buf_pool: Reply buffer pool
 | 
			
		||||
 * @reply_buf: Reply buffer base virtual address
 | 
			
		||||
 * @reply_buf_dma: Reply buffer DMA address
 | 
			
		||||
 * @reply_buf_dma_max_address: Reply DMA address max limit
 | 
			
		||||
 * @reply_free_qsz: Reply free queue size
 | 
			
		||||
 * @reply_free_q_pool: Reply free queue pool
 | 
			
		||||
 * @reply_free_q: Reply free queue base virtual address
 | 
			
		||||
 * @reply_free_q_dma: Reply free queue base DMA address
 | 
			
		||||
 * @reply_free_queue_lock: Reply free queue lock
 | 
			
		||||
 * @reply_free_queue_host_index: Reply free queue host index
 | 
			
		||||
 * @num_sense_bufs: Number of sense buffers
 | 
			
		||||
 * @sense_buf_pool: Sense buffer pool
 | 
			
		||||
 * @sense_buf: Sense buffer base virtual address
 | 
			
		||||
 * @sense_buf_dma: Sense buffer base DMA address
 | 
			
		||||
 * @sense_buf_q_sz: Sense buffer queue size
 | 
			
		||||
 * @sense_buf_q_pool: Sense buffer queue pool
 | 
			
		||||
 * @sense_buf_q: Sense buffer queue virtual address
 | 
			
		||||
 * @sense_buf_q_dma: Sense buffer queue DMA address
 | 
			
		||||
 * @sbq_lock: Sense buffer queue lock
 | 
			
		||||
 * @sbq_host_index: Sense buffer queuehost index
 | 
			
		||||
 * @is_driver_loading: Is driver still loading
 | 
			
		||||
 * @max_host_ios: Maximum host I/O count
 | 
			
		||||
 * @chain_buf_count: Chain buffer count
 | 
			
		||||
 * @chain_buf_pool: Chain buffer pool
 | 
			
		||||
 * @chain_sgl_list: Chain SGL list
 | 
			
		||||
 * @chain_bitmap_sz: Chain buffer allocator bitmap size
 | 
			
		||||
 * @chain_bitmap: Chain buffer allocator bitmap
 | 
			
		||||
 * @reset_in_progress: Reset in progress flag
 | 
			
		||||
 * @unrecoverable: Controller unrecoverable flag
 | 
			
		||||
 * @logging_level: Controller debug logging level
 | 
			
		||||
 * @current_event: Firmware event currently in process
 | 
			
		||||
 * @driver_info: Driver, Kernel, OS information to firmware
 | 
			
		||||
 * @change_count: Topology change count
 | 
			
		||||
 */
 | 
			
		||||
struct mpi3mr_ioc {
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	struct pci_dev *pdev;
 | 
			
		||||
	struct Scsi_Host *shost;
 | 
			
		||||
	u8 id;
 | 
			
		||||
	int cpu_count;
 | 
			
		||||
 | 
			
		||||
	char name[MPI3MR_NAME_LENGTH];
 | 
			
		||||
	char driver_name[MPI3MR_NAME_LENGTH];
 | 
			
		||||
 | 
			
		||||
	volatile struct mpi3_sysif_registers __iomem *sysif_regs;
 | 
			
		||||
	resource_size_t sysif_regs_phys;
 | 
			
		||||
	int bars;
 | 
			
		||||
	u64 dma_mask;
 | 
			
		||||
 | 
			
		||||
	u16 msix_count;
 | 
			
		||||
	u8 intr_enabled;
 | 
			
		||||
 | 
			
		||||
	u16 num_admin_req;
 | 
			
		||||
	u32 admin_req_q_sz;
 | 
			
		||||
	u16 admin_req_pi;
 | 
			
		||||
	u16 admin_req_ci;
 | 
			
		||||
	void *admin_req_base;
 | 
			
		||||
	dma_addr_t admin_req_dma;
 | 
			
		||||
	spinlock_t admin_req_lock;
 | 
			
		||||
 | 
			
		||||
	u16 num_admin_replies;
 | 
			
		||||
	u32 admin_reply_q_sz;
 | 
			
		||||
	u16 admin_reply_ci;
 | 
			
		||||
	u8 admin_reply_ephase;
 | 
			
		||||
	void *admin_reply_base;
 | 
			
		||||
	dma_addr_t admin_reply_dma;
 | 
			
		||||
 | 
			
		||||
	u32 ready_timeout;
 | 
			
		||||
 | 
			
		||||
	struct mpi3mr_intr_info *intr_info;
 | 
			
		||||
	u16 intr_info_count;
 | 
			
		||||
 | 
			
		||||
	u16 num_queues;
 | 
			
		||||
	u16 num_op_req_q;
 | 
			
		||||
	struct op_req_qinfo *req_qinfo;
 | 
			
		||||
 | 
			
		||||
	u16 num_op_reply_q;
 | 
			
		||||
	struct op_reply_qinfo *op_reply_qinfo;
 | 
			
		||||
 | 
			
		||||
	struct mpi3mr_drv_cmd init_cmds;
 | 
			
		||||
	struct mpi3mr_ioc_facts facts;
 | 
			
		||||
	u16 op_reply_desc_sz;
 | 
			
		||||
 | 
			
		||||
	u32 num_reply_bufs;
 | 
			
		||||
	struct dma_pool *reply_buf_pool;
 | 
			
		||||
	u8 *reply_buf;
 | 
			
		||||
	dma_addr_t reply_buf_dma;
 | 
			
		||||
	dma_addr_t reply_buf_dma_max_address;
 | 
			
		||||
 | 
			
		||||
	u16 reply_free_qsz;
 | 
			
		||||
	struct dma_pool *reply_free_q_pool;
 | 
			
		||||
	__le64 *reply_free_q;
 | 
			
		||||
	dma_addr_t reply_free_q_dma;
 | 
			
		||||
	spinlock_t reply_free_queue_lock;
 | 
			
		||||
	u32 reply_free_queue_host_index;
 | 
			
		||||
 | 
			
		||||
	u32 num_sense_bufs;
 | 
			
		||||
	struct dma_pool *sense_buf_pool;
 | 
			
		||||
	u8 *sense_buf;
 | 
			
		||||
	dma_addr_t sense_buf_dma;
 | 
			
		||||
 | 
			
		||||
	u16 sense_buf_q_sz;
 | 
			
		||||
	struct dma_pool *sense_buf_q_pool;
 | 
			
		||||
	__le64 *sense_buf_q;
 | 
			
		||||
	dma_addr_t sense_buf_q_dma;
 | 
			
		||||
	spinlock_t sbq_lock;
 | 
			
		||||
	u32 sbq_host_index;
 | 
			
		||||
 | 
			
		||||
	u8 is_driver_loading;
 | 
			
		||||
 | 
			
		||||
	u16 max_host_ios;
 | 
			
		||||
 | 
			
		||||
	u32 chain_buf_count;
 | 
			
		||||
	struct dma_pool *chain_buf_pool;
 | 
			
		||||
	struct chain_element *chain_sgl_list;
 | 
			
		||||
	u16  chain_bitmap_sz;
 | 
			
		||||
	void *chain_bitmap;
 | 
			
		||||
 | 
			
		||||
	u8 reset_in_progress;
 | 
			
		||||
	u8 unrecoverable;
 | 
			
		||||
 | 
			
		||||
	int logging_level;
 | 
			
		||||
 | 
			
		||||
	struct mpi3mr_fwevt *current_event;
 | 
			
		||||
	struct mpi3_driver_info_layout driver_info;
 | 
			
		||||
	u16 change_count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req,
 | 
			
		||||
u16 admin_req_sz, u8 ignore_reset);
 | 
			
		||||
void mpi3mr_add_sg_single(void *paddr, u8 flags, u32 length,
 | 
			
		||||
			  dma_addr_t dma_addr);
 | 
			
		||||
void mpi3mr_build_zero_len_sge(void *paddr);
 | 
			
		||||
void *mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_ioc *mrioc,
 | 
			
		||||
				     dma_addr_t phys_addr);
 | 
			
		||||
void *mpi3mr_get_reply_virt_addr(struct mpi3mr_ioc *mrioc,
 | 
			
		||||
				     dma_addr_t phys_addr);
 | 
			
		||||
void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc,
 | 
			
		||||
				     u64 sense_buf_dma);
 | 
			
		||||
 | 
			
		||||
void mpi3mr_start_watchdog(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
void mpi3mr_stop_watchdog(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
 | 
			
		||||
int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
 | 
			
		||||
			      u32 reset_reason, u8 snapdump);
 | 
			
		||||
void mpi3mr_ioc_disable_intr(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
 | 
			
		||||
enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc);
 | 
			
		||||
 | 
			
		||||
#endif /*MPI3MR_H_INCLUDED*/
 | 
			
		||||
							
								
								
									
										60
									
								
								drivers/scsi/mpi3mr/mpi3mr_debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								drivers/scsi/mpi3mr/mpi3mr_debug.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
			
		||||
/*
 | 
			
		||||
 * Driver for Broadcom MPI3 Storage Controllers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2017-2021 Broadcom Inc.
 | 
			
		||||
 *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef MPI3SAS_DEBUG_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#define MPI3SAS_DEBUG_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * debug levels
 | 
			
		||||
 */
 | 
			
		||||
#define MPI3_DEBUG			0x00000001
 | 
			
		||||
#define MPI3_DEBUG_MSG_FRAME		0x00000002
 | 
			
		||||
#define MPI3_DEBUG_SG			0x00000004
 | 
			
		||||
#define MPI3_DEBUG_EVENTS		0x00000008
 | 
			
		||||
#define MPI3_DEBUG_EVENT_WORK_TASK	0x00000010
 | 
			
		||||
#define MPI3_DEBUG_INIT			0x00000020
 | 
			
		||||
#define MPI3_DEBUG_EXIT			0x00000040
 | 
			
		||||
#define MPI3_DEBUG_FAIL			0x00000080
 | 
			
		||||
#define MPI3_DEBUG_TM			0x00000100
 | 
			
		||||
#define MPI3_DEBUG_REPLY		0x00000200
 | 
			
		||||
#define MPI3_DEBUG_HANDSHAKE		0x00000400
 | 
			
		||||
#define MPI3_DEBUG_CONFIG		0x00000800
 | 
			
		||||
#define MPI3_DEBUG_DL			0x00001000
 | 
			
		||||
#define MPI3_DEBUG_RESET		0x00002000
 | 
			
		||||
#define MPI3_DEBUG_SCSI			0x00004000
 | 
			
		||||
#define MPI3_DEBUG_IOCTL		0x00008000
 | 
			
		||||
#define MPI3_DEBUG_CSMISAS		0x00010000
 | 
			
		||||
#define MPI3_DEBUG_SAS			0x00020000
 | 
			
		||||
#define MPI3_DEBUG_TRANSPORT		0x00040000
 | 
			
		||||
#define MPI3_DEBUG_TASK_SET_FULL	0x00080000
 | 
			
		||||
#define MPI3_DEBUG_TRIGGER_DIAG		0x00200000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * debug macros
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define ioc_err(ioc, fmt, ...) \
 | 
			
		||||
	pr_err("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
 | 
			
		||||
#define ioc_notice(ioc, fmt, ...) \
 | 
			
		||||
	pr_notice("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
 | 
			
		||||
#define ioc_warn(ioc, fmt, ...) \
 | 
			
		||||
	pr_warn("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
 | 
			
		||||
#define ioc_info(ioc, fmt, ...) \
 | 
			
		||||
	pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define dbgprint(IOC, FMT, ...) \
 | 
			
		||||
	do { \
 | 
			
		||||
		if (IOC->logging_level & MPI3_DEBUG) \
 | 
			
		||||
			pr_info("%s: " FMT, (IOC)->name, ##__VA_ARGS__); \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#endif /* MPT3SAS_DEBUG_H_INCLUDED */
 | 
			
		||||
							
								
								
									
										1805
									
								
								drivers/scsi/mpi3mr/mpi3mr_fw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1805
									
								
								drivers/scsi/mpi3mr/mpi3mr_fw.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										364
									
								
								drivers/scsi/mpi3mr/mpi3mr_os.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								drivers/scsi/mpi3mr/mpi3mr_os.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,364 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
/*
 | 
			
		||||
 * Driver for Broadcom MPI3 Storage Controllers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2017-2021 Broadcom Inc.
 | 
			
		||||
 *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "mpi3mr.h"
 | 
			
		||||
 | 
			
		||||
/* global driver scop variables */
 | 
			
		||||
LIST_HEAD(mrioc_list);
 | 
			
		||||
DEFINE_SPINLOCK(mrioc_list_lock);
 | 
			
		||||
static int mrioc_ids;
 | 
			
		||||
static int warn_non_secure_ctlr;
 | 
			
		||||
 | 
			
		||||
MODULE_AUTHOR(MPI3MR_DRIVER_AUTHOR);
 | 
			
		||||
MODULE_DESCRIPTION(MPI3MR_DRIVER_DESC);
 | 
			
		||||
MODULE_LICENSE(MPI3MR_DRIVER_LICENSE);
 | 
			
		||||
MODULE_VERSION(MPI3MR_DRIVER_VERSION);
 | 
			
		||||
 | 
			
		||||
/* Module parameters*/
 | 
			
		||||
int logging_level;
 | 
			
		||||
module_param(logging_level, int, 0);
 | 
			
		||||
MODULE_PARM_DESC(logging_level,
 | 
			
		||||
	" bits for enabling additional logging info (default=0)");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_map_queues - Map queues callback handler
 | 
			
		||||
 * @shost: SCSI host reference
 | 
			
		||||
 *
 | 
			
		||||
 * Call the blk_mq_pci_map_queues with from which operational
 | 
			
		||||
 * queue the mapping has to be done
 | 
			
		||||
 *
 | 
			
		||||
 * Return: return of blk_mq_pci_map_queues
 | 
			
		||||
 */
 | 
			
		||||
static int mpi3mr_map_queues(struct Scsi_Host *shost)
 | 
			
		||||
{
 | 
			
		||||
	struct mpi3mr_ioc *mrioc = shost_priv(shost);
 | 
			
		||||
 | 
			
		||||
	return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
 | 
			
		||||
	    mrioc->pdev, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_slave_destroy - Slave destroy callback handler
 | 
			
		||||
 * @sdev: SCSI device reference
 | 
			
		||||
 *
 | 
			
		||||
 * Cleanup and free per device(lun) private data.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Nothing.
 | 
			
		||||
 */
 | 
			
		||||
static void mpi3mr_slave_destroy(struct scsi_device *sdev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_target_destroy - Target destroy callback handler
 | 
			
		||||
 * @starget: SCSI target reference
 | 
			
		||||
 *
 | 
			
		||||
 * Cleanup and free per target private data.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Nothing.
 | 
			
		||||
 */
 | 
			
		||||
static void mpi3mr_target_destroy(struct scsi_target *starget)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_slave_configure - Slave configure callback handler
 | 
			
		||||
 * @sdev: SCSI device reference
 | 
			
		||||
 *
 | 
			
		||||
 * Configure queue depth, max hardware sectors and virt boundary
 | 
			
		||||
 * as required
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 always.
 | 
			
		||||
 */
 | 
			
		||||
static int mpi3mr_slave_configure(struct scsi_device *sdev)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_slave_alloc -Slave alloc callback handler
 | 
			
		||||
 * @sdev: SCSI device reference
 | 
			
		||||
 *
 | 
			
		||||
 * Allocate per device(lun) private data and initialize it.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 on success -ENOMEM on memory allocation failure.
 | 
			
		||||
 */
 | 
			
		||||
static int mpi3mr_slave_alloc(struct scsi_device *sdev)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_target_alloc - Target alloc callback handler
 | 
			
		||||
 * @starget: SCSI target reference
 | 
			
		||||
 *
 | 
			
		||||
 * Allocate per target private data and initialize it.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 on success -ENOMEM on memory allocation failure.
 | 
			
		||||
 */
 | 
			
		||||
static int mpi3mr_target_alloc(struct scsi_target *starget)
 | 
			
		||||
{
 | 
			
		||||
	int retval = -ENODEV;
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_qcmd - I/O request despatcher
 | 
			
		||||
 * @shost: SCSI Host reference
 | 
			
		||||
 * @scmd: SCSI Command reference
 | 
			
		||||
 *
 | 
			
		||||
 * Issues the SCSI Command as an MPI3 request.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 on successful queueing of the request or if the
 | 
			
		||||
 *         request is completed with failure.
 | 
			
		||||
 *         SCSI_MLQUEUE_DEVICE_BUSY when the device is busy.
 | 
			
		||||
 *         SCSI_MLQUEUE_HOST_BUSY when the host queue is full.
 | 
			
		||||
 */
 | 
			
		||||
static int mpi3mr_qcmd(struct Scsi_Host *shost,
 | 
			
		||||
	struct scsi_cmnd *scmd)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
 | 
			
		||||
	scmd->result = DID_NO_CONNECT << 16;
 | 
			
		||||
	scmd->scsi_done(scmd);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct scsi_host_template mpi3mr_driver_template = {
 | 
			
		||||
	.module				= THIS_MODULE,
 | 
			
		||||
	.name				= "MPI3 Storage Controller",
 | 
			
		||||
	.proc_name			= MPI3MR_DRIVER_NAME,
 | 
			
		||||
	.queuecommand			= mpi3mr_qcmd,
 | 
			
		||||
	.target_alloc			= mpi3mr_target_alloc,
 | 
			
		||||
	.slave_alloc			= mpi3mr_slave_alloc,
 | 
			
		||||
	.slave_configure		= mpi3mr_slave_configure,
 | 
			
		||||
	.target_destroy			= mpi3mr_target_destroy,
 | 
			
		||||
	.slave_destroy			= mpi3mr_slave_destroy,
 | 
			
		||||
	.map_queues			= mpi3mr_map_queues,
 | 
			
		||||
	.no_write_same			= 1,
 | 
			
		||||
	.can_queue			= 1,
 | 
			
		||||
	.this_id			= -1,
 | 
			
		||||
	.sg_tablesize			= MPI3MR_SG_DEPTH,
 | 
			
		||||
	/* max xfer supported is 1M (2K in 512 byte sized sectors)
 | 
			
		||||
	 */
 | 
			
		||||
	.max_sectors			= 2048,
 | 
			
		||||
	.cmd_per_lun			= MPI3MR_MAX_CMDS_LUN,
 | 
			
		||||
	.track_queue_depth		= 1,
 | 
			
		||||
	.cmd_size			= sizeof(struct scmd_priv),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_init_drv_cmd - Initialize internal command tracker
 | 
			
		||||
 * @cmdptr: Internal command tracker
 | 
			
		||||
 * @host_tag: Host tag used for the specific command
 | 
			
		||||
 *
 | 
			
		||||
 * Initialize the internal command tracker structure with
 | 
			
		||||
 * specified host tag.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Nothing.
 | 
			
		||||
 */
 | 
			
		||||
static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr,
 | 
			
		||||
	u16 host_tag)
 | 
			
		||||
{
 | 
			
		||||
	mutex_init(&cmdptr->mutex);
 | 
			
		||||
	cmdptr->reply = NULL;
 | 
			
		||||
	cmdptr->state = MPI3MR_CMD_NOTUSED;
 | 
			
		||||
	cmdptr->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
 | 
			
		||||
	cmdptr->host_tag = host_tag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_probe - PCI probe callback
 | 
			
		||||
 * @pdev: PCI device instance
 | 
			
		||||
 * @id: PCI device ID details
 | 
			
		||||
 *
 | 
			
		||||
 * controller initialization routine. Checks the security status
 | 
			
		||||
 * of the controller and if it is invalid or tampered return the
 | 
			
		||||
 * probe without initializing the controller. Otherwise,
 | 
			
		||||
 * allocate per adapter instance through shost_priv and
 | 
			
		||||
 * initialize controller specific data structures, initializae
 | 
			
		||||
 * the controller hardware, add shost to the SCSI subsystem.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 on success, non-zero on failure.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
			
		||||
{
 | 
			
		||||
	struct mpi3mr_ioc *mrioc = NULL;
 | 
			
		||||
	struct Scsi_Host *shost = NULL;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
 | 
			
		||||
	shost = scsi_host_alloc(&mpi3mr_driver_template,
 | 
			
		||||
	    sizeof(struct mpi3mr_ioc));
 | 
			
		||||
	if (!shost) {
 | 
			
		||||
		retval = -ENODEV;
 | 
			
		||||
		goto shost_failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mrioc = shost_priv(shost);
 | 
			
		||||
	mrioc->id = mrioc_ids++;
 | 
			
		||||
	sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME);
 | 
			
		||||
	sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id);
 | 
			
		||||
	INIT_LIST_HEAD(&mrioc->list);
 | 
			
		||||
	spin_lock(&mrioc_list_lock);
 | 
			
		||||
	list_add_tail(&mrioc->list, &mrioc_list);
 | 
			
		||||
	spin_unlock(&mrioc_list_lock);
 | 
			
		||||
 | 
			
		||||
	spin_lock_init(&mrioc->admin_req_lock);
 | 
			
		||||
	spin_lock_init(&mrioc->reply_free_queue_lock);
 | 
			
		||||
	spin_lock_init(&mrioc->sbq_lock);
 | 
			
		||||
 | 
			
		||||
	mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS);
 | 
			
		||||
 | 
			
		||||
	mrioc->logging_level = logging_level;
 | 
			
		||||
	mrioc->shost = shost;
 | 
			
		||||
	mrioc->pdev = pdev;
 | 
			
		||||
 | 
			
		||||
	/* init shost parameters */
 | 
			
		||||
	shost->max_cmd_len = MPI3MR_MAX_CDB_LENGTH;
 | 
			
		||||
	shost->max_lun = -1;
 | 
			
		||||
	shost->unique_id = mrioc->id;
 | 
			
		||||
 | 
			
		||||
	shost->max_channel = 1;
 | 
			
		||||
	shost->max_id = 0xFFFFFFFF;
 | 
			
		||||
 | 
			
		||||
	mrioc->is_driver_loading = 1;
 | 
			
		||||
	if (mpi3mr_init_ioc(mrioc)) {
 | 
			
		||||
		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 | 
			
		||||
		    __FILE__, __LINE__, __func__);
 | 
			
		||||
		retval = -ENODEV;
 | 
			
		||||
		goto out_iocinit_failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	shost->nr_hw_queues = mrioc->num_op_reply_q;
 | 
			
		||||
	shost->can_queue = mrioc->max_host_ios;
 | 
			
		||||
	shost->sg_tablesize = MPI3MR_SG_DEPTH;
 | 
			
		||||
	shost->max_id = mrioc->facts.max_perids;
 | 
			
		||||
 | 
			
		||||
	retval = scsi_add_host(shost, &pdev->dev);
 | 
			
		||||
	if (retval) {
 | 
			
		||||
		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 | 
			
		||||
		    __FILE__, __LINE__, __func__);
 | 
			
		||||
		goto addhost_failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scsi_scan_host(shost);
 | 
			
		||||
	return retval;
 | 
			
		||||
 | 
			
		||||
addhost_failed:
 | 
			
		||||
	mpi3mr_cleanup_ioc(mrioc);
 | 
			
		||||
out_iocinit_failed:
 | 
			
		||||
	spin_lock(&mrioc_list_lock);
 | 
			
		||||
	list_del(&mrioc->list);
 | 
			
		||||
	spin_unlock(&mrioc_list_lock);
 | 
			
		||||
	scsi_host_put(shost);
 | 
			
		||||
shost_failed:
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_remove - PCI remove callback
 | 
			
		||||
 * @pdev: PCI device instance
 | 
			
		||||
 *
 | 
			
		||||
 * Free up all memory and resources associated with the
 | 
			
		||||
 * controllerand target devices, unregister the shost.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Nothing.
 | 
			
		||||
 */
 | 
			
		||||
static void mpi3mr_remove(struct pci_dev *pdev)
 | 
			
		||||
{
 | 
			
		||||
	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 | 
			
		||||
	struct mpi3mr_ioc *mrioc;
 | 
			
		||||
 | 
			
		||||
	mrioc = shost_priv(shost);
 | 
			
		||||
	while (mrioc->reset_in_progress || mrioc->is_driver_loading)
 | 
			
		||||
		ssleep(1);
 | 
			
		||||
 | 
			
		||||
	scsi_remove_host(shost);
 | 
			
		||||
 | 
			
		||||
	mpi3mr_cleanup_ioc(mrioc);
 | 
			
		||||
 | 
			
		||||
	spin_lock(&mrioc_list_lock);
 | 
			
		||||
	list_del(&mrioc->list);
 | 
			
		||||
	spin_unlock(&mrioc_list_lock);
 | 
			
		||||
 | 
			
		||||
	scsi_host_put(shost);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mpi3mr_shutdown - PCI shutdown callback
 | 
			
		||||
 * @pdev: PCI device instance
 | 
			
		||||
 *
 | 
			
		||||
 * Free up all memory and resources associated with the
 | 
			
		||||
 * controller
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Nothing.
 | 
			
		||||
 */
 | 
			
		||||
static void mpi3mr_shutdown(struct pci_dev *pdev)
 | 
			
		||||
{
 | 
			
		||||
	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 | 
			
		||||
	struct mpi3mr_ioc *mrioc;
 | 
			
		||||
 | 
			
		||||
	if (!shost)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	mrioc = shost_priv(shost);
 | 
			
		||||
	while (mrioc->reset_in_progress || mrioc->is_driver_loading)
 | 
			
		||||
		ssleep(1);
 | 
			
		||||
 | 
			
		||||
	mpi3mr_cleanup_ioc(mrioc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pci_device_id mpi3mr_pci_id_table[] = {
 | 
			
		||||
	{
 | 
			
		||||
		PCI_DEVICE_SUB(PCI_VENDOR_ID_LSI_LOGIC, 0x00A5,
 | 
			
		||||
		    PCI_ANY_ID, PCI_ANY_ID)
 | 
			
		||||
	},
 | 
			
		||||
	{ 0 }
 | 
			
		||||
};
 | 
			
		||||
MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table);
 | 
			
		||||
 | 
			
		||||
static struct pci_driver mpi3mr_pci_driver = {
 | 
			
		||||
	.name = MPI3MR_DRIVER_NAME,
 | 
			
		||||
	.id_table = mpi3mr_pci_id_table,
 | 
			
		||||
	.probe = mpi3mr_probe,
 | 
			
		||||
	.remove = mpi3mr_remove,
 | 
			
		||||
	.shutdown = mpi3mr_shutdown,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init mpi3mr_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int ret_val;
 | 
			
		||||
 | 
			
		||||
	pr_info("Loading %s version %s\n", MPI3MR_DRIVER_NAME,
 | 
			
		||||
	    MPI3MR_DRIVER_VERSION);
 | 
			
		||||
 | 
			
		||||
	ret_val = pci_register_driver(&mpi3mr_pci_driver);
 | 
			
		||||
 | 
			
		||||
	return ret_val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __exit mpi3mr_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	if (warn_non_secure_ctlr)
 | 
			
		||||
		pr_warn(
 | 
			
		||||
		    "Unloading %s version %s while managing a non secure controller\n",
 | 
			
		||||
		    MPI3MR_DRIVER_NAME, MPI3MR_DRIVER_VERSION);
 | 
			
		||||
	else
 | 
			
		||||
		pr_info("Unloading %s version %s\n", MPI3MR_DRIVER_NAME,
 | 
			
		||||
		    MPI3MR_DRIVER_VERSION);
 | 
			
		||||
 | 
			
		||||
	pci_unregister_driver(&mpi3mr_pci_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(mpi3mr_init);
 | 
			
		||||
module_exit(mpi3mr_exit);
 | 
			
		||||
		Loading…
	
		Reference in a new issue