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

Commit 636f9d37 authored by Vipul Pandya's avatar Vipul Pandya Committed by David S. Miller
Browse files

cxgb4: Add support for T4 configuration file



Starting with T4 firmware version 1.3.11.0 the firmware now supports device
configuration via a Firmware Configuration File. The Firmware Configuration
File was primarily developed in order to centralize all of the configuration,
resource allocation, etc. for Unified Wire operation where multiple
Physical / Virtual Function Drivers would be using a T4 adapter simultaneously.

The Firmware Configuration file can live in three locations as shown below
in order of precedence.
1) User defined configuration file: /lib/firmware/cxgb4/t4-config.txt
2) Factory Default configuration file written to FLASH within
   the manufacturing process.
3) Hardwired driver configuration.

Signed-off-by: default avatarJay Hernandez <jay@chelsio.com>
Signed-off-by: default avatarVipul Pandya <vipul@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 52367a76
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -211,6 +211,9 @@ struct tp_err_stats {
struct tp_params {
struct tp_params {
	unsigned int ntxchan;        /* # of Tx channels */
	unsigned int ntxchan;        /* # of Tx channels */
	unsigned int tre;            /* log2 of core clocks per TP tick */
	unsigned int tre;            /* log2 of core clocks per TP tick */

	uint32_t dack_re;            /* DACK timer resolution */
	unsigned short tx_modq[NCHAN];	/* channel to modulation queue map */
};
};


struct vpd_params {
struct vpd_params {
@@ -519,6 +522,8 @@ struct adapter {
	struct net_device *port[MAX_NPORTS];
	struct net_device *port[MAX_NPORTS];
	u8 chan_map[NCHAN];                   /* channel -> port map */
	u8 chan_map[NCHAN];                   /* channel -> port map */


	unsigned int l2t_start;
	unsigned int l2t_end;
	struct l2t_data *l2t;
	struct l2t_data *l2t;
	void *uld_handle[CXGB4_ULD_MAX];
	void *uld_handle[CXGB4_ULD_MAX];
	struct list_head list_node;
	struct list_head list_node;
@@ -683,7 +688,9 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
		    __be32 *buf);
		    __be32 *buf);
int t4_seeprom_wp(struct adapter *adapter, bool enable);
int t4_seeprom_wp(struct adapter *adapter, bool enable);
int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
unsigned int t4_flash_cfg_addr(struct adapter *adapter);
int t4_check_fw_version(struct adapter *adapter);
int t4_check_fw_version(struct adapter *adapter);
int t4_prep_adapter(struct adapter *adapter);
int t4_prep_adapter(struct adapter *adapter);
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
@@ -698,6 +705,8 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,


void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
			    unsigned int mask, unsigned int val);
void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
			 struct tp_tcp_stats *v6);
			 struct tp_tcp_stats *v6);
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
@@ -713,6 +722,12 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
int t4_fw_bye(struct adapter *adap, unsigned int mbox);
int t4_fw_bye(struct adapter *adap, unsigned int mbox);
int t4_early_init(struct adapter *adap, unsigned int mbox);
int t4_early_init(struct adapter *adap, unsigned int mbox);
int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset);
int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset);
int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
		      unsigned int mtype, unsigned int maddr,
		      u32 *finiver, u32 *finicsum, u32 *cfcsum);
int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
			  unsigned int cache_line_size);
int t4_fw_initialize(struct adapter *adap, unsigned int mbox);
int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
		    unsigned int vf, unsigned int nparams, const u32 *params,
		    unsigned int vf, unsigned int nparams, const u32 *params,
		    u32 *val);
		    u32 *val);
+476 −94
Original line number Original line Diff line number Diff line
@@ -193,6 +193,7 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
};
};


#define FW_FNAME "cxgb4/t4fw.bin"
#define FW_FNAME "cxgb4/t4fw.bin"
#define FW_CFNAME "cxgb4/t4-config.txt"


MODULE_DESCRIPTION(DRV_DESC);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_AUTHOR("Chelsio Communications");
MODULE_AUTHOR("Chelsio Communications");
@@ -201,6 +202,17 @@ MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
MODULE_FIRMWARE(FW_FNAME);
MODULE_FIRMWARE(FW_FNAME);


