Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f16b331 authored by Chad Dupuis's avatar Chad Dupuis Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Use bitmap to store loop_id's for fcports.



Store used fcport loop_id's in a bitmap so that as opposed to looping through
all fcports to find the next free loop_id, new loop_id lookup can be just be
done via bitops.

[jejb: plus fix for incorrect LOOPID_MAP_SIZE from Andrew Vasquez]
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 09543c09
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@
 * ----------------------------------------------------------------------
 * |             Level            |   Last Value Used  |     Holes	|
 * ----------------------------------------------------------------------
 * | Module Init and Probe        |       0x0122       | 0x4b,0xba,0xfa |
 * | Module Init and Probe        |       0x0123       | 0x4b,0xba,0xfa |
 * | Mailbox commands             |       0x1140       | 0x111a-0x111b  |
 * |                              |                    | 0x112c-0x112e  |
 * |                              |                    | 0x113a         |
+2 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@
#define MAX_FIBRE_DEVICES_2400	2048
#define MAX_FIBRE_DEVICES_LOOP	128
#define MAX_FIBRE_DEVICES_MAX	MAX_FIBRE_DEVICES_2400
#define LOOPID_MAP_SIZE		(ha->max_fibre_devices)
#define MAX_FIBRE_LUNS  	0xFFFF
#define	MAX_HOST_COUNT		16

@@ -2918,6 +2919,7 @@ struct qla_hw_data {
	void            *md_dump;
	uint32_t	md_dump_size;

	void		*loop_id_map;
	struct qlt_hw_data tgt;
};

+21 −60
Original line number Diff line number Diff line
@@ -3285,7 +3285,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
			 */
			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
				fcport->d_id.b24 = new_fcport->d_id.b24;
				fcport->loop_id = FC_NO_LOOP_ID;
				qla2x00_clear_loop_id(fcport);
				fcport->flags |= (FCF_FABRIC_DEVICE |
				    FCF_LOGIN_NEEDED);
				break;
@@ -3306,7 +3306,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
				ha->isp_ops->fabric_logout(vha, fcport->loop_id,
				    fcport->d_id.b.domain, fcport->d_id.b.area,
				    fcport->d_id.b.al_pa);
				fcport->loop_id = FC_NO_LOOP_ID;
				qla2x00_clear_loop_id(fcport);
			}

			break;
@@ -3352,71 +3352,32 @@ int
qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
{
	int	rval;
	int	found;
	fc_port_t *fcport;
	uint16_t first_loop_id;
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *vp;
	struct scsi_qla_host *tvp;
	unsigned long flags = 0;

	rval = QLA_SUCCESS;

	/* Save starting loop ID. */
	first_loop_id = dev->loop_id;

	for (;;) {
		/* Skip loop ID if already used by adapter. */
		if (dev->loop_id == vha->loop_id)
			dev->loop_id++;

		/* Skip reserved loop IDs. */
		while (qla2x00_is_reserved_id(vha, dev->loop_id))
			dev->loop_id++;

		/* Reset loop ID if passed the end. */
		if (dev->loop_id > ha->max_loop_id) {
			/* first loop ID. */
			dev->loop_id = ha->min_external_loopid;
		}
	spin_lock_irqsave(&ha->vport_slock, flags);

		/* Check for loop ID being already in use. */
		found = 0;
		fcport = NULL;
	dev->loop_id = find_first_zero_bit(ha->loop_id_map,
	    LOOPID_MAP_SIZE);
	if (dev->loop_id >= LOOPID_MAP_SIZE ||
	    qla2x00_is_reserved_id(vha, dev->loop_id)) {
		dev->loop_id = FC_NO_LOOP_ID;
		rval = QLA_FUNCTION_FAILED;
	} else
		set_bit(dev->loop_id, ha->loop_id_map);

		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
			list_for_each_entry(fcport, &vp->vp_fcports, list) {
				if (fcport->loop_id == dev->loop_id &&
								fcport != dev) {
					/* ID possibly in use */
					found++;
					break;
				}
			}
			if (found)
				break;
		}
	spin_unlock_irqrestore(&ha->vport_slock, flags);

		/* If not in use then it is free to use. */
		if (!found) {
	if (rval == QLA_SUCCESS)
		ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
		    "Assigning new loopid=%x, portid=%x.\n",
		    dev->loop_id, dev->d_id.b24);
			break;
		}

		/* ID in use. Try next value. */
		dev->loop_id++;

		/* If wrap around. No free ID to use. */
		if (dev->loop_id == first_loop_id) {
			dev->loop_id = FC_NO_LOOP_ID;
			rval = QLA_FUNCTION_FAILED;
			break;
		}
	}
	else
		ql_log(ql_log_warn, dev->vha, 0x2087,
		    "No loop_id's available, portid=%x.\n",
		    dev->d_id.b24);

	return (rval);
}
@@ -3616,7 +3577,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
			ha->isp_ops->fabric_logout(vha, fcport->loop_id,
			    fcport->d_id.b.domain, fcport->d_id.b.area,
			    fcport->d_id.b.al_pa);
			fcport->loop_id = FC_NO_LOOP_ID;
			qla2x00_clear_loop_id(fcport);
			fcport->login_retry = 0;

			rval = 3;
+26 −0
Original line number Diff line number Diff line
@@ -57,6 +57,20 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
       return fcp;
}

static inline void
qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
{
	int i;

	if (IS_FWI2_CAPABLE(ha))
		return;

	for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
		set_bit(i, ha->loop_id_map);
	set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
	set_bit(BROADCAST, ha->loop_id_map);
}

static inline int
qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
{
@@ -68,6 +82,18 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
	    loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
}

static inline void
qla2x00_clear_loop_id(fc_port_t *fcport) {
	struct qla_hw_data *ha = fcport->vha->hw;

	if (fcport->loop_id == FC_NO_LOOP_ID ||
	    qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
		return;

	clear_bit(fcport->loop_id, ha->loop_id_map);
	fcport->loop_id = FC_NO_LOOP_ID;
}

static inline void
qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
{
+15 −1
Original line number Diff line number Diff line
@@ -2872,6 +2872,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)

	list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
		list_del(&fcport->list);
		qla2x00_clear_loop_id(fcport);
		kfree(fcport);
		fcport = NULL;
	}
@@ -3169,6 +3170,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
	}

	INIT_LIST_HEAD(&ha->vp_list);

	/* Allocate memory for our loop_id bitmap */
	ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
	    GFP_KERNEL);
	if (!ha->loop_id_map)
		goto fail_async_pd;
	else {
		qla2x00_set_reserved_loop_ids(ha);
		ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
		    "loop_id_map=%p. \n", ha->loop_id_map);
	}

	return 1;

fail_async_pd:
@@ -3352,6 +3365,7 @@ qla2x00_mem_free(struct qla_hw_data *ha)
	kfree(ha->nvram);
	kfree(ha->npiv_info);
	kfree(ha->swl);
	kfree(ha->loop_id_map);

	ha->srb_mempool = NULL;
	ha->ctx_mempool = NULL;
@@ -3687,7 +3701,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
			}

			if (fcport->login_retry == 0 && status != QLA_SUCCESS)
				fcport->loop_id = FC_NO_LOOP_ID;
				qla2x00_clear_loop_id(fcport);
		}
		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
			break;