aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/qlogic
diff options
context:
space:
mode:
authorHimanshu Madhani <himanshu.madhani@qlogic.com>2013-03-12 05:02:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-13 05:35:05 -0400
commita520030e326a1267fba6babe685ad574174bde27 (patch)
tree3cb388606f065aa7da1bdfc0f47cd33787dd9771 /drivers/net/ethernet/qlogic
parent99eee14a14ec8bf36c0705a038fa8d00917fb679 (diff)
qlcnic: Implement flash sysfs callback for 83xx adapter
QLogic applications use these callbacks to perform o NIC Partitioning (NPAR) configuration and management o Diagnostic tests o Flash access and updates Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c12
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h8
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c253
3 files changed, 265 insertions, 8 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index c08fa20dd5f0..56c3676bdbfe 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -2272,7 +2272,7 @@ static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
2272 return 0; 2272 return 0;
2273} 2273}
2274 2274
2275static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter) 2275int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *adapter)
2276{ 2276{
2277 int ret; 2277 int ret;
2278 u32 cmd; 2278 u32 cmd;
@@ -2290,7 +2290,7 @@ static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)
2290 return 0; 2290 return 0;
2291} 2291}
2292 2292
2293static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter) 2293int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)
2294{ 2294{
2295 int ret; 2295 int ret;
2296 2296
@@ -2364,7 +2364,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
2364 return -EIO; 2364 return -EIO;
2365 2365
2366 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { 2366 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2367 ret = qlcnic_83xx_enable_flash_write_op(adapter); 2367 ret = qlcnic_83xx_enable_flash_write(adapter);
2368 if (ret) { 2368 if (ret) {
2369 qlcnic_83xx_unlock_flash(adapter); 2369 qlcnic_83xx_unlock_flash(adapter);
2370 dev_err(&adapter->pdev->dev, 2370 dev_err(&adapter->pdev->dev,
@@ -2406,7 +2406,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
2406 } 2406 }
2407 2407
2408 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { 2408 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
2409 ret = qlcnic_83xx_disable_flash_write_op(adapter); 2409 ret = qlcnic_83xx_disable_flash_write(adapter);
2410 if (ret) { 2410 if (ret) {
2411 qlcnic_83xx_unlock_flash(adapter); 2411 qlcnic_83xx_unlock_flash(adapter);
2412 dev_err(&adapter->pdev->dev, 2412 dev_err(&adapter->pdev->dev,
@@ -2446,8 +2446,8 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
2446 u32 temp; 2446 u32 temp;
2447 int ret = -EIO; 2447 int ret = -EIO;
2448 2448
2449 if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) || 2449 if ((count < QLC_83XX_FLASH_WRITE_MIN) ||
2450 (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) { 2450 (count > QLC_83XX_FLASH_WRITE_MAX)) {
2451 dev_err(&adapter->pdev->dev, 2451 dev_err(&adapter->pdev->dev,
2452 "%s: Invalid word count\n", __func__); 2452 "%s: Invalid word count\n", __func__);
2453 return -EIO; 2453 return -EIO;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 648a73f904ee..fbb3d1d9e55c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -12,6 +12,8 @@
12#include <linux/etherdevice.h> 12#include <linux/etherdevice.h>
13#include "qlcnic_hw.h" 13#include "qlcnic_hw.h"
14 14
15#define QLCNIC_83XX_BAR0_LENGTH 0x4000
16
15/* Directly mapped registers */ 17/* Directly mapped registers */
16#define QLC_83XX_CRB_WIN_BASE 0x3800 18#define QLC_83XX_CRB_WIN_BASE 0x3800
17#define QLC_83XX_CRB_WIN_FUNC(f) (QLC_83XX_CRB_WIN_BASE+((f)*4)) 19#define QLC_83XX_CRB_WIN_FUNC(f) (QLC_83XX_CRB_WIN_BASE+((f)*4))
@@ -257,8 +259,8 @@ struct qlc_83xx_idc {
257#define QLC_83XX_FLASH_BULK_WRITE_CMD 0xcadcadca 259#define QLC_83XX_FLASH_BULK_WRITE_CMD 0xcadcadca
258#define QLC_83XX_FLASH_READ_RETRY_COUNT 5000 260#define QLC_83XX_FLASH_READ_RETRY_COUNT 5000
259#define QLC_83XX_FLASH_STATUS_READY 0x6 261#define QLC_83XX_FLASH_STATUS_READY 0x6
260#define QLC_83XX_FLASH_BULK_WRITE_MIN 2 262#define QLC_83XX_FLASH_WRITE_MIN 2
261#define QLC_83XX_FLASH_BULK_WRITE_MAX 64 263#define QLC_83XX_FLASH_WRITE_MAX 64
262#define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY 1 264#define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY 1
263#define QLC_83XX_ERASE_MODE 1 265#define QLC_83XX_ERASE_MODE 1
264#define QLC_83XX_WRITE_MODE 2 266#define QLC_83XX_WRITE_MODE 2
@@ -451,4 +453,6 @@ int qlcnic_83xx_loopback_test(struct net_device *, u8);
451int qlcnic_83xx_interrupt_test(struct net_device *); 453int qlcnic_83xx_interrupt_test(struct net_device *);
452int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state); 454int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);
453int qlcnic_83xx_flash_test(struct qlcnic_adapter *); 455int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
456int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
457int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
454#endif 458#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 4e464dcfcb3f..c77675da671f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -884,6 +884,244 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
884 return size; 884 return size;
885} 885}
886 886
887static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
888 struct kobject *kobj,
889 struct bin_attribute *attr,
890 char *buf, loff_t offset,
891 size_t size)
892{
893 unsigned char *p_read_buf;
894 int ret, count;
895 struct device *dev = container_of(kobj, struct device, kobj);
896 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
897
898 if (!size)
899 return QL_STATUS_INVALID_PARAM;
900 if (!buf)
901 return QL_STATUS_INVALID_PARAM;
902
903 count = size / sizeof(u32);
904
905 if (size % sizeof(u32))
906 count++;
907
908 p_read_buf = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
909 if (!p_read_buf)
910 return -ENOMEM;
911 if (qlcnic_83xx_lock_flash(adapter) != 0) {
912 kfree(p_read_buf);
913 return -EIO;
914 }
915
916 ret = qlcnic_83xx_lockless_flash_read32(adapter, offset, p_read_buf,
917 count);
918
919 if (ret) {
920 qlcnic_83xx_unlock_flash(adapter);
921 kfree(p_read_buf);
922 return ret;
923 }
924
925 qlcnic_83xx_unlock_flash(adapter);
926 memcpy(buf, p_read_buf, size);
927 kfree(p_read_buf);
928
929 return size;
930}
931
932static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter,
933 char *buf, loff_t offset,
934 size_t size)
935{
936 int i, ret, count;
937 unsigned char *p_cache, *p_src;
938
939 p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
940 if (!p_cache)
941 return -ENOMEM;
942
943 memcpy(p_cache, buf, size);
944 p_src = p_cache;
945 count = size / sizeof(u32);
946
947 if (qlcnic_83xx_lock_flash(adapter) != 0) {
948 kfree(p_cache);
949 return -EIO;
950 }
951
952 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
953 ret = qlcnic_83xx_enable_flash_write(adapter);
954 if (ret) {
955 kfree(p_cache);
956 qlcnic_83xx_unlock_flash(adapter);
957 return -EIO;
958 }
959 }
960
961 for (i = 0; i < count / QLC_83XX_FLASH_WRITE_MAX; i++) {
962 ret = qlcnic_83xx_flash_bulk_write(adapter, offset,
963 (u32 *)p_src,
964 QLC_83XX_FLASH_WRITE_MAX);
965
966 if (ret) {
967 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
968 ret = qlcnic_83xx_disable_flash_write(adapter);
969 if (ret) {
970 kfree(p_cache);
971 qlcnic_83xx_unlock_flash(adapter);
972 return -EIO;
973 }
974 }
975
976 kfree(p_cache);
977 qlcnic_83xx_unlock_flash(adapter);
978 return -EIO;
979 }
980
981 p_src = p_src + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
982 offset = offset + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
983 }
984
985 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
986 ret = qlcnic_83xx_disable_flash_write(adapter);
987 if (ret) {
988 kfree(p_cache);
989 qlcnic_83xx_unlock_flash(adapter);
990 return -EIO;
991 }
992 }
993
994 kfree(p_cache);
995 qlcnic_83xx_unlock_flash(adapter);
996
997 return 0;
998}
999
1000static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
1001 char *buf, loff_t offset, size_t size)
1002{
1003 int i, ret, count;
1004 unsigned char *p_cache, *p_src;
1005
1006 p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
1007 if (!p_cache)
1008 return -ENOMEM;
1009
1010 memcpy(p_cache, buf, size);
1011 p_src = p_cache;
1012 count = size / sizeof(u32);
1013
1014 if (qlcnic_83xx_lock_flash(adapter) != 0) {
1015 kfree(p_cache);
1016 return -EIO;
1017 }
1018
1019 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1020 ret = qlcnic_83xx_enable_flash_write(adapter);
1021 if (ret) {
1022 kfree(p_cache);
1023 qlcnic_83xx_unlock_flash(adapter);
1024 return -EIO;
1025 }
1026 }
1027
1028 for (i = 0; i < count; i++) {
1029 ret = qlcnic_83xx_flash_write32(adapter, offset, (u32 *)p_src);
1030 if (ret) {
1031 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1032 ret = qlcnic_83xx_disable_flash_write(adapter);
1033 if (ret) {
1034 kfree(p_cache);
1035 qlcnic_83xx_unlock_flash(adapter);
1036 return -EIO;
1037 }
1038 }
1039 kfree(p_cache);
1040 qlcnic_83xx_unlock_flash(adapter);
1041 return -EIO;
1042 }
1043
1044 p_src = p_src + sizeof(u32);
1045 offset = offset + sizeof(u32);
1046 }
1047
1048 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1049 ret = qlcnic_83xx_disable_flash_write(adapter);
1050 if (ret) {
1051 kfree(p_cache);
1052 qlcnic_83xx_unlock_flash(adapter);
1053 return -EIO;
1054 }
1055 }
1056
1057 kfree(p_cache);
1058 qlcnic_83xx_unlock_flash(adapter);
1059
1060 return 0;
1061}
1062
1063static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
1064 struct kobject *kobj,
1065 struct bin_attribute *attr,
1066 char *buf, loff_t offset,
1067 size_t size)
1068{
1069 int ret;
1070 static int flash_mode;
1071 unsigned long data;
1072 struct device *dev = container_of(kobj, struct device, kobj);
1073 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
1074
1075 if (!buf)
1076 return QL_STATUS_INVALID_PARAM;
1077
1078 ret = kstrtoul(buf, 16, &data);
1079
1080 switch (data) {
1081 case QLC_83XX_FLASH_SECTOR_ERASE_CMD:
1082 flash_mode = QLC_83XX_ERASE_MODE;
1083 ret = qlcnic_83xx_erase_flash_sector(adapter, offset);
1084 if (ret) {
1085 dev_err(&adapter->pdev->dev,
1086 "%s failed at %d\n", __func__, __LINE__);
1087 return -EIO;
1088 }
1089 break;
1090
1091 case QLC_83XX_FLASH_BULK_WRITE_CMD:
1092 flash_mode = QLC_83XX_BULK_WRITE_MODE;
1093 break;
1094
1095 case QLC_83XX_FLASH_WRITE_CMD:
1096 flash_mode = QLC_83XX_WRITE_MODE;
1097 break;
1098 default:
1099 if (flash_mode == QLC_83XX_BULK_WRITE_MODE) {
1100 ret = qlcnic_83xx_sysfs_flash_bulk_write(adapter, buf,
1101 offset, size);
1102 if (ret) {
1103 dev_err(&adapter->pdev->dev,
1104 "%s failed at %d\n",
1105 __func__, __LINE__);
1106 return -EIO;
1107 }
1108 }
1109
1110 if (flash_mode == QLC_83XX_WRITE_MODE) {
1111 ret = qlcnic_83xx_sysfs_flash_write(adapter, buf,
1112 offset, size);
1113 if (ret) {
1114 dev_err(&adapter->pdev->dev,
1115 "%s failed at %d\n", __func__,
1116 __LINE__);
1117 return -EIO;
1118 }
1119 }
1120 }
1121
1122 return size;
1123}
1124
887static struct device_attribute dev_attr_bridged_mode = { 1125static struct device_attribute dev_attr_bridged_mode = {
888 .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, 1126 .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
889 .show = qlcnic_show_bridged_mode, 1127 .show = qlcnic_show_bridged_mode,
@@ -958,6 +1196,13 @@ static struct bin_attribute bin_attr_pm_config = {
958 .write = qlcnic_sysfs_write_pm_config, 1196 .write = qlcnic_sysfs_write_pm_config,
959}; 1197};
960 1198
1199static struct bin_attribute bin_attr_flash = {
1200 .attr = {.name = "flash", .mode = (S_IRUGO | S_IWUSR)},
1201 .size = 0,
1202 .read = qlcnic_83xx_sysfs_flash_read_handler,
1203 .write = qlcnic_83xx_sysfs_flash_write_handler,
1204};
1205
961void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) 1206void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
962{ 1207{
963 struct device *dev = &adapter->pdev->dev; 1208 struct device *dev = &adapter->pdev->dev;
@@ -1046,10 +1291,18 @@ void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)
1046 1291
1047void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter) 1292void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)
1048{ 1293{
1294 struct device *dev = &adapter->pdev->dev;
1295
1049 qlcnic_create_diag_entries(adapter); 1296 qlcnic_create_diag_entries(adapter);
1297
1298 if (sysfs_create_bin_file(&dev->kobj, &bin_attr_flash))
1299 dev_info(dev, "failed to create flash sysfs entry\n");
1050} 1300}
1051 1301
1052void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter) 1302void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)
1053{ 1303{
1304 struct device *dev = &adapter->pdev->dev;
1305
1054 qlcnic_remove_diag_entries(adapter); 1306 qlcnic_remove_diag_entries(adapter);
1307 sysfs_remove_bin_file(&dev->kobj, &bin_attr_flash);
1055} 1308}