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

Commit 5a54b1d5 authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[SCSI] bfa: Added support for flash configuration



- Added flash sub-module.
- Implemented the interface to read/erase/update flash partition.

Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 51e569aa
Loading
Loading
Loading
Loading
+0 −22
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
struct bfa_s;

typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);

/*
 * Interrupt message handlers
@@ -76,16 +75,6 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
	(__index) &= ((__size) - 1);			\
} while (0)

/*
 * Queue element to wait for room in request queue. FIFO order is
 * maintained when fullfilling requests.
 */
struct bfa_reqq_wait_s {
	struct list_head	qe;
	void		(*qresume) (void *cbarg);
	void		*cbarg;
};

/*
 * Circular queue usage assignments
 */
@@ -129,17 +118,6 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),

#define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)


/*
 * Generic BFA callback element.
 */
struct bfa_cb_qe_s {
	struct list_head         qe;
	bfa_cb_cbfn_t  cbfn;
	bfa_boolean_t   once;
	void           *cbarg;
};

#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
		(__hcb_qe)->cbfn  = (__cbfn);      \
		(__hcb_qe)->cbarg = (__cbarg);      \
+15 −0
Original line number Diff line number Diff line
@@ -132,6 +132,17 @@ bfa_com_sfp_attach(struct bfa_s *bfa)
	bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp);
}

static void
bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
{
	struct bfa_flash_s	*flash = BFA_FLASH(bfa);
	struct bfa_mem_dma_s	*flash_dma = BFA_MEM_FLASH_DMA(bfa);

	bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg);
	bfa_flash_memclaim(flash, flash_dma->kva_curp,
			   flash_dma->dma_curp, mincfg);
}

/*
 * BFA IOC FC related definitions
 */
@@ -1371,6 +1382,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
	struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
	struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
	struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
	struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);

	WARN_ON((cfg == NULL) || (meminfo == NULL));

@@ -1390,6 +1402,8 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
	bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo());
	bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo());
	bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo());
	bfa_mem_dma_setup(meminfo, flash_dma,
			  bfa_flash_meminfo(cfg->drvcfg.min_cfg));
}

/*
@@ -1459,6 +1473,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
	bfa_com_ablk_attach(bfa);
	bfa_com_cee_attach(bfa);
	bfa_com_sfp_attach(bfa);
	bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
}

/*
+81 −25
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ enum bfa_status {
	BFA_STATUS_SFP_UNSUPP	= 10,	/*  Unsupported SFP - Replace SFP */
	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */
	BFA_STATUS_DEVBUSY	= 13,	/*  Device busy - Retry operation */
	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */
	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
