Re: [PATCH 14/15] mpi3mr: Refresh sas ports during soft reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On Jul 29, 2022, at 6:16 AM, Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx> wrote:
> 
> - Update the Host's sas ports if there is change in port id
> or phys. If the port id is changed then the driver updates
> the same. If some phys are enabled/disabled during reset then
> driver updates the same in STL.
> 
> - Check for the responding expander devices and update the
> device handle if it got changed. Register the expander with
> STL if it got added during reset and unregister the
> expander device if it got removed during reset.
> 
> Signed-off-by: Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx>
> ---
> drivers/scsi/mpi3mr/mpi3mr.h           |  11 +
> drivers/scsi/mpi3mr/mpi3mr_fw.c        |  10 +-
> drivers/scsi/mpi3mr/mpi3mr_os.c        |  50 ++++
> drivers/scsi/mpi3mr/mpi3mr_transport.c | 351 +++++++++++++++++++++++++
> 4 files changed, 421 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
> index d203167..0f47b45 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr.h
> +++ b/drivers/scsi/mpi3mr/mpi3mr.h
> @@ -482,6 +482,9 @@ struct mpi3mr_hba_port {
>  * struct mpi3mr_sas_port - Internal SAS port information
>  * @port_list: List of ports belonging to a SAS node
>  * @num_phys: Number of phys associated with port
> + * @marked_responding: used while refresing the sas ports
> + * @lowest_phy: lowest phy ID of current sas port
> + * @phy_mask: phy_mask of current sas port
>  * @hba_port: HBA port entry
>  * @remote_identify: Attached device identification
>  * @rphy: SAS transport layer rphy object
> @@ -491,6 +494,9 @@ struct mpi3mr_hba_port {
> struct mpi3mr_sas_port {
> 	struct list_head port_list;
> 	u8 num_phys;
> +	u8 marked_responding;
> +	int lowest_phy;
> +	u32 phy_mask;
> 	struct mpi3mr_hba_port *hba_port;
> 	struct sas_identify remote_identify;
> 	struct sas_rphy *rphy;
> @@ -939,6 +945,7 @@ struct scmd_priv {
>  * @scan_started: Async scan started
>  * @scan_failed: Asycn scan failed
>  * @stop_drv_processing: Stop all command processing
> + * @device_refresh_on: Don't process the events until devices are refreshed
>  * @max_host_ios: Maximum host I/O count
>  * @chain_buf_count: Chain buffer count
>  * @chain_buf_pool: Chain buffer pool
> @@ -1107,6 +1114,7 @@ struct mpi3mr_ioc {
> 	u8 scan_started;
> 	u16 scan_failed;
> 	u8 stop_drv_processing;
> +	u8 device_refresh_on;
> 
> 	u16 max_host_ios;
> 	spinlock_t tgtdev_lock;
> @@ -1378,4 +1386,7 @@ struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
> 	struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy);
> void mpi3mr_print_device_event_notice(struct mpi3mr_ioc *mrioc,
> 	bool device_add);
> +void mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc);
> +void mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc);
> +void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc);
> #endif /*MPI3MR_H_INCLUDED*/
> diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
> index 59ef373..dfb7570 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
> +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
> @@ -3977,6 +3977,11 @@ retry_init:
> 		goto out_failed;
> 	}
> 
> +	if (!is_resume) {
> +		mrioc->device_refresh_on = 1;
> +		mpi3mr_add_event_wait_for_device_refresh(mrioc);
> +	}
> +
> 	ioc_info(mrioc, "sending port enable\n");
> 	retval = mpi3mr_issue_port_enable(mrioc, 0);
> 	if (retval) {
> @@ -4733,6 +4738,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
> 	ioc_info(mrioc, "controller reset is triggered by %s\n",
> 	    mpi3mr_reset_rc_name(reset_reason));
> 
> +	mrioc->device_refresh_on = 0;
> 	mrioc->reset_in_progress = 1;
> 	mrioc->stop_bsgs = 1;
> 	mrioc->prev_reset_result = -1;
> @@ -4814,7 +4820,8 @@ out:
> 			mpi3mr_pel_wait_post(mrioc, &mrioc->pel_cmds);
> 		}
> 
> -		mpi3mr_rfresh_tgtdevs(mrioc);
> +		mrioc->device_refresh_on = 0;
> +
> 		mrioc->ts_update_counter = 0;
> 		spin_lock_irqsave(&mrioc->watchdog_lock, flags);
> 		if (mrioc->watchdog_work_q)
> @@ -4828,6 +4835,7 @@ out:
> 	} else {
> 		mpi3mr_issue_reset(mrioc,
> 		    MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
> +		mrioc->device_refresh_on = 0;
> 		mrioc->unrecoverable = 1;
> 		mrioc->reset_in_progress = 0;
> 		retval = -1;
> diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
> index 139c164..d4f37b1 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr_os.c
> +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
> @@ -40,6 +40,8 @@ static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
> 
> #define MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION	(0xFFFF)
> 
> +#define MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH	(0xFFFE)
> +
> /**
>  * mpi3mr_host_tag_for_scmd - Get host tag for a scmd
>  * @mrioc: Adapter instance reference
> @@ -1114,6 +1116,9 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
> 		    MPI3_DEVICE0_FLAGS_ATT_METHOD_VIRTUAL)) ||
> 		    (tgtdev->parent_handle == 0xFFFF))
> 			tgtdev->non_stl = 1;
> +		if (tgtdev->dev_spec.sas_sata_inf.hba_port)
> +			tgtdev->dev_spec.sas_sata_inf.hba_port->port_id =
> +			    dev_pg0->io_unit_port;
> 		break;
> 	}
> 	case MPI3_DEVICE_DEVFORM_PCIE:
> @@ -1886,6 +1891,22 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
> 		}
> 		break;
> 	}
> +	case MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH:
> +	{
> +		while (mrioc->device_refresh_on)
> +			msleep(500);
> +
> +		dprint_event_bh(mrioc,
> +		    "scan for non responding and newly added devices after soft reset started\n");
> +		if (mrioc->sas_transport_enabled) {
> +			mpi3mr_refresh_sas_ports(mrioc);
> +			mpi3mr_refresh_expanders(mrioc);
> +		}
> +		mpi3mr_rfresh_tgtdevs(mrioc);
> +		ioc_info(mrioc,
> +		    "scan for non responding and newly added devices after soft reset completed\n");
> +		break;
> +	}
> 	default:
> 		break;
> 	}
> @@ -2655,6 +2676,35 @@ static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_ioc *mrioc,
> 	}
> }
> 
> +/**
> + * mpi3mr_add_event_wait_for_device_refresh - Add Wait for Device Refresh Event
> + * @mrioc: Adapter instance reference
> + *
> + * Add driver specific event to make sure that the driver won't process the
> + * events until all the devices are refreshed during soft reset.
> + *
> + * Return: Nothing
> + */
> +void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc)
> +{
> +	struct mpi3mr_fwevt *fwevt = NULL;
> +
> +	fwevt = mpi3mr_alloc_fwevt(0);
> +	if (!fwevt) {
> +		dprint_event_th(mrioc,
> +		    "failed to schedule bottom half handler for event(0x%02x)\n",
> +		    MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH);
> +		return;
> +	}
> +	fwevt->mrioc = mrioc;
> +	fwevt->event_id = MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH;
> +	fwevt->send_ack = 0;
> +	fwevt->process_evt = 1;
> +	fwevt->evt_ctx = 0;
> +	fwevt->event_data_size = 0;
> +	mpi3mr_fwevt_add_to_list(mrioc, fwevt);
> +}
> +
> /**
>  * mpi3mr_os_handle_events - Firmware event handler
>  * @mrioc: Adapter instance reference
> diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c
> index e8a9a76..c1ca97c 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
> +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
> @@ -9,6 +9,9 @@
> 
> #include "mpi3mr.h"
> 
> +static void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
> +	struct mpi3mr_sas_node *sas_expander);
> +
> /**
>  * mpi3mr_post_transport_req - Issue transport requests and wait
>  * @mrioc: Adapter instance reference
> @@ -597,6 +600,9 @@ static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
> 
> 	list_del(&mr_sas_phy->port_siblings);
> 	mr_sas_port->num_phys--;
> +	mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
> +	if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
> +		mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
> 	sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
> 	mr_sas_phy->phy_belongs_to_port = 0;
> }
> @@ -621,6 +627,9 @@ static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
> 
> 	list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
> 	mr_sas_port->num_phys++;
> +	mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
> +	if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
> +		mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
> 	sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
> 	mr_sas_phy->phy_belongs_to_port = 1;
> }
> @@ -1356,6 +1365,7 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
> 		list_add_tail(&mr_sas_node->phy[i].port_siblings,
> 		    &mr_sas_port->phy_list);
> 		mr_sas_port->num_phys++;
> +		mr_sas_port->phy_mask |= (1 << i);
> 	}
> 
> 	if (!mr_sas_port->num_phys) {
> @@ -1364,6 +1374,8 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
> 		goto out_fail;
> 	}
> 
> +	mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
> +
> 	if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
> 		tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
> 		    mr_sas_port->remote_identify.sas_address,
> @@ -1565,6 +1577,345 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
> 	kfree(mr_sas_port);
> }
> 
> +/**
> + * struct host_port - host port details
> + * @sas_address: SAS Address of the attached device
> + * @phy_mask: phy mask of host port
> + * @handle: Device Handle of attached device
> + * @iounit_port_id: port ID
> + * @used: host port is already matched with sas port from sas_port_list
> + * @lowest_phy: lowest phy ID of host port
> + */
> +struct host_port {
> +	u64	sas_address;
> +	u32	phy_mask;
> +	u16	handle;
> +	u8	iounit_port_id;
> +	u8	used;
> +	u8	lowest_phy;
> +};
> +
> +/**
> + * mpi3mr_update_mr_sas_port - update sas port objects during reset
> + * @mrioc: Adapter instance reference
> + * @h_port: host_port object
> + * @mr_sas_port: sas_port objects which needs to be updated
> + *
> + * Update the port ID of sas port object. Also add the phys if new phys got
> + * added to current sas port and remove the phys if some phys are moved
> + * out of the current sas port.
> + *
> + * Return: Nothing.
> + */
> +static void
> +mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
> +	struct mpi3mr_sas_port *mr_sas_port)
> +{
> +	struct mpi3mr_sas_phy *mr_sas_phy;
> +	u32 phy_mask_xor, phys_to_be_added, phys_to_be_removed;
> +	int i;
> +
> +	h_port->used = 1;
> +	mr_sas_port->marked_responding = 1;
> +
> +	dev_info(&mr_sas_port->port->dev,
> +	    "sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n",
> +	    mr_sas_port->remote_identify.sas_address,
> +	    mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
> +	    h_port->iounit_port_id, h_port->phy_mask);
> +
> +	mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
> +	mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
> +
> +	/* Get the newly added phys bit map & removed phys bit map */
> +	phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
> +	phys_to_be_added = h_port->phy_mask & phy_mask_xor;
> +	phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
> +
> +	/*
> +	 * Register these new phys to current mr_sas_port's port.
> +	 * if these phys are previously registered with another port
> +	 * then delete these phys from that port first.
> +	 */
> +	for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) {
> +		mr_sas_phy = &mrioc->sas_hba.phy[i];
> +		if (mr_sas_phy->phy_belongs_to_port)
> +			mpi3mr_del_phy_from_an_existing_port(mrioc,
> +			    &mrioc->sas_hba, mr_sas_phy);
> +		mpi3mr_add_phy_to_an_existing_port(mrioc,
> +		    &mrioc->sas_hba, mr_sas_phy,
> +		    mr_sas_port->remote_identify.sas_address,
> +		    mr_sas_port->hba_port);
> +	}
> +
> +	/* Delete the phys which are not part of current mr_sas_port's port. */
> +	for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) {
> +		mr_sas_phy = &mrioc->sas_hba.phy[i];
> +		if (mr_sas_phy->phy_belongs_to_port)
> +			mpi3mr_del_phy_from_an_existing_port(mrioc,
> +			    &mrioc->sas_hba, mr_sas_phy);
> +	}
> +}
> +
> +/**
> + * mpi3mr_refresh_sas_ports - update host's sas ports during reset
> + * @mrioc: Adapter instance reference
> + *
> + * Update the host's sas ports during reset by checking whether
> + * sas ports are still intact or not. Add/remove phys if any hba
> + * phys are (moved in)/(moved out) of sas port. Also update
> + * io_unit_port if it got changed during reset.
> + *
> + * Return: Nothing.
> + */
> +void
> +mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
> +{
> +	struct host_port h_port[32];
> +	int i, j, found, host_port_count = 0, port_idx;
> +	u16 sz, attached_handle, ioc_status;
> +	struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
> +	struct mpi3_device_page0 dev_pg0;
> +	struct mpi3_device0_sas_sata_format *sasinf;
> +	struct mpi3mr_sas_port *mr_sas_port;
> +
> +	sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
> +		(mrioc->sas_hba.num_phys *
> +		 sizeof(struct mpi3_sas_io_unit0_phy_data));
> +	sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
> +	if (!sas_io_unit_pg0)
> +		return;
> +	if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
> +		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
> +		    __FILE__, __LINE__, __func__);
> +		goto out;
> +	}
> +
> +	/* Create a new expander port table */
> +	for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
> +		attached_handle = le16_to_cpu(
> +		    sas_io_unit_pg0->phy_data[i].attached_dev_handle);
> +		if (!attached_handle)
> +			continue;
> +		found = 0;
> +		for (j = 0; j < host_port_count; j++) {
> +			if (h_port[j].handle == attached_handle) {
> +				h_port[j].phy_mask |= (1 << i);
> +				found = 1;
> +				break;
> +			}
> +		}
> +		if (found)
> +			continue;
> +		if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
> +		    sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
> +		    attached_handle))) {
> +			dprint_reset(mrioc,
> +			    "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
> +			    attached_handle, __FILE__, __LINE__, __func__);
> +			continue;
> +		}
> +		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
> +			dprint_reset(mrioc,
> +			    "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
> +			    ioc_status, attached_handle,
> +			    __FILE__, __LINE__, __func__);
> +			continue;
> +		}
> +		sasinf = &dev_pg0.device_specific.sas_sata_format;
> +
> +		port_idx = host_port_count;
> +		h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
> +		h_port[port_idx].handle = attached_handle;
> +		h_port[port_idx].phy_mask = (1 << i);
> +		h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
> +		h_port[port_idx].lowest_phy = sasinf->phy_num;
> +		h_port[port_idx].used = 0;
> +		host_port_count++;
> +	}
> +
> +	if (!host_port_count)
> +		goto out;
> +
> +	if (mrioc->logging_level & MPI3_DEBUG_RESET) {
> +		ioc_info(mrioc, "Host port details before reset\n");
> +		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
> +		    port_list) {
> +			ioc_info(mrioc,
> +			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
> +			    mr_sas_port->hba_port->port_id,
> +			    mr_sas_port->remote_identify.sas_address,
> +			    mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
> +		}
> +		mr_sas_port = NULL;
> +		ioc_info(mrioc, "Host port details after reset\n");
> +		for (i = 0; i < host_port_count; i++) {
> +			ioc_info(mrioc,
> +			    "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
> +			    h_port[i].iounit_port_id, h_port[i].sas_address,
> +			    h_port[i].phy_mask, h_port[i].lowest_phy);
> +		}
> +	}
> +
> +	/* mark all host sas port entries as dirty */
> +	list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
> +	    port_list) {
> +		mr_sas_port->marked_responding = 0;
> +		mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
> +	}
> +
> +	/* First check for matching lowest phy */
> +	for (i = 0; i < host_port_count; i++) {
> +		mr_sas_port = NULL;
> +		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
> +		    port_list) {
> +			if (mr_sas_port->marked_responding)
> +				continue;
> +			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
> +				continue;
> +			if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
> +				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
> +				break;
> +			}
> +		}
> +	}
> +
> +	/* In case if lowest phy is got enabled or disabled during reset */
> +	for (i = 0; i < host_port_count; i++) {
> +		if (h_port[i].used)
> +			continue;
> +		mr_sas_port = NULL;
> +		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
> +		    port_list) {
> +			if (mr_sas_port->marked_responding)
> +				continue;
> +			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
> +				continue;
> +			if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
> +				mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
> +				break;
> +			}
> +		}
> +	}
> +
> +	/* In case if expander cable is removed & connected to another HBA port during reset */
> +	for (i = 0; i < host_port_count; i++) {
> +		if (h_port[i].used)
> +			continue;
> +		mr_sas_port = NULL;
> +		list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
> +		    port_list) {
> +			if (mr_sas_port->marked_responding)
> +				continue;
> +			if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
> +				continue;
> +			mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
> +			break;
> +		}
> +	}
> +out:
> +	kfree(sas_io_unit_pg0);
> +}
> +
> +/**
> + * mpi3mr_refresh_expanders - Refresh expander device exposure
> + * @mrioc: Adapter instance reference
> + *
> + * This is executed post controller reset to identify any
> + * missing expander devices during reset and remove from the upper layers
> + * or expose any newly detected expander device to the upper layers.
> + *
> + * Return: Nothing.
> + */
> +void
> +mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
> +{
> +	struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
> +	struct mpi3_sas_expander_page0 expander_pg0;
> +	u16 ioc_status, handle;
> +	u64 sas_address;
> +	int i;
> +	unsigned long flags;
> +	struct mpi3mr_hba_port *hba_port;
> +
> +	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
> +	list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
> +		sas_expander->non_responding = 1;
> +	}
> +	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
> +
> +	sas_expander = NULL;
> +
> +	handle = 0xffff;
> +
> +	/* Search for responding expander devices and add them if they are newly got added */
> +	while (true) {
> +		if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
> +		    sizeof(struct mpi3_sas_expander_page0),
> +		    MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
> +			dprint_reset(mrioc,
> +			    "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
> +			    handle, __FILE__, __LINE__, __func__);
> +			break;
> +		}
> +
> +		if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
> +			dprint_reset(mrioc,
> +			   "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
> +			   ioc_status, handle, __FILE__, __LINE__, __func__);
> +			break;
> +		}
> +
> +		handle = le16_to_cpu(expander_pg0.dev_handle);
> +		sas_address = le64_to_cpu(expander_pg0.sas_address);
> +		hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
> +
> +		if (!hba_port) {
> +			mpi3mr_sas_host_refresh(mrioc);
> +			mpi3mr_expander_add(mrioc, handle);
> +			continue;
> +		}
> +
> +		spin_lock_irqsave(&mrioc->sas_node_lock, flags);
> +		sas_expander =
> +		    mpi3mr_expander_find_by_sas_address(mrioc,
> +		    sas_address, hba_port);
> +		spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
> +
> +		if (!sas_expander) {
> +			mpi3mr_sas_host_refresh(mrioc);
> +			mpi3mr_expander_add(mrioc, handle);
> +			continue;
> +		}
> +
> +		sas_expander->non_responding = 0;
> +		if (sas_expander->handle == handle)
> +			continue;
> +
> +		sas_expander->handle = handle;
> +		for (i = 0 ; i < sas_expander->num_phys ; i++)
> +			sas_expander->phy[i].handle = handle;
> +	}
> +
> +	/*
> +	 * Delete non responding expander devices and the corresponding
> +	 * hba_port if the non responding expander device's parent device
> +	 * is a host node.
> +	 */
> +
Remove newline here

> +	sas_expander = NULL;
> +	spin_lock_irqsave(&mrioc->sas_node_lock, flags);
> +	list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
> +	    &mrioc->sas_expander_list, list) {
> +		if (sas_expander->non_responding) {
> +			spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
> +			mpi3mr_expander_node_remove(mrioc, sas_expander);
> +			spin_lock_irqsave(&mrioc->sas_node_lock, flags);
> +		}
> +	}
> +	spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
> +}
> +
> /**
>  * mpi3mr_expander_node_add - insert an expander to the list.
>  * @mrioc: Adapter instance reference
> -- 
> 2.27.0
> 

With the small nits fixed, you can add

Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx>

--
Himanshu Madhani	Oracle Linux Engineering





[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux