static void mptsas_expander_delete()

in fusion/mptsas.c [3534:3615]


static void mptsas_expander_delete(MPT_ADAPTER *ioc,
		struct mptsas_portinfo *port_info, u8 force)
{

	struct mptsas_portinfo *parent;
	int		i;
	u64		expander_sas_address;
	struct mptsas_phyinfo *phy_info;
	struct mptsas_portinfo buffer;
	struct mptsas_portinfo_details *port_details;
	struct sas_port *port;

	if (!port_info)
		return;

	/* see if expander is still there before deleting */
	mptsas_sas_expander_pg0(ioc, &buffer,
	    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
	    MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
	    port_info->phy_info[0].identify.handle);

	if (buffer.num_phys) {
		kfree(buffer.phy_info);
		if (!force)
			return;
	}


	/*
	 * Obtain the port_info instance to the parent port
	 */
	port_details = NULL;
	expander_sas_address =
	    port_info->phy_info[0].identify.sas_address;
	parent = mptsas_find_portinfo_by_handle(ioc,
	    port_info->phy_info[0].identify.handle_parent);
	mptsas_delete_expander_siblings(ioc, parent, port_info);
	if (!parent)
		goto out;

	/*
	 * Delete rphys in the parent that point
	 * to this expander.
	 */
	phy_info = parent->phy_info;
	port = NULL;
	for (i = 0; i < parent->num_phys; i++, phy_info++) {
		if (!phy_info->phy)
			continue;
		if (phy_info->attached.sas_address !=
		    expander_sas_address)
			continue;
		if (!port) {
			port = mptsas_get_port(phy_info);
			port_details = phy_info->port_details;
		}
		dev_printk(KERN_DEBUG, &phy_info->phy->dev,
		    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
		    phy_info->phy_id, phy_info->phy);
		sas_port_delete_phy(port, phy_info->phy);
	}
	if (port) {
		dev_printk(KERN_DEBUG, &port->dev,
		    MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
		    ioc->name, port->port_identifier,
		    (unsigned long long)expander_sas_address);
		sas_port_delete(port);
		mptsas_port_delete(ioc, port_details);
	}
 out:

	printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
	    "sas_addr (0x%llx)\n",  ioc->name, port_info->num_phys,
	    (unsigned long long)expander_sas_address);

	/*
	 * free link
	 */
	list_del(&port_info->list);
	kfree(port_info->phy_info);
	kfree(port_info);
}