Commit 74dd5aa1 authored by Vishal Kulkarni's avatar Vishal Kulkarni Committed by David S. Miller
Browse files

cxgb4: Enable hash filter with offload



Hash (exact-match) filters used for offloading flows share the
same active region resources on the chip with upper layer drivers,
like iw_cxgb4, chcr, etc. Currently, only either Hash filters
or ULDs can use the active region resources, but not both. Hence,
use the new firmware configuration parameters (when available)
to allow both the Hash filters and ULDs to share the
active region simultaneously.

Signed-off-by: default avatarVishal Kulkarni <vishal@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2bb0f3b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -600,6 +600,7 @@ struct port_info {
	u8 vin;
	u8 vivld;
	u8 smt_idx;
	u8 rx_cchan;
};

struct dentry;
+26 −12
Original line number Diff line number Diff line
@@ -1041,7 +1041,7 @@ static void mk_act_open_req6(struct filter_entry *f, struct sk_buff *skb,
			    RSS_QUEUE_V(f->fs.iq) |
			    TX_QUEUE_V(f->fs.nat_mode) |
			    T5_OPT_2_VALID_F |
			    RX_CHANNEL_F |
			    RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
			    CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
					 (f->fs.dirsteer << 1)) |
			    PACE_V((f->fs.maskhash) |
@@ -1081,7 +1081,7 @@ static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
			    RSS_QUEUE_V(f->fs.iq) |
			    TX_QUEUE_V(f->fs.nat_mode) |
			    T5_OPT_2_VALID_F |
			    RX_CHANNEL_F |
			    RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
			    CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
					 (f->fs.dirsteer << 1)) |
			    PACE_V((f->fs.maskhash) |
@@ -1833,24 +1833,38 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
	}
}

int init_hash_filter(struct adapter *adap)
void init_hash_filter(struct adapter *adap)
{
	u32 reg;

	/* On T6, verify the necessary register configs and warn the user in
	 * case of improper config
	 */
	if (is_t6(adap->params.chip)) {
		if (TCAM_ACTV_HIT_G(t4_read_reg(adap, LE_DB_RSP_CODE_0_A)) != 4)
			goto err;
		if (is_offload(adap)) {
			if (!(t4_read_reg(adap, TP_GLOBAL_CONFIG_A)
			   & ACTIVEFILTERCOUNTS_F)) {
				dev_err(adap->pdev_dev, "Invalid hash filter + ofld config\n");
				return;
			}
		} else {
			reg = t4_read_reg(adap, LE_DB_RSP_CODE_0_A);
			if (TCAM_ACTV_HIT_G(reg) != 4) {
				dev_err(adap->pdev_dev, "Invalid hash filter config\n");
				return;
			}

			reg = t4_read_reg(adap, LE_DB_RSP_CODE_1_A);
			if (HASH_ACTV_HIT_G(reg) != 4) {
				dev_err(adap->pdev_dev, "Invalid hash filter config\n");
				return;
			}
		}

		if (HASH_ACTV_HIT_G(t4_read_reg(adap, LE_DB_RSP_CODE_1_A)) != 4)
			goto err;
	} else {
		dev_err(adap->pdev_dev, "Hash filter supported only on T6\n");
		return -EINVAL;
		return;
	}

	adap->params.hash_filter = 1;
	return 0;
err:
	dev_warn(adap->pdev_dev, "Invalid hash filter config!\n");
	return -EINVAL;
}
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ int delete_filter(struct adapter *adapter, unsigned int fidx);

int writable_filter(struct filter_entry *f);
void clear_all_filters(struct adapter *adapter);
int init_hash_filter(struct adapter *adap);
void init_hash_filter(struct adapter *adap);
bool is_filter_exact_match(struct adapter *adap,
			   struct ch_filter_specification *fs);
#endif /* __CXGB4_FILTER_H */
+43 −9
Original line number Diff line number Diff line
@@ -1646,6 +1646,18 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_port_chan);

/**
 *      cxgb4_port_e2cchan - get the HW c-channel of a port
 *      @dev: the net device for the port
 *
 *      Return the HW RX c-channel of the given port.
 */
unsigned int cxgb4_port_e2cchan(const struct net_device *dev)
{
	return netdev2pinfo(dev)->rx_cchan;
}
EXPORT_SYMBOL(cxgb4_port_e2cchan);

unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
{
	struct adapter *adap = netdev2adap(dev);
@@ -3905,14 +3917,14 @@ static int adap_init0_phy(struct adapter *adap)
 */
static int adap_init0_config(struct adapter *adapter, int reset)
{
	char *fw_config_file, fw_config_file_path[256];
	u32 finiver, finicsum, cfcsum, param, val;
	struct fw_caps_config_cmd caps_cmd;
	const struct firmware *cf;
	unsigned long mtype = 0, maddr = 0;
	u32 finiver, finicsum, cfcsum;
	int ret;
	int config_issued = 0;
	char *fw_config_file, fw_config_file_path[256];
	const struct firmware *cf;
	char *config_name = NULL;
	int config_issued = 0;
	int ret;

	/*
	 * Reset device if necessary.
@@ -4020,6 +4032,24 @@ static int adap_init0_config(struct adapter *adapter, int reset)
			goto bye;
	}

	val = 0;

	/* Ofld + Hash filter is supported. Older fw will fail this request and
	 * it is fine.
	 */
	param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
		 FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD));
	ret = t4_set_params(adapter, adapter->mbox, adapter->pf, 0,
			    1, &param, &val);

	/* FW doesn't know about Hash filter + ofld support,
	 * it's not a problem, don't return an error.
	 */
	if (ret < 0) {
		dev_warn(adapter->pdev_dev,
			 "Hash filter with ofld is not supported by FW\n");
	}

	/*
	 * Issue a Capability Configuration command to the firmware to get it
	 * to parse the Configuration File.  We don't use t4_fw_config_file()
@@ -4580,6 +4610,13 @@ static int adap_init0(struct adapter *adap)
	if (ret < 0)
		goto bye;

	/* hash filter has some mandatory register settings to be tested and for
	 * that it needs to test whether offload is enabled or not, hence
	 * checking and setting it here.
	 */
	if (caps_cmd.ofldcaps)
		adap->params.offload = 1;

	if (caps_cmd.ofldcaps ||
	    (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_HASHFILTER))) {
		/* query offload-related parameters */
@@ -4619,11 +4656,8 @@ static int adap_init0(struct adapter *adap)
		adap->params.ofldq_wr_cred = val[5];

		if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_HASHFILTER)) {
			ret = init_hash_filter(adap);
			if (ret < 0)
				goto bye;
			init_hash_filter(adap);
		} else {
			adap->params.offload = 1;
			adap->num_ofld_uld += 1;
		}
	}
+1 −0
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ int cxgb4_immdata_send(struct net_device *dev, unsigned int idx,
int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb);
unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
unsigned int cxgb4_port_chan(const struct net_device *dev);
unsigned int cxgb4_port_e2cchan(const struct net_device *dev);
unsigned int cxgb4_port_viid(const struct net_device *dev);
unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid);
unsigned int cxgb4_port_idx(const struct net_device *dev);
Loading