Driving Structure of sas Controller--Based on 3.10.0-693.25.4

Keywords: Big Data network

The Department test environment has recently released a core, which is downtime in the mpt3sas module. I have never seen this module before. How to check the core? I haven't seen it before, just see it now. This module is the driver of the SAS controller. In previous IO stack research, only the general block layer has been known, and SCSI has not touched down. It is also a good opportunity to understand the bug below the IO stack scsi.

As can be seen from the config description, mpt3sas is driven by SAS controller. The special point is that it is based on Fusion-MPT architecture.

config SCSI_MPT3SAS
	tristate "LSI MPT Fusion SAS 3.0 Device Driver"
	depends on PCI && SCSI
	select SCSI_SAS_ATTRS
	select RAID_ATTRS
	---help---
	This driver supports PCI-Express SAS 12Gb/s Host Adapters.

What is Fusion-MPT? Look first at a description on the network

Fusion-MPT technology, developed by LSI Logic, aims to provide customers with easier solutions to SCSI and Fibre Channel.
Fusion-MPT technology mainly includes Fusion-MPT firmware, SAS, U320 SCSI, Fibre Channel hard core, and operating system level driver.
Fusion-MPT architecture uses unified firmware and drivers to support all I/O controllers based on Fusion-MPT technology.
Fusion-MPT architecture can be divided into two parts: operating system layer and hardware layer. From the perspective of driver design, it can be further divided into three functional levels: driver, firmware and hardware.
Fusion-MPT builds a unique firmware layer on the hardware layer. Different firmware provides SCSI or FC support for upper driver, and advanced integrated RAID functions. Firmware layer effectively isolates drivers from hardware and provides a unified MPI (Message Passing Interface) interface for upper drivers, so that the same driver can be applied to different underlying hardware systems, which is helpful to accelerate application development. The driver layer provides functional interface to the upper operating system, accesses the firmware layer through MPI, realizes the hardware access of the operating system, and implements the frame encapsulation and disassembly according to the communication protocol. MPI provides a messaging transport architecture, which defines the interface between host and LSI Fusion-MPT chipset.

The above description is very clear. Generally speaking, Fusion-MPT is a good thing. It provides a firmware on the hardware. The upper driver can access the firmware with MPI interface, while the firmware can access different hardware. This simplifies the access of the operating system to different hardware. The driver of mpt3sas is MPT firmware. The following is SAS interface. Let's see the position of this device in the system. LSISAS 1068E is a device using mpt3sas.

According to the data, the structure of mpt3sas driver is simply analyzed.

static int __init
_mpt3sas_init(void)
{
	int error;

#ifdef MPT2SAS_SCSI
	pr_info("%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
					MPT2SAS_DRIVER_VERSION);
#else
	pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
					MPT3SAS_DRIVER_VERSION);
#endif /* MPT2SAS_SCSI */

	mpt3sas_transport_template =	//Setting template
	    sas_attach_transport(&mpt3sas_transport_functions);
	if (!mpt3sas_transport_template)
		return -ENODEV;

#ifdef MPT2SAS_SCSI
	mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions);
	if (!mpt2sas_raid_template) {	
		sas_release_transport(mpt3sas_transport_template);
		return -ENODEV;
	}
#else
	mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
	if (!mpt3sas_raid_template) {	//Setting template
		sas_release_transport(mpt3sas_transport_template);
		return -ENODEV;
	}
#endif /* MPT2SAS_SCSI */

	error = scsih_init();	//Register a series of callback functions
	if (error) {
		scsih_exit();
		return error;
	}


#ifdef MPT2SAS_SCSI
	mpt3sas_ctl_init(1);
#else
	mpt3sas_ctl_init(2);	//Register / dev/mpt3clt
#endif /* MPT2SAS_SCSI */

	error = pci_register_driver(&mpt3sas_driver);	//Register a pci device
	if (error)
		scsih_exit();

	return error;
}

static int
scsih_init(void)
{
	mpt2_ids = 0;
	mpt3_ids = 0;

	mpt3sas_base_initialize_callback_handler();

	 /* queuecommand callback hander */
	scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);

	/* task management callback handler */
	tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);

	/* base internal commands callback handler */
	base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
	port_enable_cb_idx = mpt3sas_base_register_callback_handler(
	    mpt3sas_port_enable_done);

	/* transport internal commands callback handler */
	transport_cb_idx = mpt3sas_base_register_callback_handler(
	    mpt3sas_transport_done);

	/* scsih internal commands callback handler */
	scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);

	/* configuration page API internal commands callback handler */
	config_cb_idx = mpt3sas_base_register_callback_handler(
	    mpt3sas_config_done);

	/* ctl module callback handler */
	ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);

	tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
	    _scsih_tm_tr_complete);

	tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
	    _scsih_tm_volume_tr_complete);

	tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
	    _scsih_sas_control_complete);

	return 0;
}

We do not analyze in detail what mpt3sas_transport_template, mpt3sas_raid_template and scsih_init have done, because our purpose is to understand the structure of mpt3sas driver. We have a general framework, and we need to analyze it carefully when we have in-depth contacts. We focus on mpt3sas registered pci devices.
The registration of PCI is to mount the PCI driver to the driver chain of its bus, scan the PCI device at the same time, mount the device that it can drive to the device list on the driver and call the probe function. The pci probe function of mpt3sas is _scsih_probe

static int
_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct MPT3SAS_ADAPTER *ioc; //Create and initialize MPT3SAS_ADAPTER 
	...
		/* Use mpt3sas driver host template for SAS 3.0 HBA's */
		//Apply for a scsi host
		shost = scsi_host_alloc(&mpt3sas_driver_template,
		  sizeof(struct MPT3SAS_ADAPTER));
		if (!shost)
			return -ENODEV;
		ioc = shost_priv(shost);
	...
	ioc->is_driver_loading = 1;
	if ((mpt3sas_base_attach(ioc))) {	// Initialize the controller and allocate resources
		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
		    ioc->name, __FILE__, __LINE__, __func__);
		rv = -ENODEV;
		goto out_attach_fail;
	}
	...
	rv = scsi_add_host(shost, &pdev->dev);	//Add to scsi middle level
	if (rv) {
		pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
		    ioc->name, __FILE__, __LINE__, __func__);
		goto out_add_shost_fail;
	}
	...
	scsi_scan_host(shost);	//Scanning all scsi buses
	return 0;
	...
}

Controller driver is such a routine, first allocating resources to initialize the controller, then creating a scsi host to add to the system, and then scanning the scsi bus device to create a target to connect to the system. At this time, the IO stack sees the scsi device, and then up is the general block layer. IO to the scsi layer, how to communicate with the following hardware is implemented in this driver, but we do not need to care so much.

Supplementary information from the Internet

Scsi host, Scsi target, Scsi device and other data structures are defined in SCSI middle level. Scsi
Host describes a SCSI bus controller. In many practical systems, scsi host is a PCI bus-based HBA or a SCSI.
Controller chip. Each Scsi host can have multiple channels, and one channel actually extends a scsi bus. each
channel can connect multiple scsi nodes, and the number of connections is related to the carrying capacity of scsi bus. Scsi target on scsi bus
scsi node is abstracted. Each Scsi target may have multiple lun s, i.e. multiple Scsi devices. Scsi device
It is used to describe a specific function unit of scsi, which is addressed by channel, id and lun in scsi host. Notice that Scsi
The function of device is to expand the ability of Scsi target to describe devices without representing any entity attributes. In a real environment, Scsi target
For a physical disk or Raid volume, Scsi device corresponds to a logical unit lun.
scsi middle level

This is the general structure of mpt3sas, which is driven by the controller.
The downtime problem I encountered was that the controller resources were released during the processing of / dev/mpt3sas ioctl, resulting in illegal memory access, which is usually caused by concurrency, and https://patchwork.kernel.org/patch/10196101/ This patch describes a very similar problem, but not the same one. The specific reasons are still under analysis.

Reference resources:

  1. mptsas-driven reading notes

Posted by nando on Sat, 19 Jan 2019 12:24:13 -0800