/*
 * Normally we're willing to become the firmware's Master PF but will be happy
 * if another PF has already become the Master and initialized the adapter.
 * Setting "force_init" will cause this driver to forcibly establish itself as
 * the Master PF and initialize the adapter.
 */
static uint force_init;

module_param(force_init, uint, 0644);
MODULE_PARM_DESC(force_init, "Forcibly become Master PF and initialize adapter");

static int dflt_msg_enable = DFLT_MSG_ENABLE;
static int dflt_msg_enable = DFLT_MSG_ENABLE;


module_param(dflt_msg_enable, int, 0644);
module_param(dflt_msg_enable, int, 0644);
@@ -236,6 +248,20 @@ module_param_array(intr_cnt, uint, NULL, 0644);
MODULE_PARM_DESC(intr_cnt,
MODULE_PARM_DESC(intr_cnt,
		 "thresholds 1..3 for queue interrupt packet counters");
		 "thresholds 1..3 for queue interrupt packet counters");


/*
 * Normally we tell the chip to deliver Ingress Packets into our DMA buffers
 * offset by 2 bytes in order to have the IP headers line up on 4-byte
 * boundaries.  This is a requirement for many architectures which will throw
 * a machine check fault if an attempt is made to access one of the 4-byte IP
 * header fields on a non-4-byte boundary.  And it's a major performance issue
 * even on some architectures which allow it like some implementations of the
 * x86 ISA.  However, some architectures don't mind this and for some very
 * edge-case performance sensitive applications (like forwarding large volumes
 * of small packets), setting this DMA offset to 0 will decrease the number of
 * PCI-E Bus transfers enough to measurably affect performance.
 */
static int rx_dma_offset = 2;

static bool vf_acls;
static bool vf_acls;


#ifdef CONFIG_PCI_IOV
#ifdef CONFIG_PCI_IOV
@@ -3076,6 +3102,10 @@ static void setup_memwin(struct adapter *adap)
	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
		     (bar0 + MEMWIN2_BASE) | BIR(0) |
		     (bar0 + MEMWIN2_BASE) | BIR(0) |
		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
}

static void setup_memwin_rdma(struct adapter *adap)
{
	if (adap->vres.ocq.size) {
	if (adap->vres.ocq.size) {
		unsigned int start, sz_kb;
		unsigned int start, sz_kb;


@@ -3153,6 +3183,232 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
 */
 */
#define MAX_ATIDS 8192U
#define MAX_ATIDS 8192U


/*
 * Phase 0 of initialization: contact FW, obtain config, perform basic init.
 *
 * If the firmware we're dealing with has Configuration File support, then
 * we use that to perform all configuration
 */

/*
 * Tweak configuration based on module parameters, etc.  Most of these have
 * defaults assigned to them by Firmware Configuration Files (if we're using
 * them) but need to be explicitly set if we're using hard-coded
 * initialization.  But even in the case of using Firmware Configuration
 * Files, we'd like to expose the ability to change these via module
 * parameters so these are essentially common tweaks/settings for
 * Configuration Files and hard-coded initialization ...
 */
static int adap_init0_tweaks(struct adapter *adapter)
{
	/*
	 * Fix up various Host-Dependent Parameters like Page Size, Cache
	 * Line Size, etc.  The firmware default is for a 4KB Page Size and
	 * 64B Cache Line Size ...
	 */
	t4_fixup_host_params(adapter, PAGE_SIZE, L1_CACHE_BYTES);

	/*
	 * Process module parameters which affect early initialization.
	 */
	if (rx_dma_offset != 2 && rx_dma_offset != 0) {
		dev_err(&adapter->pdev->dev,
			"Ignoring illegal rx_dma_offset=%d, using 2\n",
			rx_dma_offset);
		rx_dma_offset = 2;
	}
	t4_set_reg_field(adapter, SGE_CONTROL,
			 PKTSHIFT_MASK,
			 PKTSHIFT(rx_dma_offset));

	/*
	 * Don't include the "IP Pseudo Header" in CPL_RX_PKT checksums: Linux
	 * adds the pseudo header itself.
	 */
	t4_tp_wr_bits_indirect(adapter, TP_INGRESS_CONFIG,
			       CSUM_HAS_PSEUDO_HDR, 0);

	return 0;
}

/*
 * Attempt to initialize the adapter via a Firmware Configuration File.
 */
static int adap_init0_config(struct adapter *adapter, int reset)
{
	struct fw_caps_config_cmd caps_cmd;
	const struct firmware *cf;
	unsigned long mtype = 0, maddr = 0;
	u32 finiver, finicsum, cfcsum;
	int ret, using_flash;

	/*
	 * Reset device if necessary.
	 */
	if (reset) {
		ret = t4_fw_reset(adapter, adapter->mbox,
				  PIORSTMODE | PIORST);
		if (ret < 0)
			goto bye;
	}

	/*
	 * If we have a T4 configuration file under /lib/firmware/cxgb4/,
	 * then use that.  Otherwise, use the configuration file stored
	 * in the adapter flash ...
	 */
	ret = request_firmware(&cf, FW_CFNAME, adapter->pdev_dev);
	if (ret < 0) {
		using_flash = 1;
		mtype = FW_MEMTYPE_CF_FLASH;
		maddr = t4_flash_cfg_addr(adapter);
	} else {
		u32 params[7], val[7];

		using_flash = 0;
		if (cf->size >= FLASH_CFG_MAX_SIZE)
			ret = -ENOMEM;
		else {
			params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
			     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
			ret = t4_query_params(adapter, adapter->mbox,
					      adapter->fn, 0, 1, params, val);
			if (ret == 0) {
				/*
				 * For t4_memory_write() below addresses and
				 * sizes have to be in terms of multiples of 4
				 * bytes.  So, if the Configuration File isn't
				 * a multiple of 4 bytes in length we'll have
				 * to write that out separately since we can't
				 * guarantee that the bytes following the
				 * residual byte in the buffer returned by
				 * request_firmware() are zeroed out ...
				 */
				size_t resid = cf->size & 0x3;
				size_t size = cf->size & ~0x3;
				__be32 *data = (__be32 *)cf->data;

				mtype = FW_PARAMS_PARAM_Y_GET(val[0]);
				maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16;

				ret = t4_memory_write(adapter, mtype, maddr,
						      size, data);
				if (ret == 0 && resid != 0) {
					union {
						__be32 word;
						char buf[4];
					} last;
					int i;

					last.word = data[size >> 2];
					for (i = resid; i < 4; i++)
						last.buf[i] = 0;
					ret = t4_memory_write(adapter, mtype,
							      maddr + size,
							      4, &last.word);
				}
			}
		}

		release_firmware(cf);
		if (ret)
			goto bye;
	}

	/*
	 * Issue a Capability Configuration command to the firmware to get it
	 * to parse the Configuration File.  We don't use t4_fw_config_file()
	 * because we want the ability to modify various features after we've
	 * processed the configuration file ...
	 */
	memset(&caps_cmd, 0, sizeof(caps_cmd));
	caps_cmd.op_to_write =
		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
		      FW_CMD_REQUEST |
		      FW_CMD_READ);
	caps_cmd.retval_len16 =
		htonl(FW_CAPS_CONFIG_CMD_CFVALID |
		      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
		      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
		      FW_LEN16(caps_cmd));
	ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
			 &caps_cmd);
	if (ret < 0)
		goto bye;

	finiver = ntohl(caps_cmd.finiver);
	finicsum = ntohl(caps_cmd.finicsum);
	cfcsum = ntohl(caps_cmd.cfcsum);
	if (finicsum != cfcsum)
		dev_warn(adapter->pdev_dev, "Configuration File checksum "\
			 "mismatch: [fini] csum=%#x, computed csum=%#x\n",
			 finicsum, cfcsum);

	/*
	 * If we're a pure NIC driver then disable all offloading facilities.
	 * This will allow the firmware to optimize aspects of the hardware
	 * configuration which will result in improved performance.
	 */
	caps_cmd.ofldcaps = 0;
	caps_cmd.iscsicaps = 0;
	caps_cmd.rdmacaps = 0;
	caps_cmd.fcoecaps = 0;

	/*
	 * And now tell the firmware to use the configuration we just loaded.
	 */
	caps_cmd.op_to_write =
		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
		      FW_CMD_REQUEST |
		      FW_CMD_WRITE);
	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
	ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
			 NULL);
	if (ret < 0)
		goto bye;

	/*
	 * Tweak configuration based on system architecture, module
	 * parameters, etc.
	 */
	ret = adap_init0_tweaks(adapter);
	if (ret < 0)
		goto bye;

	/*
	 * And finally tell the firmware to initialize itself using the
	 * parameters from the Configuration File.
	 */
	ret = t4_fw_initialize(adapter, adapter->mbox);
	if (ret < 0)
		goto bye;

	/*
	 * Return successfully and note that we're operating with parameters
	 * not supplied by the driver, rather than from hard-wired
	 * initialization constants burried in the driver.
	 */
	adapter->flags |= USING_SOFT_PARAMS;
	dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
		 "Configuration File %s, version %#x, computed checksum %#x\n",
		 (using_flash
		  ? "in device FLASH"
		  : "/lib/firmware/" FW_CFNAME),
		 finiver, cfcsum);
	return 0;

	/*
	 * Something bad happened.  Return the error ...  (If the "error"
	 * is that there's no Configuration File on the adapter we don't
	 * want to issue a warning since this is fairly common.)
	 */
