drivers/scsi/isci/port.c

Source file repositories/reference/linux-study-clean/drivers/scsi/isci/port.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/isci/port.c
Extension
.c
Size
53842 bytes
Lines
1774
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (isci_port->active_phy_mask == 0) {
			int phy_idx = isci_port->last_active_phy;
			struct isci_phy *iphy = &ihost->phys[phy_idx];

			/* Generate the link down now to the host, since it
			 * was intercepted by the hard reset state machine when
			 * it really happened.
			 */
			isci_port_link_down(ihost, iphy, isci_port);
		}
		/* Advance the port state so that link state changes will be
		 * noticed.
		 */
		port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);

	}
	clear_bit(IPORT_RESET_PENDING, &isci_port->state);
	wake_up(&ihost->eventq);

}

/* This method will return a true value if the specified phy can be assigned to
 * this port The following is a list of phys for each port that are allowed: -
 * Port 0 - 3 2 1 0 - Port 1 -     1 - Port 2 - 3 2 - Port 3 - 3 This method
 * doesn't preclude all configurations.  It merely ensures that a phy is part
 * of the allowable set of phy identifiers for that port.  For example, one
 * could assign phy 3 to port 0 and no other phys.  Please refer to
 * sci_port_is_phy_mask_valid() for information regarding whether the
 * phy_mask for a port can be supported. bool true if this is a valid phy
 * assignment for the port false if this is not a valid phy assignment for the
 * port
 */
bool sci_port_is_valid_phy_assignment(struct isci_port *iport, u32 phy_index)
{
	struct isci_host *ihost = iport->owning_controller;
	struct sci_user_parameters *user = &ihost->user_parameters;

	/* Initialize to invalid value. */
	u32 existing_phy_index = SCI_MAX_PHYS;
	u32 index;

	if ((iport->physical_port_index == 1) && (phy_index != 1))
		return false;

	if (iport->physical_port_index == 3 && phy_index != 3)
		return false;

	if (iport->physical_port_index == 2 &&
	    (phy_index == 0 || phy_index == 1))
		return false;

	for (index = 0; index < SCI_MAX_PHYS; index++)
		if (iport->phy_table[index] && index != phy_index)
			existing_phy_index = index;

	/* Ensure that all of the phys in the port are capable of
	 * operating at the same maximum link rate.
	 */
	if (existing_phy_index < SCI_MAX_PHYS &&
	    user->phys[phy_index].max_speed_generation !=
	    user->phys[existing_phy_index].max_speed_generation)
		return false;

	return true;
}

/**
 * sci_port_is_phy_mask_valid()
 * @iport: This is the port object for which to determine if the phy mask
 *    can be supported.
 * @phy_mask: Phy mask belonging to this port
 *
 * This method will return a true value if the port's phy mask can be supported
 * by the SCU. The following is a list of valid PHY mask configurations for
 * each port: - Port 0 - [[3  2] 1] 0 - Port 1 -        [1] - Port 2 - [[3] 2]
 * - Port 3 -  [3] This method returns a boolean indication specifying if the
 * phy mask can be supported. true if this is a valid phy assignment for the
 * port false if this is not a valid phy assignment for the port
 */
static bool sci_port_is_phy_mask_valid(
	struct isci_port *iport,
	u32 phy_mask)
{
	if (iport->physical_port_index == 0) {
		if (((phy_mask & 0x0F) == 0x0F)
		    || ((phy_mask & 0x03) == 0x03)
		    || ((phy_mask & 0x01) == 0x01)
		    || (phy_mask == 0))
			return true;
	} else if (iport->physical_port_index == 1) {

Annotation

Implementation Notes