@@ -384,31 +385,39 @@ struct bfa_ioc_attr_s {
 * All numerical fields are in big-endian format.
 */
struct bfa_mfg_block_s {
	u8		version;	/*  manufacturing block version */
	u8		mfg_sig[3];	/*  characters 'M', 'F', 'G' */
	u16	mfgsize;	/*  mfg block size */
	u16	u16_chksum;	/*  old u16 checksum */
	u8	version;    /*!< manufacturing block version */
	u8     mfg_sig[3]; /*!< characters 'M', 'F', 'G' */
	u16    mfgsize;    /*!< mfg block size */
	u16    u16_chksum; /*!< old u16 checksum */
	char        brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
	char        brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
	u8		mfg_day;	/*  manufacturing day */
	u8		mfg_month;	/*  manufacturing month */
	u16	mfg_year;	/*  manufacturing year */
	wwn_t		mfg_wwn;	/*  wwn base for this adapter */
	u8		num_wwn;	/*  number of wwns assigned */
	u8		mfg_speeds;	/*  speeds allowed for this adapter */
	u8     mfg_day;    /*!< manufacturing day */
	u8     mfg_month;  /*!< manufacturing month */
	u16    mfg_year;   /*!< manufacturing year */
	wwn_t       mfg_wwn;    /*!< wwn base for this adapter */
	u8     num_wwn;    /*!< number of wwns assigned */
	u8     mfg_speeds; /*!< speeds allowed for this adapter */
	u8     rsv[2];
	char    supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
	char    supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
	char
		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
	char
		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
	mac_t		mfg_mac;	/*  mac address */
	u8		num_mac;	/*  number of mac addresses */
	char    supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
	char    supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
	mac_t       mfg_mac;    /*!< base mac address */
	u8     num_mac;    /*!< number of mac addresses */
	u8     rsv2;
	u32	mfg_type;	/*  card type */
	u8		rsv3[108];
	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */
	u32    card_type;  /*!< card type          */
	char        cap_nic;    /*!< capability nic     */
	char        cap_cna;    /*!< capability cna     */
	char        cap_hba;    /*!< capability hba     */
	char        cap_fc16g;  /*!< capability fc 16g      */
	char        cap_sriov;  /*!< capability sriov       */
	char        cap_mezz;   /*!< capability mezz        */
	u8     rsv3;
	u8     mfg_nports; /*!< number of ports        */
	char        media[8];   /*!< xfi/xaui           */
	char        initial_mode[8]; /*!< initial mode: hba/cna/nic */
	u8     rsv4[84];
	u8     md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
};

#pragma pack()
@@ -825,6 +834,53 @@ struct sfp_xcvr_s {
	union sfp_xcvr_fc3_code_u	fc3;
};

/*
 *	Flash module specific
 */
#define BFA_FLASH_PART_ENTRY_SIZE	32	/* partition entry size */
#define BFA_FLASH_PART_MAX		32	/* maximal # of partitions */

enum bfa_flash_part_type {
	BFA_FLASH_PART_OPTROM   = 1,    /* option rom partition */
	BFA_FLASH_PART_FWIMG    = 2,    /* firmware image partition */
	BFA_FLASH_PART_FWCFG    = 3,    /* firmware tuneable config */
	BFA_FLASH_PART_DRV      = 4,    /* IOC driver config */
	BFA_FLASH_PART_BOOT     = 5,    /* boot config */
	BFA_FLASH_PART_ASIC     = 6,    /* asic bootstrap configuration */
	BFA_FLASH_PART_MFG      = 7,    /* manufacturing block partition */
	BFA_FLASH_PART_OPTROM2  = 8,    /* 2nd option rom partition */
	BFA_FLASH_PART_VPD      = 9,    /* vpd data of OEM info */
	BFA_FLASH_PART_PBC      = 10,   /* pre-boot config */
	BFA_FLASH_PART_BOOTOVL  = 11,   /* boot overlay partition */
	BFA_FLASH_PART_LOG      = 12,   /* firmware log partition */
	BFA_FLASH_PART_PXECFG   = 13,   /* pxe boot config partition */
	BFA_FLASH_PART_PXEOVL   = 14,   /* pxe boot overlay partition */
	BFA_FLASH_PART_PORTCFG  = 15,   /* port cfg partition */
	BFA_FLASH_PART_ASICBK   = 16,   /* asic backup partition */
};

/*
 * flash partition attributes
 */
struct bfa_flash_part_attr_s {
	u32	part_type;      /* partition type */
	u32	part_instance;  /* partition instance */
	u32	part_off;       /* partition offset */
	u32	part_size;      /* partition size */
	u32	part_len;       /* partition content length */
	u32	part_status;    /* partition status */
	char	rsv[BFA_FLASH_PART_ENTRY_SIZE - 24];
};

/*
 * flash attributes
 */
struct bfa_flash_attr_s {
	u32	status; /* flash overall status */
	u32	npart;  /* num of partitions */
	struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX];
};

#pragma pack()

#endif /* __BFA_DEFS_H__ */
+494 −0
Original line number Diff line number Diff line
@@ -3821,3 +3821,497 @@ bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,

	return bfa_sfp_speed_valid(sfp, portspeed);
}

/*
 *	Flash module specific
 */

/*
 * FLASH DMA buffer should be big enough to hold both MFG block and
 * asic block(64k) at the same time and also should be 2k aligned to
 * avoid write segement to cross sector boundary.
 */
#define BFA_FLASH_SEG_SZ	2048
#define BFA_FLASH_DMA_BUF_SZ	\
	BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)

static void
bfa_flash_cb(struct bfa_flash_s *flash)
{
	flash->op_busy = 0;
	if (flash->cbfn)
		flash->cbfn(flash->cbarg, flash->status);
}

static void
bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)
{
	struct bfa_flash_s	*flash = cbarg;

	bfa_trc(flash, event);
	switch (event) {
	case BFA_IOC_E_DISABLED:
	case BFA_IOC_E_FAILED:
		if (flash->op_busy) {
			flash->status = BFA_STATUS_IOC_FAILURE;
			flash->cbfn(flash->cbarg, flash->status);
			flash->op_busy = 0;
		}
		break;

	default:
		break;
	}
}

/*
 * Send flash attribute query request.
 *
 * @param[in] cbarg - callback argument
 */
static void
bfa_flash_query_send(void *cbarg)
{
	struct bfa_flash_s *flash = cbarg;
	struct bfi_flash_query_req_s *msg =
			(struct bfi_flash_query_req_s *) flash->mb.msg;

	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
		bfa_ioc_portid(flash->ioc));
	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),
		flash->dbuf_pa);
	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
}

/*
 * Send flash write request.
 *
 * @param[in] cbarg - callback argument
 */
static void
bfa_flash_write_send(struct bfa_flash_s *flash)
{
	struct bfi_flash_write_req_s *msg =
			(struct bfi_flash_write_req_s *) flash->mb.msg;
	u32	len;

	msg->type = be32_to_cpu(flash->type);
	msg->instance = flash->instance;
	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
		flash->residue : BFA_FLASH_DMA_BUF_SZ;
	msg->length = be32_to_cpu(len);

	/* indicate if it's the last msg of the whole write operation */
	msg->last = (len == flash->residue) ? 1 : 0;

	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
			bfa_ioc_portid(flash->ioc));
	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);

	flash->residue -= len;
	flash->offset += len;
}

/*
 * Send flash read request.
 *
 * @param[in] cbarg - callback argument
 */
static void
bfa_flash_read_send(void *cbarg)
{
	struct bfa_flash_s *flash = cbarg;
	struct bfi_flash_read_req_s *msg =
			(struct bfi_flash_read_req_s *) flash->mb.msg;
	u32	len;

	msg->type = be32_to_cpu(flash->type);
	msg->instance = flash->instance;
	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
			flash->residue : BFA_FLASH_DMA_BUF_SZ;
	msg->length = be32_to_cpu(len);
	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
		bfa_ioc_portid(flash->ioc));
	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
}

/*
 * Send flash erase request.
 *
 * @param[in] cbarg - callback argument
 */
static void
bfa_flash_erase_send(void *cbarg)
{
	struct bfa_flash_s *flash = cbarg;
	struct bfi_flash_erase_req_s *msg =
			(struct bfi_flash_erase_req_s *) flash->mb.msg;

	msg->type = be32_to_cpu(flash->type);
	msg->instance = flash->instance;
	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,
			bfa_ioc_portid(flash->ioc));
	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
}

/*
 * Process flash response messages upon receiving interrupts.
 *
 * @param[in] flasharg - flash structure
 * @param[in] msg - message structure
 */
static void
bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
{
	struct bfa_flash_s *flash = flasharg;
	u32	status;

	union {
		struct bfi_flash_query_rsp_s *query;
		struct bfi_flash_erase_rsp_s *erase;
		struct bfi_flash_write_rsp_s *write;
		struct bfi_flash_read_rsp_s *read;
		struct bfi_mbmsg_s   *msg;
	} m;

	m.msg = msg;
	bfa_trc(flash, msg->mh.msg_id);

	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {
		/* receiving response after ioc failure */
		bfa_trc(flash, 0x9999);
		return;
	}

	switch (msg->mh.msg_id) {
	case BFI_FLASH_I2H_QUERY_RSP:
		status = be32_to_cpu(m.query->status);
		bfa_trc(flash, status);
		if (status == BFA_STATUS_OK) {
			u32	i;
			struct bfa_flash_attr_s *attr, *f;

			attr = (struct bfa_flash_attr_s *) flash->ubuf;
			f = (struct bfa_flash_attr_s *) flash->dbuf_kva;
			attr->status = be32_to_cpu(f->status);
			attr->npart = be32_to_cpu(f->npart);
			bfa_trc(flash, attr->status);
			bfa_trc(flash, attr->npart);
			for (i = 0; i < attr->npart; i++) {
				attr->part[i].part_type =
					be32_to_cpu(f->part[i].part_type);
				attr->part[i].part_instance =
					be32_to_cpu(f->part[i].part_instance);
				attr->part[i].part_off =
					be32_to_cpu(f->part[i].part_off);
				attr->part[i].part_size =
					be32_to_cpu(f->part[i].part_size);
				attr->part[i].part_len =
					be32_to_cpu(f->part[i].part_len);
				attr->part[i].part_status =
					be32_to_cpu(f->part[i].part_status);
			}
		}
		flash->status = status;
		bfa_flash_cb(flash);
		break;
	case BFI_FLASH_I2H_ERASE_RSP:
		status = be32_to_cpu(m.erase->status);
		bfa_trc(flash, status);
		flash->status = status;
		bfa_flash_cb(flash);
		break;
	case BFI_FLASH_I2H_WRITE_RSP:
		status = be32_to_cpu(m.write->status);
		bfa_trc(flash, status);
		if (status != BFA_STATUS_OK || flash->residue == 0) {
			flash->status = status;
			bfa_flash_cb(flash);
		} else {
			bfa_trc(flash, flash->offset);
			bfa_flash_write_send(flash);
		}
		break;
	case BFI_FLASH_I2H_READ_RSP:
		status = be32_to_cpu(m.read->status);
		bfa_trc(flash, status);
		if (status != BFA_STATUS_OK) {
			flash->status = status;
			bfa_flash_cb(flash);
		} else {
			u32 len = be32_to_cpu(m.read->length);
			bfa_trc(flash, flash->offset);
			bfa_trc(flash, len);
			memcpy(flash->ubuf + flash->offset,
				flash->dbuf_kva, len);
			flash->residue -= len;
			flash->offset += len;
			if (flash->residue == 0) {
				flash->status = status;
				bfa_flash_cb(flash);
			} else
				bfa_flash_read_send(flash);
		}
		break;
	case BFI_FLASH_I2H_BOOT_VER_RSP:
	case BFI_FLASH_I2H_EVENT:
		bfa_trc(flash, msg->mh.msg_id);
		break;

	default:
		WARN_ON(1);
	}
}

/*
 * Flash memory info API.
 *
 * @param[in] mincfg - minimal cfg variable
 */
u32
bfa_flash_meminfo(bfa_boolean_t mincfg)
{
	/* min driver doesn't need flash */
	if (mincfg)
		return 0;
	return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
}

/*
 * Flash attach API.
 *
 * @param[in] flash - flash structure
 * @param[in] ioc  - ioc structure
 * @param[in] dev  - device structure
 * @param[in] trcmod - trace module
 * @param[in] logmod - log module
 */
void
bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,
		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
{
	flash->ioc = ioc;
	flash->trcmod = trcmod;
	flash->cbfn = NULL;
	flash->cbarg = NULL;
	flash->op_busy = 0;

	bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
	bfa_q_qe_init(&flash->ioc_notify);
	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);

	/* min driver doesn't need flash */
	if (mincfg) {
		flash->dbuf_kva = NULL;
		flash->dbuf_pa = 0;
	}
}

/*
 * Claim memory for flash
 *
 * @param[in] flash - flash structure
 * @param[in] dm_kva - pointer to virtual memory address
 * @param[in] dm_pa - physical memory address
 * @param[in] mincfg - minimal cfg variable
 */
void
bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,
		bfa_boolean_t mincfg)
{
	if (mincfg)
		return;

	flash->dbuf_kva = dm_kva;
	flash->dbuf_pa = dm_pa;
	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
	dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
	dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
}

/*
 * Get flash attribute.
 *
 * @param[in] flash - flash structure
 * @param[in] attr - flash attribute structure
 * @param[in] cbfn - callback function
 * @param[in] cbarg - callback argument
 *
 * Return status.
 */
bfa_status_t
bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,
		bfa_cb_flash_t cbfn, void *cbarg)
{
	bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);

	if (!bfa_ioc_is_operational(flash->ioc))
		return BFA_STATUS_IOC_NON_OP;

	if (flash->op_busy) {
		bfa_trc(flash, flash->op_busy);
		return BFA_STATUS_DEVBUSY;
	}

	flash->op_busy = 1;
	flash->cbfn = cbfn;
	flash->cbarg = cbarg;
	flash->ubuf = (u8 *) attr;
	bfa_flash_query_send(flash);

	return BFA_STATUS_OK;
}

/*
 * Erase flash partition.
 *
 * @param[in] flash - flash structure
 * @param[in] type - flash partition type
 * @param[in] instance - flash partition instance
 * @param[in] cbfn - callback function
 * @param[in] cbarg - callback argument
 *
 * Return status.
 */
bfa_status_t
bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
		u8 instance, bfa_cb_flash_t cbfn, void *cbarg)
{
	bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);
	bfa_trc(flash, type);
	bfa_trc(flash, instance);

	if (!bfa_ioc_is_operational(flash->ioc))
		return BFA_STATUS_IOC_NON_OP;

	if (flash->op_busy) {
		bfa_trc(flash, flash->op_busy);
		return BFA_STATUS_DEVBUSY;
	}

	flash->op_busy = 1;
	flash->cbfn = cbfn;
	flash->cbarg = cbarg;
	flash->type = type;
	flash->instance = instance;

	bfa_flash_erase_send(flash);
	return BFA_STATUS_OK;
}

/*
 * Update flash partition.
 *
 * @param[in] flash - flash structure
 * @param[in] type - flash partition type
 * @param[in] instance - flash partition instance
 * @param[in] buf - update data buffer
 * @param[in] len - data buffer length
 * @param[in] offset - offset relative to the partition starting address
 * @param[in] cbfn - callback function
 * @param[in] cbarg - callback argument
 *
 * Return status.
 */
bfa_status_t
bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
		u8 instance, void *buf, u32 len, u32 offset,
		bfa_cb_flash_t cbfn, void *cbarg)
{
	bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);
	bfa_trc(flash, type);
	bfa_trc(flash, instance);
	bfa_trc(flash, len);
	bfa_trc(flash, offset);

	if (!bfa_ioc_is_operational(flash->ioc))
		return BFA_STATUS_IOC_NON_OP;

	/*
	 * 'len' must be in word (4-byte) boundary
	 * 'offset' must be in sector (16kb) boundary
	 */
	if (!len || (len & 0x03) || (offset & 0x00003FFF))
		return BFA_STATUS_FLASH_BAD_LEN;

	if (type == BFA_FLASH_PART_MFG)
		return BFA_STATUS_EINVAL;

	if (flash->op_busy) {
		bfa_trc(flash, flash->op_busy);
		return BFA_STATUS_DEVBUSY;
	}

	flash->op_busy = 1;
	flash->cbfn = cbfn;
	flash->cbarg = cbarg;
	flash->type = type;
	flash->instance = instance;
	flash->residue = len;
	flash->offset = 0;
	flash->addr_off = offset;
	flash->ubuf = buf;

	bfa_flash_write_send(flash);
	return BFA_STATUS_OK;
}

/*
 * Read flash partition.
 *
 * @param[in] flash - flash structure
 * @param[in] type - flash partition type
 * @param[in] instance - flash partition instance
 * @param[in] buf - read data buffer
 * @param[in] len - data buffer length
 * @param[in] offset - offset relative to the partition starting address
 * @param[in] cbfn - callback function
 * @param[in] cbarg - callback argument
 *
 * Return status.
 */
bfa_status_t
bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
		u8 instance, void *buf, u32 len, u32 offset,
		bfa_cb_flash_t cbfn, void *cbarg)
{
	bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);
	bfa_trc(flash, type);
	bfa_trc(flash, instance);
	bfa_trc(flash, len);
	bfa_trc(flash, offset);

	if (!bfa_ioc_is_operational(flash->ioc))
		return BFA_STATUS_IOC_NON_OP;

	/*
	 * 'len' must be in word (4-byte) boundary
	 * 'offset' must be in sector (16kb) boundary
	 */
	if (!len || (len & 0x03) || (offset & 0x00003FFF))
		return BFA_STATUS_FLASH_BAD_LEN;

	if (flash->op_busy) {
		bfa_trc(flash, flash->op_busy);
		return BFA_STATUS_DEVBUSY;
	}

	flash->op_busy = 1;
	flash->cbfn = cbfn;
	flash->cbarg = cbarg;
	flash->type = type;
	flash->instance = instance;
	flash->residue = len;
	flash->offset = 0;
	flash->addr_off = offset;
	flash->ubuf = buf;
	bfa_flash_read_send(flash);

	return BFA_STATUS_OK;
}
+72 −0
Original line number Diff line number Diff line
@@ -347,6 +347,28 @@ struct bfa_ioc_hwif_s {
	bfa_boolean_t	(*ioc_lpu_read_stat)	(struct bfa_ioc_s *ioc);
};

/*
 * Queue element to wait for room in request queue. FIFO order is
 * maintained when fullfilling requests.
 */
struct bfa_reqq_wait_s {
	struct list_head	qe;
	void	(*qresume) (void *cbarg);
	void	*cbarg;
};

typedef void	(*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);

/*
 * Generic BFA callback element.
 */
struct bfa_cb_qe_s {
	struct list_head	qe;
	bfa_cb_cbfn_t	cbfn;
	bfa_boolean_t	once;
	void		*cbarg;
};

/*
 * ASIC block configurtion related
 */
@@ -419,6 +441,56 @@ bfa_status_t bfa_sfp_speed(struct bfa_sfp_s *sfp,
			enum bfa_port_speed portspeed,
			bfa_cb_sfp_t cbfn, void *cbarg);

/*
 *	Flash module specific
 */
typedef void	(*bfa_cb_flash_t) (void *cbarg, bfa_status_t status);

struct bfa_flash_s {
	struct bfa_ioc_s *ioc;		/* back pointer to ioc */
	struct bfa_trc_mod_s *trcmod;
	u32		type;           /* partition type */
	u8		instance;       /* partition instance */
	u8		rsv[3];
	u32		op_busy;        /*  operation busy flag */
	u32		residue;        /*  residual length */
	u32		offset;         /*  offset */
	bfa_status_t	status;         /*  status */
	u8		*dbuf_kva;      /*  dma buf virtual address */
	u64		dbuf_pa;        /*  dma buf physical address */
	struct bfa_reqq_wait_s	reqq_wait; /*  to wait for room in reqq */
	bfa_cb_flash_t	cbfn;           /*  user callback function */
	void		*cbarg;         /*  user callback arg */
	u8		*ubuf;          /*  user supplied buffer */
	struct bfa_cb_qe_s	hcb_qe; /*  comp: BFA callback qelem */
	u32		addr_off;       /*  partition address offset */
	struct bfa_mbox_cmd_s	mb;       /*  mailbox */
	struct bfa_ioc_notify_s	ioc_notify; /*  ioc event notify */
	struct bfa_mem_dma_s	flash_dma;
};

#define BFA_FLASH(__bfa)		(&(__bfa)->modules.flash)
#define BFA_MEM_FLASH_DMA(__bfa)	(&(BFA_FLASH(__bfa)->flash_dma))

bfa_status_t bfa_flash_get_attr(struct bfa_flash_s *flash,
			struct bfa_flash_attr_s *attr,
			bfa_cb_flash_t cbfn, void *cbarg);
bfa_status_t bfa_flash_erase_part(struct bfa_flash_s *flash,
			enum bfa_flash_part_type type, u8 instance,
			bfa_cb_flash_t cbfn, void *cbarg);
bfa_status_t bfa_flash_update_part(struct bfa_flash_s *flash,
			enum bfa_flash_part_type type, u8 instance,
			void *buf, u32 len, u32 offset,
			bfa_cb_flash_t cbfn, void *cbarg);
bfa_status_t bfa_flash_read_part(struct bfa_flash_s *flash,
			enum bfa_flash_part_type type, u8 instance, void *buf,
			u32 len, u32 offset, bfa_cb_flash_t cbfn, void *cbarg);
u32	bfa_flash_meminfo(bfa_boolean_t mincfg);
void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
void bfa_flash_memclaim(struct bfa_flash_s *flash,
		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);

#define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
#define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
#define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
Loading