bye:
	if (ret != -ENOENT)
		dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
			 -ret);
	return ret;
}

/*
/*
 * Phase 0 of initialization: contact FW, obtain config, perform basic init.
 * Phase 0 of initialization: contact FW, obtain config, perform basic init.
 */
 */
@@ -3162,72 +3418,197 @@ static int adap_init0(struct adapter *adap)
	u32 v, port_vec;
	u32 v, port_vec;
	enum dev_state state;
	enum dev_state state;
	u32 params[7], val[7];
	u32 params[7], val[7];
	struct fw_caps_config_cmd c;
	int reset = 1, j;


	/*
	 * Contact FW, advertising Master capability (and potentially forcing
	 * ourselves as the Master PF if our module parameter force_init is
	 * set).
	 */
	ret = t4_fw_hello(adap, adap->mbox, adap->fn,
			  force_init ? MASTER_MUST : MASTER_MAY,
			  &state);
	if (ret < 0) {
		dev_err(adap->pdev_dev, "could not connect to FW, error %d\n",
			ret);
		return ret;
	}
	if (ret == adap->mbox)
		adap->flags |= MASTER_PF;
	if (force_init && state == DEV_STATE_INIT)
		state = DEV_STATE_UNINIT;

	/*
	 * If we're the Master PF Driver and the device is uninitialized,
	 * then let's consider upgrading the firmware ...  (We always want
	 * to check the firmware version number in order to A. get it for
	 * later reporting and B. to warn if the currently loaded firmware
	 * is excessively mismatched relative to the driver.)
	 */
	ret = t4_check_fw_version(adap);
	ret = t4_check_fw_version(adap);
	if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
		if (ret == -EINVAL || ret > 0) {
		if (ret == -EINVAL || ret > 0) {
		if (upgrade_fw(adap) >= 0)             /* recache FW version */
			if (upgrade_fw(adap) >= 0) {
				/*
				 * Note that the chip was reset as part of the
				 * firmware upgrade so we don't reset it again
				 * below and grab the new firmware version.
				 */
				reset = 0;
				ret = t4_check_fw_version(adap);
				ret = t4_check_fw_version(adap);
			}
			}
		}
		if (ret < 0)
		if (ret < 0)
			return ret;
			return ret;

	/* contact FW, request master */
	ret = t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, &state);
	if (ret < 0) {
		dev_err(adap->pdev_dev, "could not connect to FW, error %d\n",
			ret);
		return ret;
	}
	}


	/* reset device */
	/*
	ret = t4_fw_reset(adap, adap->fn, PIORSTMODE | PIORST);
	 * Grab VPD parameters.  This should be done after we establish a
	 * connection to the firmware since some of the VPD parameters
	 * (notably the Core Clock frequency) are retrieved via requests to
	 * the firmware.  On the other hand, we need these fairly early on
	 * so we do this right after getting ahold of the firmware.
	 */
	ret = get_vpd_params(adap, &adap->params.vpd);
	if (ret < 0)
	if (ret < 0)
		goto bye;
		goto bye;


	for (v = 0; v < SGE_NTIMERS - 1; v++)
	/*
		adap->sge.timer_val[v] = min(intr_holdoff[v], MAX_SGE_TIMERVAL);
	 * Find out what ports are available to us.
	adap->sge.timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL;
	 */
	adap->sge.counter_val[0] = 1;
	v =
	for (v = 1; v < SGE_NCOUNTERS; v++)
	    FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
		adap->sge.counter_val[v] = min(intr_cnt[v - 1],
	    FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC);
					       THRESHOLD_3_MASK);
	ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, &v, &port_vec);
#define FW_PARAM_DEV(param) \
	if (ret < 0)
	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
		goto bye;
	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))

	adap->params.nports = hweight32(port_vec);
	adap->params.portvec = port_vec;

	/*
	 * If the firmware is initialized already (and we're not forcing a
	 * master initialization), note that we're living with existing
	 * adapter parameters.  Otherwise, it's time to try initializing the
	 * adapter ...
	 */
	if (state == DEV_STATE_INIT) {
		dev_info(adap->pdev_dev, "Coming up as %s: "\
			 "Adapter already initialized\n",
			 adap->flags & MASTER_PF ? "MASTER" : "SLAVE");
		adap->flags |= USING_SOFT_PARAMS;
	} else {
		dev_info(adap->pdev_dev, "Coming up as MASTER: "\
			 "Initializing adapter\n");
		/*
		 * Find out whether we're dealing with a version of
		 * the firmware which has configuration file support.
		 */
		params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
			     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1,
				      params, val);


	params[0] = FW_PARAM_DEV(CCLK);
		/*
	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 1, params, val);
		 * If the firmware doesn't support Configuration
		 * Files warn user and exit,
		 */
		if (ret < 0)
		if (ret < 0)
			dev_warn(adap->pdev_dev, "Firmware doesn't support "\
				 "configuration file.\n");
		else {
			/*
			 * The firmware provides us with a memory
			 * buffer where we can load a Configuration
			 * File from the host if we want to override
			 * the Configuration File in flash.
			 */

			ret = adap_init0_config(adap, reset);
			if (ret == -ENOENT) {
				dev_info(adap->pdev_dev,
				    "No Configuration File present "
				    "on adapter.\n");
			}
		}
		if (ret < 0) {
			dev_err(adap->pdev_dev,
				"could not initialize adapter, error %d\n",
				-ret);
			goto bye;
			goto bye;
	adap->params.vpd.cclk = val[0];
		}
	}


	ret = adap_init1(adap, &c);
	/*
	 * If we're living with non-hard-coded parameters (either from a
	 * Firmware Configuration File or values programmed by a different PF
	 * Driver), give the SGE code a chance to pull in anything that it
	 * needs ...  Note that this must be called after we retrieve our VPD
	 * parameters in order to know how to convert core ticks to seconds.
	 */
	if (adap->flags & USING_SOFT_PARAMS) {
		ret = t4_sge_init(adap);
		if (ret < 0)
		if (ret < 0)
			goto bye;
			goto bye;
	}

	/*
	 * Grab some of our basic fundamental operating parameters.
	 */
#define FW_PARAM_DEV(param) \
	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
	FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))


#define FW_PARAM_PFVF(param) \
#define FW_PARAM_PFVF(param) \
	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
	FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
	FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)|  \
	FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)|  \
	 FW_PARAMS_PARAM_Y(adap->fn))
	FW_PARAMS_PARAM_Y(0) | \
	FW_PARAMS_PARAM_Z(0)


	params[0] = FW_PARAM_DEV(PORTVEC);
	params[0] = FW_PARAM_PFVF(EQ_START);
	params[1] = FW_PARAM_PFVF(L2T_START);
	params[1] = FW_PARAM_PFVF(L2T_START);
	params[2] = FW_PARAM_PFVF(L2T_END);
	params[2] = FW_PARAM_PFVF(L2T_END);
	params[3] = FW_PARAM_PFVF(FILTER_START);
	params[3] = FW_PARAM_PFVF(FILTER_START);
	params[4] = FW_PARAM_PFVF(FILTER_END);
	params[4] = FW_PARAM_PFVF(FILTER_END);
	params[5] = FW_PARAM_PFVF(IQFLINT_START);
	params[5] = FW_PARAM_PFVF(IQFLINT_START);
	params[6] = FW_PARAM_PFVF(EQ_START);
	ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, params, val);
	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val);
	if (ret < 0)
	if (ret < 0)
		goto bye;
		goto bye;
	port_vec = val[0];
	adap->sge.egr_start = val[0];
	adap->l2t_start = val[1];
	adap->l2t_end = val[2];
	adap->tids.ftid_base = val[3];
	adap->tids.ftid_base = val[3];
	adap->tids.nftids = val[4] - val[3] + 1;
	adap->tids.nftids = val[4] - val[3] + 1;
	adap->sge.ingr_start = val[5];
	adap->sge.ingr_start = val[5];
	adap->sge.egr_start = val[6];


	if (c.ofldcaps) {
	/* query params related to active filter region */
	params[0] = FW_PARAM_PFVF(ACTIVE_FILTER_START);
	params[1] = FW_PARAM_PFVF(ACTIVE_FILTER_END);
	ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params, val);
	/* If Active filter size is set we enable establishing
	 * offload connection through firmware work request
	 */
	if ((val[0] != val[1]) && (ret >= 0)) {
		adap->flags |= FW_OFLD_CONN;
		adap->tids.aftid_base = val[0];
		adap->tids.aftid_end = val[1];
	}

#ifdef CONFIG_CHELSIO_T4_OFFLOAD
	/*
	 * Get device capabilities so we can determine what resources we need
	 * to manage.
	 */
	memset(&caps_cmd, 0, sizeof(caps_cmd));
	caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
				     F_FW_CMD_REQUEST | F_FW_CMD_READ);
	caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
	ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
			 &caps_cmd);
	if (ret < 0)
		goto bye;

	if (caps_cmd.toecaps) {
		/* query offload-related parameters */
		/* query offload-related parameters */
		params[0] = FW_PARAM_DEV(NTID);
		params[0] = FW_PARAM_DEV(NTID);
		params[1] = FW_PARAM_PFVF(SERVER_START);
		params[1] = FW_PARAM_PFVF(SERVER_START);
@@ -3235,28 +3616,55 @@ static int adap_init0(struct adapter *adap)
		params[3] = FW_PARAM_PFVF(TDDP_START);
		params[3] = FW_PARAM_PFVF(TDDP_START);
		params[4] = FW_PARAM_PFVF(TDDP_END);
		params[4] = FW_PARAM_PFVF(TDDP_END);
		params[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ);
		params[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ);
		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6,
				      val);
				      params, val);
		if (ret < 0)
		if (ret < 0)
			goto bye;
			goto bye;
		adap->tids.ntids = val[0];
		adap->tids.ntids = val[0];
		adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
		adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
		adap->tids.stid_base = val[1];
		adap->tids.stid_base = val[1];
		adap->tids.nstids = val[2] - val[1] + 1;
		adap->tids.nstids = val[2] - val[1] + 1;
		/*
		 * Setup server filter region. Divide the availble filter
		 * region into two parts. Regular filters get 1/3rd and server
		 * filters get 2/3rd part. This is only enabled if workarond
		 * path is enabled.
		 * 1. For regular filters.
		 * 2. Server filter: This are special filters which are used
		 * to redirect SYN packets to offload queue.
		 */
		if (adap->flags & FW_OFLD_CONN && !is_bypass(adap)) {
			adap->tids.sftid_base = adap->tids.ftid_base +
					DIV_ROUND_UP(adap->tids.nftids, 3);
			adap->tids.nsftids = adap->tids.nftids -
					 DIV_ROUND_UP(adap->tids.nftids, 3);
			adap->tids.nftids = adap->tids.sftid_base -
						adap->tids.ftid_base;
		}
		adap->vres.ddp.start = val[3];
		adap->vres.ddp.start = val[3];
		adap->vres.ddp.size = val[4] - val[3] + 1;
		adap->vres.ddp.size = val[4] - val[3] + 1;
		adap->params.ofldq_wr_cred = val[5];
		adap->params.ofldq_wr_cred = val[5];

		params[0] = FW_PARAM_PFVF(ETHOFLD_START);
		params[1] = FW_PARAM_PFVF(ETHOFLD_END);
		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
				      params, val);
		if ((val[0] != val[1]) && (ret >= 0)) {
			adap->tids.uotid_base = val[0];
			adap->tids.nuotids = val[1] - val[0] + 1;
		}

		adap->params.offload = 1;
		adap->params.offload = 1;
	}
	}
	if (c.rdmacaps) {
	if (caps_cmd.rdmacaps) {
		params[0] = FW_PARAM_PFVF(STAG_START);
		params[0] = FW_PARAM_PFVF(STAG_START);
		params[1] = FW_PARAM_PFVF(STAG_END);
		params[1] = FW_PARAM_PFVF(STAG_END);
		params[2] = FW_PARAM_PFVF(RQ_START);
		params[2] = FW_PARAM_PFVF(RQ_START);
		params[3] = FW_PARAM_PFVF(RQ_END);
		params[3] = FW_PARAM_PFVF(RQ_END);
		params[4] = FW_PARAM_PFVF(PBL_START);
		params[4] = FW_PARAM_PFVF(PBL_START);
		params[5] = FW_PARAM_PFVF(PBL_END);
		params[5] = FW_PARAM_PFVF(PBL_END);
		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6,
				      val);
				      params, val);
		if (ret < 0)
		if (ret < 0)
			goto bye;
			goto bye;
		adap->vres.stag.start = val[0];
		adap->vres.stag.start = val[0];
@@ -3272,8 +3680,7 @@ static int adap_init0(struct adapter *adap)
		params[3] = FW_PARAM_PFVF(CQ_END);
		params[3] = FW_PARAM_PFVF(CQ_END);
		params[4] = FW_PARAM_PFVF(OCQ_START);
		params[4] = FW_PARAM_PFVF(OCQ_START);
		params[5] = FW_PARAM_PFVF(OCQ_END);
		params[5] = FW_PARAM_PFVF(OCQ_END);
		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
		ret = t4_query_params(adap, 0, 0, 0, 6, params, val);
				      val);
		if (ret < 0)
		if (ret < 0)
			goto bye;
			goto bye;
		adap->vres.qp.start = val[0];
		adap->vres.qp.start = val[0];
@@ -3283,11 +3690,11 @@ static int adap_init0(struct adapter *adap)
		adap->vres.ocq.start = val[4];
		adap->vres.ocq.start = val[4];
		adap->vres.ocq.size = val[5] - val[4] + 1;
		adap->vres.ocq.size = val[5] - val[4] + 1;
	}
	}
	if (c.iscsicaps) {
	if (caps_cmd.iscsicaps) {
		params[0] = FW_PARAM_PFVF(ISCSI_START);
		params[0] = FW_PARAM_PFVF(ISCSI_START);
		params[1] = FW_PARAM_PFVF(ISCSI_END);
		params[1] = FW_PARAM_PFVF(ISCSI_END);
		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 2, params,
		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
				      val);
				      params, val);
		if (ret < 0)
		if (ret < 0)
			goto bye;
			goto bye;
		adap->vres.iscsi.start = val[0];
		adap->vres.iscsi.start = val[0];
@@ -3295,63 +3702,33 @@ static int adap_init0(struct adapter *adap)
	}
	}
#undef FW_PARAM_PFVF
#undef FW_PARAM_PFVF
#undef FW_PARAM_DEV
#undef FW_PARAM_DEV
#endif /* CONFIG_CHELSIO_T4_OFFLOAD */


	adap->params.nports = hweight32(port_vec);
	/*
	adap->params.portvec = port_vec;
	 * These are finalized by FW initialization, load their values now.
	adap->flags |= FW_OK;
	 */

	/* These are finalized by FW initialization, load their values now */
	v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
	v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
	adap->params.tp.tre = TIMERRESOLUTION_GET(v);
	adap->params.tp.tre = TIMERRESOLUTION_GET(v);
	adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
	t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
	t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
		     adap->params.b_wnd);
		     adap->params.b_wnd);


#ifdef CONFIG_PCI_IOV
	/* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
	/*
	for (j = 0; j < NCHAN; j++)
	 * Provision resource limits for Virtual Functions.  We currently
		adap->params.tp.tx_modq[j] = j;
	 * grant them all the same static resource limits except for the Port
	 * Access Rights Mask which we're assigning based on the PF.  All of
	 * the static provisioning stuff for both the PF and VF really needs
	 * to be managed in a persistent manner for each device which the
	 * firmware controls.
	 */
	{
		int pf, vf;

		for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) {
			if (num_vf[pf] <= 0)
				continue;


			/* VF numbering starts at 1! */
	adap->flags |= FW_OK;
			for (vf = 1; vf <= num_vf[pf]; vf++) {
				ret = t4_cfg_pfvf(adap, adap->fn, pf, vf,
						  VFRES_NEQ, VFRES_NETHCTRL,
						  VFRES_NIQFLINT, VFRES_NIQ,
						  VFRES_TC, VFRES_NVI,
						  FW_PFVF_CMD_CMASK_MASK,
						  pfvfres_pmask(adap, pf, vf),
						  VFRES_NEXACTF,
						  VFRES_R_CAPS, VFRES_WX_CAPS);
				if (ret < 0)
					dev_warn(adap->pdev_dev, "failed to "
						 "provision pf/vf=%d/%d; "
						 "err=%d\n", pf, vf, ret);
			}
		}
	}
#endif

	setup_memwin(adap);
	return 0;
	return 0;


	/*
	/*
	 * If a command timed out or failed with EIO FW does not operate within
	 * Something bad happened.  If a command timed out or failed with EIO
	 * its spec or something catastrophic happened to HW/FW, stop issuing
	 * FW does not operate within its spec or something catastrophic
	 * commands.
	 * happened to HW/FW, stop issuing commands.
	 */
	 */
bye:	if (ret != -ETIMEDOUT && ret != -EIO)
bye:
		t4_fw_bye(adap, adap->fn);
	if (ret != -ETIMEDOUT && ret != -EIO)
		t4_fw_bye(adap, adap->mbox);
	return ret;
	return ret;
}
}


@@ -3814,7 +4191,9 @@ static int __devinit init_one(struct pci_dev *pdev,
	err = t4_prep_adapter(adapter);
	err = t4_prep_adapter(adapter);
	if (err)
	if (err)
		goto out_unmap_bar;
		goto out_unmap_bar;
	setup_memwin(adapter);
	err = adap_init0(adapter);
	err = adap_init0(adapter);
	setup_memwin_rdma(adapter);
	if (err)
	if (err)
		goto out_unmap_bar;
		goto out_unmap_bar;


@@ -3956,8 +4335,11 @@ static void __devexit remove_one(struct pci_dev *pdev)
{
{
	struct adapter *adapter = pci_get_drvdata(pdev);
	struct adapter *adapter = pci_get_drvdata(pdev);


#ifdef CONFIG_PCI_IOV
	pci_disable_sriov(pdev);
	pci_disable_sriov(pdev);


#endif

	if (adapter) {
	if (adapter) {
		int i;
		int i;


+2 −0
Original line number Original line Diff line number Diff line
@@ -100,6 +100,8 @@ struct tid_info {


	unsigned int nftids;
	unsigned int nftids;
	unsigned int ftid_base;
	unsigned int ftid_base;
	unsigned int aftid_base;
	unsigned int aftid_end;


	spinlock_t atid_lock ____cacheline_aligned_in_smp;
	spinlock_t atid_lock ____cacheline_aligned_in_smp;
	union aopen_entry *afree;
	union aopen_entry *afree;
Loading