aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSudarsana Kalluru <Sudarsana.Kalluru@qlogic.com>2015-10-26 05:02:30 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-27 22:34:50 -0400
commit0d8e0aa05796c8a5652c164de5e4f16d8c9ee199 (patch)
tree746c8c6a282891763263d6afe048b932c4a5ca3f
parent2950219d87b040959f23484dd4ff5856bf1bc172 (diff)
qede: classification configuration
Add the ability to configure basic classification in driver by implementing ndo_set_mac_address() and ndo_set_rx_mode(). Signed-off-by: Sudarsana Kalluru <Sudarsana.Kalluru@qlogic.com> Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com> Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede.h10
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c241
2 files changed, 251 insertions, 0 deletions
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 424ef4a55828..79479427b6d4 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -87,6 +87,9 @@ struct qede_dev {
87 struct qed_update_vport_rss_params rss_params; 87 struct qed_update_vport_rss_params rss_params;
88 u16 q_num_rx_buffers; /* Must be a power of two */ 88 u16 q_num_rx_buffers; /* Must be a power of two */
89 u16 q_num_tx_buffers; /* Must be a power of two */ 89 u16 q_num_tx_buffers; /* Must be a power of two */
90
91 struct delayed_work sp_task;
92 unsigned long sp_flags;
90}; 93};
91 94
92enum QEDE_STATE { 95enum QEDE_STATE {
@@ -184,6 +187,13 @@ struct qede_fastpath {
184 187
185#define QEDE_CSUM_ERROR BIT(0) 188#define QEDE_CSUM_ERROR BIT(0)
186#define QEDE_CSUM_UNNECESSARY BIT(1) 189#define QEDE_CSUM_UNNECESSARY BIT(1)
190
191#define QEDE_SP_RX_MODE 1
192
193union qede_reload_args {
194 u16 mtu;
195};
196
187#define RX_RING_SIZE_POW 13 197#define RX_RING_SIZE_POW 13
188#define RX_RING_SIZE BIT(RX_RING_SIZE_POW) 198#define RX_RING_SIZE BIT(RX_RING_SIZE_POW)
189#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1) 199#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index daba118f99ca..0351204317e7 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1030,10 +1030,31 @@ static irqreturn_t qede_msix_fp_int(int irq, void *fp_cookie)
1030 1030
1031static int qede_open(struct net_device *ndev); 1031static int qede_open(struct net_device *ndev);
1032static int qede_close(struct net_device *ndev); 1032static int qede_close(struct net_device *ndev);
1033static int qede_set_mac_addr(struct net_device *ndev, void *p);
1034static void qede_set_rx_mode(struct net_device *ndev);
1035static void qede_config_rx_mode(struct net_device *ndev);
1036
1037static int qede_set_ucast_rx_mac(struct qede_dev *edev,
1038 enum qed_filter_xcast_params_type opcode,
1039 unsigned char mac[ETH_ALEN])
1040{
1041 struct qed_filter_params filter_cmd;
1042
1043 memset(&filter_cmd, 0, sizeof(filter_cmd));
1044 filter_cmd.type = QED_FILTER_TYPE_UCAST;
1045 filter_cmd.filter.ucast.type = opcode;
1046 filter_cmd.filter.ucast.mac_valid = 1;
1047 ether_addr_copy(filter_cmd.filter.ucast.mac, mac);
1048
1049 return edev->ops->filter_config(edev->cdev, &filter_cmd);
1050}
1051
1033static const struct net_device_ops qede_netdev_ops = { 1052static const struct net_device_ops qede_netdev_ops = {
1034 .ndo_open = qede_open, 1053 .ndo_open = qede_open,
1035 .ndo_stop = qede_close, 1054 .ndo_stop = qede_close,
1036 .ndo_start_xmit = qede_start_xmit, 1055 .ndo_start_xmit = qede_start_xmit,
1056 .ndo_set_rx_mode = qede_set_rx_mode,
1057 .ndo_set_mac_address = qede_set_mac_addr,
1037 .ndo_validate_addr = eth_validate_addr, 1058 .ndo_validate_addr = eth_validate_addr,
1038}; 1059};
1039 1060
@@ -1198,6 +1219,20 @@ err:
1198 return -ENOMEM; 1219 return -ENOMEM;
1199} 1220}
1200 1221
1222static void qede_sp_task(struct work_struct *work)
1223{
1224 struct qede_dev *edev = container_of(work, struct qede_dev,
1225 sp_task.work);
1226 mutex_lock(&edev->qede_lock);
1227
1228 if (edev->state == QEDE_STATE_OPEN) {
1229 if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags))
1230 qede_config_rx_mode(edev->ndev);
1231 }
1232
1233 mutex_unlock(&edev->qede_lock);
1234}
1235
1201static void qede_update_pf_params(struct qed_dev *cdev) 1236static void qede_update_pf_params(struct qed_dev *cdev)
1202{ 1237{
1203 struct qed_pf_params pf_params; 1238 struct qed_pf_params pf_params;
@@ -1269,6 +1304,9 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
1269 1304
1270 edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); 1305 edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION);
1271 1306
1307 INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task);
1308 mutex_init(&edev->qede_lock);
1309
1272 DP_INFO(edev, "Ending successfully qede probe\n"); 1310 DP_INFO(edev, "Ending successfully qede probe\n");
1273 1311
1274 return 0; 1312 return 0;
@@ -1306,6 +1344,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
1306 1344
1307 DP_INFO(edev, "Starting qede_remove\n"); 1345 DP_INFO(edev, "Starting qede_remove\n");
1308 1346
1347 cancel_delayed_work_sync(&edev->sp_task);
1309 unregister_netdev(ndev); 1348 unregister_netdev(ndev);
1310 1349
1311 edev->ops->common->set_power_state(cdev, PCI_D0); 1350 edev->ops->common->set_power_state(cdev, PCI_D0);
@@ -2036,6 +2075,24 @@ static int qede_start_queues(struct qede_dev *edev)
2036 return 0; 2075 return 0;
2037} 2076}
2038 2077
2078static int qede_set_mcast_rx_mac(struct qede_dev *edev,
2079 enum qed_filter_xcast_params_type opcode,
2080 unsigned char *mac, int num_macs)
2081{
2082 struct qed_filter_params filter_cmd;
2083 int i;
2084
2085 memset(&filter_cmd, 0, sizeof(filter_cmd));
2086 filter_cmd.type = QED_FILTER_TYPE_MCAST;
2087 filter_cmd.filter.mcast.type = opcode;
2088 filter_cmd.filter.mcast.num = num_macs;
2089
2090 for (i = 0; i < num_macs; i++, mac += ETH_ALEN)
2091 ether_addr_copy(filter_cmd.filter.mcast.mac[i], mac);
2092
2093 return edev->ops->filter_config(edev->cdev, &filter_cmd);
2094}
2095
2039enum qede_unload_mode { 2096enum qede_unload_mode {
2040 QEDE_UNLOAD_NORMAL, 2097 QEDE_UNLOAD_NORMAL,
2041}; 2098};
@@ -2046,6 +2103,9 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode)
2046 2103
2047 DP_INFO(edev, "Starting qede unload\n"); 2104 DP_INFO(edev, "Starting qede unload\n");
2048 2105
2106 mutex_lock(&edev->qede_lock);
2107 edev->state = QEDE_STATE_CLOSED;
2108
2049 /* Close OS Tx */ 2109 /* Close OS Tx */
2050 netif_tx_disable(edev->ndev); 2110 netif_tx_disable(edev->ndev);
2051 netif_carrier_off(edev->ndev); 2111 netif_carrier_off(edev->ndev);
@@ -2120,6 +2180,9 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode)
2120 /* Add primary mac and set Rx filters */ 2180 /* Add primary mac and set Rx filters */
2121 ether_addr_copy(edev->primary_mac, edev->ndev->dev_addr); 2181 ether_addr_copy(edev->primary_mac, edev->ndev->dev_addr);
2122 2182
2183 mutex_lock(&edev->qede_lock);
2184 edev->state = QEDE_STATE_OPEN;
2185 mutex_unlock(&edev->qede_lock);
2123 DP_INFO(edev, "Ending successfully qede load\n"); 2186 DP_INFO(edev, "Ending successfully qede load\n");
2124 2187
2125 return 0; 2188 return 0;
@@ -2159,3 +2222,181 @@ static int qede_close(struct net_device *ndev)
2159 2222
2160 return 0; 2223 return 0;
2161} 2224}
2225
2226static int qede_set_mac_addr(struct net_device *ndev, void *p)
2227{
2228 struct qede_dev *edev = netdev_priv(ndev);
2229 struct sockaddr *addr = p;
2230 int rc;
2231
2232 ASSERT_RTNL(); /* @@@TBD To be removed */
2233
2234 DP_INFO(edev, "Set_mac_addr called\n");
2235
2236 if (!is_valid_ether_addr(addr->sa_data)) {
2237 DP_NOTICE(edev, "The MAC address is not valid\n");
2238 return -EFAULT;
2239 }
2240
2241 ether_addr_copy(ndev->dev_addr, addr->sa_data);
2242
2243 if (!netif_running(ndev)) {
2244 DP_NOTICE(edev, "The device is currently down\n");
2245 return 0;
2246 }
2247
2248 /* Remove the previous primary mac */
2249 rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL,
2250 edev->primary_mac);
2251 if (rc)
2252 return rc;
2253
2254 /* Add MAC filter according to the new unicast HW MAC address */
2255 ether_addr_copy(edev->primary_mac, ndev->dev_addr);
2256 return qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD,
2257 edev->primary_mac);
2258}
2259
2260static int
2261qede_configure_mcast_filtering(struct net_device *ndev,
2262 enum qed_filter_rx_mode_type *accept_flags)
2263{
2264 struct qede_dev *edev = netdev_priv(ndev);
2265 unsigned char *mc_macs, *temp;
2266 struct netdev_hw_addr *ha;
2267 int rc = 0, mc_count;
2268 size_t size;
2269
2270 size = 64 * ETH_ALEN;
2271
2272 mc_macs = kzalloc(size, GFP_KERNEL);
2273 if (!mc_macs) {
2274 DP_NOTICE(edev,
2275 "Failed to allocate memory for multicast MACs\n");
2276 rc = -ENOMEM;
2277 goto exit;
2278 }
2279
2280 temp = mc_macs;
2281
2282 /* Remove all previously configured MAC filters */
2283 rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL,
2284 mc_macs, 1);
2285 if (rc)
2286 goto exit;
2287
2288 netif_addr_lock_bh(ndev);
2289
2290 mc_count = netdev_mc_count(ndev);
2291 if (mc_count < 64) {
2292 netdev_for_each_mc_addr(ha, ndev) {
2293 ether_addr_copy(temp, ha->addr);
2294 temp += ETH_ALEN;
2295 }
2296 }
2297
2298 netif_addr_unlock_bh(ndev);
2299
2300 /* Check for all multicast @@@TBD resource allocation */
2301 if ((ndev->flags & IFF_ALLMULTI) ||
2302 (mc_count > 64)) {
2303 if (*accept_flags == QED_FILTER_RX_MODE_TYPE_REGULAR)
2304 *accept_flags = QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC;
2305 } else {
2306 /* Add all multicast MAC filters */
2307 rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD,
2308 mc_macs, mc_count);
2309 }
2310
2311exit:
2312 kfree(mc_macs);
2313 return rc;
2314}
2315
2316static void qede_set_rx_mode(struct net_device *ndev)
2317{
2318 struct qede_dev *edev = netdev_priv(ndev);
2319
2320 DP_INFO(edev, "qede_set_rx_mode called\n");
2321
2322 if (edev->state != QEDE_STATE_OPEN) {
2323 DP_INFO(edev,
2324 "qede_set_rx_mode called while interface is down\n");
2325 } else {
2326 set_bit(QEDE_SP_RX_MODE, &edev->sp_flags);
2327 schedule_delayed_work(&edev->sp_task, 0);
2328 }
2329}
2330
2331/* Must be called with qede_lock held */
2332static void qede_config_rx_mode(struct net_device *ndev)
2333{
2334 enum qed_filter_rx_mode_type accept_flags = QED_FILTER_TYPE_UCAST;
2335 struct qede_dev *edev = netdev_priv(ndev);
2336 struct qed_filter_params rx_mode;
2337 unsigned char *uc_macs, *temp;
2338 struct netdev_hw_addr *ha;
2339 int rc, uc_count;
2340 size_t size;
2341
2342 netif_addr_lock_bh(ndev);
2343
2344 uc_count = netdev_uc_count(ndev);
2345 size = uc_count * ETH_ALEN;
2346
2347 uc_macs = kzalloc(size, GFP_ATOMIC);
2348 if (!uc_macs) {
2349 DP_NOTICE(edev, "Failed to allocate memory for unicast MACs\n");
2350 netif_addr_unlock_bh(ndev);
2351 return;
2352 }
2353
2354 temp = uc_macs;
2355 netdev_for_each_uc_addr(ha, ndev) {
2356 ether_addr_copy(temp, ha->addr);
2357 temp += ETH_ALEN;
2358 }
2359
2360 netif_addr_unlock_bh(ndev);
2361
2362 /* Configure the struct for the Rx mode */
2363 memset(&rx_mode, 0, sizeof(struct qed_filter_params));
2364 rx_mode.type = QED_FILTER_TYPE_RX_MODE;
2365
2366 /* Remove all previous unicast secondary macs and multicast macs
2367 * (configrue / leave the primary mac)
2368 */
2369 rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_REPLACE,
2370 edev->primary_mac);
2371 if (rc)
2372 goto out;
2373
2374 /* Check for promiscuous */
2375 if ((ndev->flags & IFF_PROMISC) ||
2376 (uc_count > 15)) { /* @@@TBD resource allocation - 1 */
2377 accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC;
2378 } else {
2379 /* Add MAC filters according to the unicast secondary macs */
2380 int i;
2381
2382 temp = uc_macs;
2383 for (i = 0; i < uc_count; i++) {
2384 rc = qede_set_ucast_rx_mac(edev,
2385 QED_FILTER_XCAST_TYPE_ADD,
2386 temp);
2387 if (rc)
2388 goto out;
2389
2390 temp += ETH_ALEN;
2391 }
2392
2393 rc = qede_configure_mcast_filtering(ndev, &accept_flags);
2394 if (rc)
2395 goto out;
2396 }
2397
2398 rx_mode.filter.accept_flags = accept_flags;
2399 edev->ops->filter_config(edev->cdev, &rx_mode);
2400out:
2401 kfree(uc_macs);
2402}