aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-08-16 20:34:22 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-17 06:59:47 -0400
commitb6021212291d1eb1e7d1245bbd8c53bcbe2355d7 (patch)
treebc10d1a36a46aaa8e1646a644e77ecafa88a0f14 /drivers/net/qlcnic
parentecd7d31038e2e0e95b4596eec021e02ba67a0a37 (diff)
qlcnic: add eswitch statistics support
Adding eswitch statistics support. User can get whole eswitch stats or stats of func belong to that eswitch. Added: o command to get statistics of eswitch and function. o sysfs support to export eswitch and func statatistics. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic')
-rw-r--r--drivers/net/qlcnic/qlcnic.h31
-rw-r--r--drivers/net/qlcnic/qlcnic_ctx.c125
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c132
3 files changed, 287 insertions, 1 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 970389331bbc..7f4e11bd4cd4 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -555,6 +555,7 @@ struct qlcnic_recv_context {
555#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 555#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
556#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 556#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
557#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 557#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
558#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
558 559
559#define QLCNIC_RCODE_SUCCESS 0 560#define QLCNIC_RCODE_SUCCESS 0
560#define QLCNIC_RCODE_TIMEOUT 17 561#define QLCNIC_RCODE_TIMEOUT 17
@@ -1126,6 +1127,31 @@ struct qlcnic_esw_func_cfg {
1126 u8 reserved; 1127 u8 reserved;
1127}; 1128};
1128 1129
1130#define QLCNIC_STATS_VERSION 1
1131#define QLCNIC_STATS_PORT 1
1132#define QLCNIC_STATS_ESWITCH 2
1133#define QLCNIC_QUERY_RX_COUNTER 0
1134#define QLCNIC_QUERY_TX_COUNTER 1
1135struct __qlcnic_esw_statistics {
1136 __le16 context_id;
1137 __le16 version;
1138 __le16 size;
1139 __le16 unused;
1140 __le64 unicast_frames;
1141 __le64 multicast_frames;
1142 __le64 broadcast_frames;
1143 __le64 dropped_frames;
1144 __le64 errors;
1145 __le64 local_frames;
1146 __le64 numbytes;
1147 __le64 rsvd[3];
1148};
1149
1150struct qlcnic_esw_statistics {
1151 struct __qlcnic_esw_statistics rx;
1152 struct __qlcnic_esw_statistics tx;
1153};
1154
1129int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val); 1155int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
1130int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val); 1156int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val);
1131 1157
@@ -1252,6 +1278,11 @@ int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
1252int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8, 1278int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
1253 u8, u8, u16); 1279 u8, u8, u16);
1254int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); 1280int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
1281int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
1282 struct __qlcnic_esw_statistics *);
1283int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
1284 struct __qlcnic_esw_statistics *);
1285int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
1255extern int qlcnic_config_tso; 1286extern int qlcnic_config_tso;
1256 1287
1257/* 1288/*
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cc5d861d9a12..57c9b09bd16a 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -983,3 +983,128 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
983 983
984 return err; 984 return err;
985} 985}
986
987int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
988 const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
989
990 size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
991 dma_addr_t stats_dma_t;
992 void *stats_addr;
993 u32 arg1;
994 int err;
995
996 if (esw_stats == NULL)
997 return -ENOMEM;
998
999 if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
1000 func != adapter->ahw.pci_func) {
1001 dev_err(&adapter->pdev->dev,
1002 "Not privilege to query stats for func=%d", func);
1003 return -EIO;
1004 }
1005
1006 stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
1007 &stats_dma_t);
1008 if (!stats_addr) {
1009 dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
1010 return -ENOMEM;
1011 }
1012 memset(stats_addr, 0, stats_size);
1013
1014 arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
1015 arg1 |= rx_tx << 15 | stats_size << 16;
1016
1017 err = qlcnic_issue_cmd(adapter,
1018 adapter->ahw.pci_func,
1019 adapter->fw_hal_version,
1020 arg1,
1021 MSD(stats_dma_t),
1022 LSD(stats_dma_t),
1023 QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
1024
1025 if (!err)
1026 memcpy(esw_stats, stats_addr, stats_size);
1027
1028 pci_free_consistent(adapter->pdev, stats_size, stats_addr,
1029 stats_dma_t);
1030 return err;
1031}
1032
1033int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
1034 const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
1035
1036 struct __qlcnic_esw_statistics port_stats;
1037 u8 i;
1038 int ret = -EIO;
1039
1040 if (esw_stats == NULL)
1041 return -ENOMEM;
1042 if (adapter->op_mode != QLCNIC_MGMT_FUNC)
1043 return -EIO;
1044 if (adapter->npars == NULL)
1045 return -EIO;
1046
1047 memset(esw_stats, 0, sizeof(struct __qlcnic_esw_statistics));
1048 esw_stats->context_id = eswitch;
1049
1050 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
1051 if (adapter->npars[i].phy_port != eswitch)
1052 continue;
1053
1054 memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
1055 if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
1056 continue;
1057
1058 esw_stats->size = port_stats.size;
1059 esw_stats->version = port_stats.version;
1060 esw_stats->unicast_frames += port_stats.unicast_frames;
1061 esw_stats->multicast_frames += port_stats.multicast_frames;
1062 esw_stats->broadcast_frames += port_stats.broadcast_frames;
1063 esw_stats->dropped_frames += port_stats.dropped_frames;
1064 esw_stats->errors += port_stats.errors;
1065 esw_stats->local_frames += port_stats.local_frames;
1066 esw_stats->numbytes += port_stats.numbytes;
1067
1068 ret = 0;
1069 }
1070 return ret;
1071}
1072
1073int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
1074 const u8 port, const u8 rx_tx)
1075{
1076
1077 u32 arg1;
1078
1079 if (adapter->op_mode != QLCNIC_MGMT_FUNC)
1080 return -EIO;
1081
1082 if (func_esw == QLCNIC_STATS_PORT) {
1083 if (port >= QLCNIC_MAX_PCI_FUNC)
1084 goto err_ret;
1085 } else if (func_esw == QLCNIC_STATS_ESWITCH) {
1086 if (port >= QLCNIC_NIU_MAX_XG_PORTS)
1087 goto err_ret;
1088 } else {
1089 goto err_ret;
1090 }
1091
1092 if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
1093 goto err_ret;
1094
1095 arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
1096 arg1 |= BIT_14 | rx_tx << 15;
1097
1098 return qlcnic_issue_cmd(adapter,
1099 adapter->ahw.pci_func,
1100 adapter->fw_hal_version,
1101 arg1,
1102 0,
1103 0,
1104 QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
1105
1106err_ret:
1107 dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
1108 "rx_ctx=%d\n", func_esw, port, rx_tx);
1109 return -EIO;
1110}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 06ffd7637f87..a30bde52d40b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3378,6 +3378,115 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
3378} 3378}
3379 3379
3380static ssize_t 3380static ssize_t
3381qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
3382 struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
3383{
3384 struct device *dev = container_of(kobj, struct device, kobj);
3385 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
3386 struct qlcnic_esw_statistics port_stats;
3387 int ret;
3388
3389 if (size != sizeof(struct qlcnic_esw_statistics))
3390 return QL_STATUS_INVALID_PARAM;
3391
3392 if (offset >= QLCNIC_MAX_PCI_FUNC)
3393 return QL_STATUS_INVALID_PARAM;
3394
3395 memset(&port_stats, 0, size);
3396 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
3397 &port_stats.rx);
3398 if (ret)
3399 return ret;
3400
3401 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
3402 &port_stats.tx);
3403 if (ret)
3404 return ret;
3405
3406 memcpy(buf, &port_stats, size);
3407 return size;
3408}
3409
3410static ssize_t
3411qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
3412 struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
3413{
3414 struct device *dev = container_of(kobj, struct device, kobj);
3415 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
3416 struct qlcnic_esw_statistics esw_stats;
3417 int ret;
3418
3419 if (size != sizeof(struct qlcnic_esw_statistics))
3420 return QL_STATUS_INVALID_PARAM;
3421
3422 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
3423 return QL_STATUS_INVALID_PARAM;
3424
3425 memset(&esw_stats, 0, size);
3426 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
3427 &esw_stats.rx);
3428 if (ret)
3429 return ret;
3430
3431 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
3432 &esw_stats.tx);
3433 if (ret)
3434 return ret;
3435
3436 memcpy(buf, &esw_stats, size);
3437 return size;
3438}
3439
3440static ssize_t
3441qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
3442 struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
3443{
3444 struct device *dev = container_of(kobj, struct device, kobj);
3445 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
3446 int ret;
3447
3448 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
3449 return QL_STATUS_INVALID_PARAM;
3450
3451 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
3452 QLCNIC_QUERY_RX_COUNTER);
3453 if (ret)
3454 return ret;
3455
3456 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
3457 QLCNIC_QUERY_TX_COUNTER);
3458 if (ret)
3459 return ret;
3460
3461 return size;
3462}
3463
3464static ssize_t
3465qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
3466 struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
3467{
3468
3469 struct device *dev = container_of(kobj, struct device, kobj);
3470 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
3471 int ret;
3472
3473 if (offset >= QLCNIC_MAX_PCI_FUNC)
3474 return QL_STATUS_INVALID_PARAM;
3475
3476 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
3477 QLCNIC_QUERY_RX_COUNTER);
3478 if (ret)
3479 return ret;
3480
3481 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
3482 QLCNIC_QUERY_TX_COUNTER);
3483 if (ret)
3484 return ret;
3485
3486 return size;
3487}
3488
3489static ssize_t
3381qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, 3490qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
3382 struct bin_attribute *attr, char *buf, loff_t offset, size_t size) 3491 struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
3383{ 3492{
@@ -3426,6 +3535,20 @@ static struct bin_attribute bin_attr_pci_config = {
3426 .write = NULL, 3535 .write = NULL,
3427}; 3536};
3428 3537
3538static struct bin_attribute bin_attr_port_stats = {
3539 .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
3540 .size = 0,
3541 .read = qlcnic_sysfs_get_port_stats,
3542 .write = qlcnic_sysfs_clear_port_stats,
3543};
3544
3545static struct bin_attribute bin_attr_esw_stats = {
3546 .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
3547 .size = 0,
3548 .read = qlcnic_sysfs_get_esw_stats,
3549 .write = qlcnic_sysfs_clear_esw_stats,
3550};
3551
3429static struct bin_attribute bin_attr_esw_config = { 3552static struct bin_attribute bin_attr_esw_config = {
3430 .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, 3553 .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
3431 .size = 0, 3554 .size = 0,
@@ -3465,6 +3588,9 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
3465{ 3588{
3466 struct device *dev = &adapter->pdev->dev; 3589 struct device *dev = &adapter->pdev->dev;
3467 3590
3591 if (device_create_bin_file(dev, &bin_attr_port_stats))
3592 dev_info(dev, "failed to create port stats sysfs entry");
3593
3468 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) 3594 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
3469 return; 3595 return;
3470 if (device_create_file(dev, &dev_attr_diag_mode)) 3596 if (device_create_file(dev, &dev_attr_diag_mode))
@@ -3484,7 +3610,8 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
3484 dev_info(dev, "failed to create esw config sysfs entry"); 3610 dev_info(dev, "failed to create esw config sysfs entry");
3485 if (device_create_bin_file(dev, &bin_attr_pm_config)) 3611 if (device_create_bin_file(dev, &bin_attr_pm_config))
3486 dev_info(dev, "failed to create pm config sysfs entry"); 3612 dev_info(dev, "failed to create pm config sysfs entry");
3487 3613 if (device_create_bin_file(dev, &bin_attr_esw_stats))
3614 dev_info(dev, "failed to create eswitch stats sysfs entry");
3488} 3615}
3489 3616
3490static void 3617static void
@@ -3492,6 +3619,8 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
3492{ 3619{
3493 struct device *dev = &adapter->pdev->dev; 3620 struct device *dev = &adapter->pdev->dev;
3494 3621
3622 device_remove_bin_file(dev, &bin_attr_port_stats);
3623
3495 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) 3624 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
3496 return; 3625 return;
3497 device_remove_file(dev, &dev_attr_diag_mode); 3626 device_remove_file(dev, &dev_attr_diag_mode);
@@ -3504,6 +3633,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
3504 device_remove_bin_file(dev, &bin_attr_npar_config); 3633 device_remove_bin_file(dev, &bin_attr_npar_config);
3505 device_remove_bin_file(dev, &bin_attr_esw_config); 3634 device_remove_bin_file(dev, &bin_attr_esw_config);
3506 device_remove_bin_file(dev, &bin_attr_pm_config); 3635 device_remove_bin_file(dev, &bin_attr_pm_config);
3636 device_remove_bin_file(dev, &bin_attr_esw_stats);
3507} 3637}
3508 3638
3509#ifdef CONFIG_INET 3639#ifdef CONFIG_INET