aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_main.c
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2010-06-01 07:28:51 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-02 05:24:03 -0400
commit2e9d722db6617ed10204bfa9cd60552620592a43 (patch)
treeda905f18459e55a8cb534d757f5b14a3e9da73d5 /drivers/net/qlcnic/qlcnic_main.c
parentdd8f61d7ff92eb8a4626565ca37b209b3a8a9ce2 (diff)
qlcnic: NIC Partitioning - Add basic infrastructure support
Following changes have been added to enable the adapter to work in NIC partitioning mode where multiple PCI functions of an adapter port can be configured to work as NIC functions. The first function that is enumerated on the PCI bus assumes the role of management function which, besides being able to do all the NIC functionality, can configure other NIC partitions. Other NIC functions can be configured as privileged or non privileged functions. Privileged function can not configure other NIC functions but can do all the NIC functionality including any firmware initialization, chip reset etc. Non privileged functions can do only basic IO. For chip reset etc, it depends on the privilege or management function. 1. Added code to determine PCI function number independent of kernel API. 2. Added Driver - FW version 2.0 support. 3. Changed producer and consumer register offset calculation. 4. Added management and privileged operation modes for npar functions. A module parameter has been added to control it. 5. Added support for configuring the eswitch in the adapter. Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c195
1 files changed, 173 insertions, 22 deletions
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 23ea9caa5261..1e5e66facabd 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -65,6 +65,10 @@ static int load_fw_file;
65module_param(load_fw_file, int, 0644); 65module_param(load_fw_file, int, 0644);
66MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); 66MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
67 67
68static int qlcnic_config_npars;
69module_param(qlcnic_config_npars, int, 0644);
70MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
71
68static int __devinit qlcnic_probe(struct pci_dev *pdev, 72static int __devinit qlcnic_probe(struct pci_dev *pdev,
69 const struct pci_device_id *ent); 73 const struct pci_device_id *ent);
70static void __devexit qlcnic_remove(struct pci_dev *pdev); 74static void __devexit qlcnic_remove(struct pci_dev *pdev);
@@ -307,19 +311,14 @@ static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count)
307static int 311static int
308qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) 312qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
309{ 313{
310 int i; 314 u8 mac_addr[ETH_ALEN];
311 unsigned char *p;
312 u64 mac_addr;
313 struct net_device *netdev = adapter->netdev; 315 struct net_device *netdev = adapter->netdev;
314 struct pci_dev *pdev = adapter->pdev; 316 struct pci_dev *pdev = adapter->pdev;
315 317
316 if (qlcnic_get_mac_addr(adapter, &mac_addr) != 0) 318 if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
317 return -EIO; 319 return -EIO;
318 320
319 p = (unsigned char *)&mac_addr; 321 memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
320 for (i = 0; i < 6; i++)
321 netdev->dev_addr[i] = *(p + 5 - i);
322
323 memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); 322 memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
324 memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); 323 memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);
325 324
@@ -371,6 +370,22 @@ static const struct net_device_ops qlcnic_netdev_ops = {
371#endif 370#endif
372}; 371};
373 372
373static struct qlcnic_nic_template qlcnic_ops = {
374 .get_mac_addr = qlcnic_get_mac_addr,
375 .config_bridged_mode = qlcnic_config_bridged_mode,
376 .config_led = qlcnic_config_led,
377 .set_ilb_mode = qlcnic_set_ilb_mode,
378 .clear_ilb_mode = qlcnic_clear_ilb_mode
379};
380
381static struct qlcnic_nic_template qlcnic_pf_ops = {
382 .get_mac_addr = qlcnic_get_mac_address,
383 .config_bridged_mode = qlcnic_config_bridged_mode,
384 .config_led = qlcnic_config_led,
385 .set_ilb_mode = qlcnic_set_ilb_mode,
386 .clear_ilb_mode = qlcnic_clear_ilb_mode
387};
388
374static void 389static void
375qlcnic_setup_intr(struct qlcnic_adapter *adapter) 390qlcnic_setup_intr(struct qlcnic_adapter *adapter)
376{ 391{
@@ -452,6 +467,125 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
452 iounmap(adapter->ahw.pci_base0); 467 iounmap(adapter->ahw.pci_base0);
453} 468}
454 469
470/* Use api lock to access this function */
471static int
472qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
473{
474 u8 id;
475 u32 ref_count;
476 int i, ret = 1;
477 u32 data = QLCNIC_MGMT_FUNC;
478 void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
479
480 /* If other drivers are not in use set their privilege level */
481 ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
482 ret = qlcnic_api_lock(adapter);
483 if (ret)
484 goto err_lock;
485 if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
486 goto err_npar;
487
488 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
489 id = adapter->npars[i].id;
490 if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
491 id == adapter->ahw.pci_func)
492 continue;
493 data |= (qlcnic_config_npars & QLC_DEV_SET_DRV(0xf, id));
494 }
495 writel(data, priv_op);
496
497err_npar:
498 qlcnic_api_unlock(adapter);
499err_lock:
500 return ret;
501}
502
503static u8
504qlcnic_set_mgmt_driver(struct qlcnic_adapter *adapter)
505{
506 u8 i, ret = 0;
507
508 if (qlcnic_get_pci_info(adapter))
509 return ret;
510 /* Set the eswitch */
511 for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) {
512 if (!qlcnic_get_eswitch_capabilities(adapter, i,
513 &adapter->eswitch[i])) {
514 ret++;
515 qlcnic_toggle_eswitch(adapter, i, ret);
516 }
517 }
518 return ret;
519}
520
521static u32
522qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
523{
524 void __iomem *msix_base_addr;
525 void __iomem *priv_op;
526 u32 func;
527 u32 msix_base;
528 u32 op_mode, priv_level;
529
530 /* Determine FW API version */
531 adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API);
532 if (adapter->fw_hal_version == ~0) {
533 adapter->nic_ops = &qlcnic_ops;
534 adapter->fw_hal_version = QLCNIC_FW_BASE;
535 adapter->ahw.pci_func = PCI_FUNC(adapter->pdev->devfn);
536 dev_info(&adapter->pdev->dev,
537 "FW does not support nic partion\n");
538 return adapter->fw_hal_version;
539 }
540
541 /* Find PCI function number */
542 pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
543 msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE;
544 msix_base = readl(msix_base_addr);
545 func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
546 adapter->ahw.pci_func = func;
547
548 /* Determine function privilege level */
549 priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
550 op_mode = readl(priv_op);
551 if (op_mode == QLC_DEV_DRV_DEFAULT) {
552 priv_level = QLCNIC_MGMT_FUNC;
553 if (qlcnic_api_lock(adapter))
554 return 0;
555 op_mode = (op_mode & ~QLC_DEV_SET_DRV(0xf, func)) |
556 (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, func));
557 writel(op_mode, priv_op);
558 qlcnic_api_unlock(adapter);
559
560 } else
561 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
562
563 switch (priv_level) {
564 case QLCNIC_MGMT_FUNC:
565 adapter->op_mode = QLCNIC_MGMT_FUNC;
566 adapter->nic_ops = &qlcnic_pf_ops;
567 /* Set privilege level for other functions */
568 if (qlcnic_config_npars)
569 qlcnic_set_function_modes(adapter);
570 dev_info(&adapter->pdev->dev,
571 "HAL Version: %d, Management function\n",
572 adapter->fw_hal_version);
573 break;
574 case QLCNIC_PRIV_FUNC:
575 adapter->op_mode = QLCNIC_PRIV_FUNC;
576 dev_info(&adapter->pdev->dev,
577 "HAL Version: %d, Privileged function\n",
578 adapter->fw_hal_version);
579 adapter->nic_ops = &qlcnic_pf_ops;
580 break;
581 default:
582 dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
583 priv_level);
584 return 0;
585 }
586 return adapter->fw_hal_version;
587}
588
455static int 589static int
456qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) 590qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
457{ 591{
@@ -460,7 +594,6 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
460 unsigned long mem_len, pci_len0 = 0; 594 unsigned long mem_len, pci_len0 = 0;
461 595
462 struct pci_dev *pdev = adapter->pdev; 596 struct pci_dev *pdev = adapter->pdev;
463 int pci_func = adapter->ahw.pci_func;
464 597
465 /* remap phys address */ 598 /* remap phys address */
466 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ 599 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
@@ -483,8 +616,13 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
483 adapter->ahw.pci_base0 = mem_ptr0; 616 adapter->ahw.pci_base0 = mem_ptr0;
484 adapter->ahw.pci_len0 = pci_len0; 617 adapter->ahw.pci_len0 = pci_len0;
485 618
619 if (!qlcnic_get_driver_mode(adapter)) {
620 iounmap(adapter->ahw.pci_base0);
621 return -EIO;
622 }
623
486 adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, 624 adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
487 QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func))); 625 QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
488 626
489 return 0; 627 return 0;
490} 628}
@@ -553,7 +691,10 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
553 dev_info(&pdev->dev, "firmware v%d.%d.%d\n", 691 dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
554 fw_major, fw_minor, fw_build); 692 fw_major, fw_minor, fw_build);
555 693
556 adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1); 694 if (adapter->fw_hal_version == QLCNIC_FW_NPAR)
695 qlcnic_get_nic_info(adapter, adapter->ahw.pci_func);
696 else
697 adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1);
557 698
558 adapter->flags &= ~QLCNIC_LRO_ENABLED; 699 adapter->flags &= ~QLCNIC_LRO_ENABLED;
559 700
@@ -633,6 +774,10 @@ wait_init:
633 774
634 qlcnic_check_options(adapter); 775 qlcnic_check_options(adapter);
635 776
777 if (adapter->fw_hal_version != QLCNIC_FW_BASE &&
778 adapter->op_mode == QLCNIC_MGMT_FUNC)
779 qlcnic_set_mgmt_driver(adapter);
780
636 adapter->need_fw_reset = 0; 781 adapter->need_fw_reset = 0;
637 782
638 qlcnic_release_firmware(adapter); 783 qlcnic_release_firmware(adapter);
@@ -977,12 +1122,11 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
977 1122
978 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); 1123 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
979 1124
980 netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); 1125 netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
981 netdev->features |= (NETIF_F_GRO); 1126 NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6);
982 netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
983 1127
984 netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); 1128 netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
985 netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); 1129 NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6);
986 1130
987 if (pci_using_dac) { 1131 if (pci_using_dac) {
988 netdev->features |= NETIF_F_HIGHDMA; 1132 netdev->features |= NETIF_F_HIGHDMA;
@@ -1036,7 +1180,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1036 struct net_device *netdev = NULL; 1180 struct net_device *netdev = NULL;
1037 struct qlcnic_adapter *adapter = NULL; 1181 struct qlcnic_adapter *adapter = NULL;
1038 int err; 1182 int err;
1039 int pci_func_id = PCI_FUNC(pdev->devfn);
1040 uint8_t revision_id; 1183 uint8_t revision_id;
1041 uint8_t pci_using_dac; 1184 uint8_t pci_using_dac;
1042 1185
@@ -1072,7 +1215,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1072 adapter->netdev = netdev; 1215 adapter->netdev = netdev;
1073 adapter->pdev = pdev; 1216 adapter->pdev = pdev;
1074 adapter->dev_rst_time = jiffies; 1217 adapter->dev_rst_time = jiffies;
1075 adapter->ahw.pci_func = pci_func_id;
1076 1218
1077 revision_id = pdev->revision; 1219 revision_id = pdev->revision;
1078 adapter->ahw.revision_id = revision_id; 1220 adapter->ahw.revision_id = revision_id;
@@ -1088,7 +1230,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1088 goto err_out_free_netdev; 1230 goto err_out_free_netdev;
1089 1231
1090 /* This will be reset for mezz cards */ 1232 /* This will be reset for mezz cards */
1091 adapter->portnum = pci_func_id; 1233 adapter->portnum = adapter->ahw.pci_func;
1092 1234
1093 err = qlcnic_get_board_info(adapter); 1235 err = qlcnic_get_board_info(adapter);
1094 if (err) { 1236 if (err) {
@@ -1175,6 +1317,11 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
1175 1317
1176 qlcnic_detach(adapter); 1318 qlcnic_detach(adapter);
1177 1319
1320 if (adapter->npars != NULL)
1321 kfree(adapter->npars);
1322 if (adapter->eswitch != NULL)
1323 kfree(adapter->eswitch);
1324
1178 qlcnic_clr_all_drv_state(adapter); 1325 qlcnic_clr_all_drv_state(adapter);
1179 1326
1180 clear_bit(__QLCNIC_RESETTING, &adapter->state); 1327 clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1340,11 +1487,11 @@ qlcnic_tso_check(struct net_device *netdev,
1340 u8 opcode = TX_ETHER_PKT; 1487 u8 opcode = TX_ETHER_PKT;
1341 __be16 protocol = skb->protocol; 1488 __be16 protocol = skb->protocol;
1342 u16 flags = 0, vid = 0; 1489 u16 flags = 0, vid = 0;
1343 u32 producer;
1344 int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; 1490 int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
1345 struct cmd_desc_type0 *hwdesc; 1491 struct cmd_desc_type0 *hwdesc;
1346 struct vlan_ethhdr *vh; 1492 struct vlan_ethhdr *vh;
1347 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1493 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1494 u32 producer = tx_ring->producer;
1348 1495
1349 if (protocol == cpu_to_be16(ETH_P_8021Q)) { 1496 if (protocol == cpu_to_be16(ETH_P_8021Q)) {
1350 1497
@@ -1360,6 +1507,11 @@ qlcnic_tso_check(struct net_device *netdev,
1360 vlan_oob = 1; 1507 vlan_oob = 1;
1361 } 1508 }
1362 1509
1510 if (*(skb->data) & BIT_0) {
1511 flags |= BIT_0;
1512 memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
1513 }
1514
1363 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && 1515 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
1364 skb_shinfo(skb)->gso_size > 0) { 1516 skb_shinfo(skb)->gso_size > 0) {
1365 1517
@@ -1409,7 +1561,6 @@ qlcnic_tso_check(struct net_device *netdev,
1409 /* For LSO, we need to copy the MAC/IP/TCP headers into 1561 /* For LSO, we need to copy the MAC/IP/TCP headers into
1410 * the descriptor ring 1562 * the descriptor ring
1411 */ 1563 */
1412 producer = tx_ring->producer;
1413 copied = 0; 1564 copied = 0;
1414 offset = 2; 1565 offset = 2;
1415 1566
@@ -2382,7 +2533,7 @@ qlcnic_store_bridged_mode(struct device *dev,
2382 if (strict_strtoul(buf, 2, &new)) 2533 if (strict_strtoul(buf, 2, &new))
2383 goto err_out; 2534 goto err_out;
2384 2535
2385 if (!qlcnic_config_bridged_mode(adapter, !!new)) 2536 if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
2386 ret = len; 2537 ret = len;
2387 2538
2388err_out: 2539err_out: