root/drivers/net/wireless/marvell/mwifiex/debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mwifiex_info_read
  2. mwifiex_getlog_read
  3. mwifiex_histogram_read
  4. mwifiex_histogram_write
  5. mwifiex_debug_read
  6. mwifiex_regrdwr_write
  7. mwifiex_regrdwr_read
  8. mwifiex_debug_mask_read
  9. mwifiex_debug_mask_write
  10. mwifiex_verext_write
  11. mwifiex_verext_read
  12. mwifiex_memrw_write
  13. mwifiex_memrw_read
  14. mwifiex_rdeeprom_write
  15. mwifiex_rdeeprom_read
  16. mwifiex_hscfg_write
  17. mwifiex_hscfg_read
  18. mwifiex_timeshare_coex_read
  19. mwifiex_timeshare_coex_write
  20. mwifiex_reset_write
  21. mwifiex_dev_debugfs_init
  22. mwifiex_dev_debugfs_remove
  23. mwifiex_debugfs_init
  24. mwifiex_debugfs_remove

   1 /*
   2  * Marvell Wireless LAN device driver: debugfs
   3  *
   4  * Copyright (C) 2011-2014, Marvell International Ltd.
   5  *
   6  * This software file (the "File") is distributed by Marvell International
   7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8  * (the "License").  You may use, redistribute and/or modify this File in
   9  * accordance with the terms and conditions of the License, a copy of which
  10  * is available by writing to the Free Software Foundation, Inc.,
  11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13  *
  14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  17  * this warranty disclaimer.
  18  */
  19 
  20 #include <linux/debugfs.h>
  21 
  22 #include "main.h"
  23 #include "11n.h"
  24 
  25 
  26 static struct dentry *mwifiex_dfs_dir;
  27 
  28 static char *bss_modes[] = {
  29         "UNSPECIFIED",
  30         "ADHOC",
  31         "STATION",
  32         "AP",
  33         "AP_VLAN",
  34         "WDS",
  35         "MONITOR",
  36         "MESH_POINT",
  37         "P2P_CLIENT",
  38         "P2P_GO",
  39         "P2P_DEVICE",
  40 };
  41 
  42 /*
  43  * Proc info file read handler.
  44  *
  45  * This function is called when the 'info' file is opened for reading.
  46  * It prints the following driver related information -
  47  *      - Driver name
  48  *      - Driver version
  49  *      - Driver extended version
  50  *      - Interface name
  51  *      - BSS mode
  52  *      - Media state (connected or disconnected)
  53  *      - MAC address
  54  *      - Total number of Tx bytes
  55  *      - Total number of Rx bytes
  56  *      - Total number of Tx packets
  57  *      - Total number of Rx packets
  58  *      - Total number of dropped Tx packets
  59  *      - Total number of dropped Rx packets
  60  *      - Total number of corrupted Tx packets
  61  *      - Total number of corrupted Rx packets
  62  *      - Carrier status (on or off)
  63  *      - Tx queue status (started or stopped)
  64  *
  65  * For STA mode drivers, it also prints the following extra -
  66  *      - ESSID
  67  *      - BSSID
  68  *      - Channel
  69  *      - Region code
  70  *      - Multicast count
  71  *      - Multicast addresses
  72  */
  73 static ssize_t
  74 mwifiex_info_read(struct file *file, char __user *ubuf,
  75                   size_t count, loff_t *ppos)
  76 {
  77         struct mwifiex_private *priv =
  78                 (struct mwifiex_private *) file->private_data;
  79         struct net_device *netdev = priv->netdev;
  80         struct netdev_hw_addr *ha;
  81         struct netdev_queue *txq;
  82         unsigned long page = get_zeroed_page(GFP_KERNEL);
  83         char *p = (char *) page, fmt[64];
  84         struct mwifiex_bss_info info;
  85         ssize_t ret;
  86         int i = 0;
  87 
  88         if (!p)
  89                 return -ENOMEM;
  90 
  91         memset(&info, 0, sizeof(info));
  92         ret = mwifiex_get_bss_info(priv, &info);
  93         if (ret)
  94                 goto free_and_exit;
  95 
  96         mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
  97 
  98         mwifiex_get_ver_ext(priv, 0);
  99 
 100         p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
 101         p += sprintf(p, "driver_version = %s", fmt);
 102         p += sprintf(p, "\nverext = %s", priv->version_str);
 103         p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
 104 
 105         if (info.bss_mode >= ARRAY_SIZE(bss_modes))
 106                 p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
 107         else
 108                 p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
 109 
 110         p += sprintf(p, "media_state=\"%s\"\n",
 111                      (!priv->media_connected ? "Disconnected" : "Connected"));
 112         p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
 113 
 114         if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
 115                 p += sprintf(p, "multicast_count=\"%d\"\n",
 116                              netdev_mc_count(netdev));
 117                 p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
 118                              info.ssid.ssid);
 119                 p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
 120                 p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
 121                 p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
 122                 p += sprintf(p, "region_code=\"0x%x\"\n",
 123                              priv->adapter->region_code);
 124 
 125                 netdev_for_each_mc_addr(ha, netdev)
 126                         p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
 127                                         i++, ha->addr);
 128         }
 129 
 130         p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
 131         p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
 132         p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
 133         p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
 134         p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
 135         p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
 136         p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
 137         p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
 138         p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
 139                                          ? "on" : "off"));
 140         p += sprintf(p, "tx queue");
 141         for (i = 0; i < netdev->num_tx_queues; i++) {
 142                 txq = netdev_get_tx_queue(netdev, i);
 143                 p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
 144                              "stopped" : "started");
 145         }
 146         p += sprintf(p, "\n");
 147 
 148         ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
 149                                       (unsigned long) p - page);
 150 
 151 free_and_exit:
 152         free_page(page);
 153         return ret;
 154 }
 155 
 156 /*
 157  * Proc getlog file read handler.
 158  *
 159  * This function is called when the 'getlog' file is opened for reading
 160  * It prints the following log information -
 161  *      - Number of multicast Tx frames
 162  *      - Number of failed packets
 163  *      - Number of Tx retries
 164  *      - Number of multicast Tx retries
 165  *      - Number of duplicate frames
 166  *      - Number of RTS successes
 167  *      - Number of RTS failures
 168  *      - Number of ACK failures
 169  *      - Number of fragmented Rx frames
 170  *      - Number of multicast Rx frames
 171  *      - Number of FCS errors
 172  *      - Number of Tx frames
 173  *      - WEP ICV error counts
 174  *      - Number of received beacons
 175  *      - Number of missed beacons
 176  */
 177 static ssize_t
 178 mwifiex_getlog_read(struct file *file, char __user *ubuf,
 179                     size_t count, loff_t *ppos)
 180 {
 181         struct mwifiex_private *priv =
 182                 (struct mwifiex_private *) file->private_data;
 183         unsigned long page = get_zeroed_page(GFP_KERNEL);
 184         char *p = (char *) page;
 185         ssize_t ret;
 186         struct mwifiex_ds_get_stats stats;
 187 
 188         if (!p)
 189                 return -ENOMEM;
 190 
 191         memset(&stats, 0, sizeof(stats));
 192         ret = mwifiex_get_stats_info(priv, &stats);
 193         if (ret)
 194                 goto free_and_exit;
 195 
 196         p += sprintf(p, "\n"
 197                      "mcasttxframe     %u\n"
 198                      "failed           %u\n"
 199                      "retry            %u\n"
 200                      "multiretry       %u\n"
 201                      "framedup         %u\n"
 202                      "rtssuccess       %u\n"
 203                      "rtsfailure       %u\n"
 204                      "ackfailure       %u\n"
 205                      "rxfrag           %u\n"
 206                      "mcastrxframe     %u\n"
 207                      "fcserror         %u\n"
 208                      "txframe          %u\n"
 209                      "wepicverrcnt-1   %u\n"
 210                      "wepicverrcnt-2   %u\n"
 211                      "wepicverrcnt-3   %u\n"
 212                      "wepicverrcnt-4   %u\n"
 213                      "bcn_rcv_cnt   %u\n"
 214                      "bcn_miss_cnt   %u\n",
 215                      stats.mcast_tx_frame,
 216                      stats.failed,
 217                      stats.retry,
 218                      stats.multi_retry,
 219                      stats.frame_dup,
 220                      stats.rts_success,
 221                      stats.rts_failure,
 222                      stats.ack_failure,
 223                      stats.rx_frag,
 224                      stats.mcast_rx_frame,
 225                      stats.fcs_error,
 226                      stats.tx_frame,
 227                      stats.wep_icv_error[0],
 228                      stats.wep_icv_error[1],
 229                      stats.wep_icv_error[2],
 230                      stats.wep_icv_error[3],
 231                      stats.bcn_rcv_cnt,
 232                      stats.bcn_miss_cnt);
 233 
 234 
 235         ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
 236                                       (unsigned long) p - page);
 237 
 238 free_and_exit:
 239         free_page(page);
 240         return ret;
 241 }
 242 
 243 /* Sysfs histogram file read handler.
 244  *
 245  * This function is called when the 'histogram' file is opened for reading
 246  * It prints the following histogram information -
 247  *      - Number of histogram samples
 248  *      - Receive packet number of each rx_rate
 249  *      - Receive packet number of each snr
 250  *      - Receive packet number of each nosie_flr
 251  *      - Receive packet number of each signal streath
 252  */
 253 static ssize_t
 254 mwifiex_histogram_read(struct file *file, char __user *ubuf,
 255                        size_t count, loff_t *ppos)
 256 {
 257         struct mwifiex_private *priv =
 258                 (struct mwifiex_private *)file->private_data;
 259         ssize_t ret;
 260         struct mwifiex_histogram_data *phist_data;
 261         int i, value;
 262         unsigned long page = get_zeroed_page(GFP_KERNEL);
 263         char *p = (char *)page;
 264 
 265         if (!p)
 266                 return -ENOMEM;
 267 
 268         if (!priv || !priv->hist_data)
 269                 return -EFAULT;
 270         phist_data = priv->hist_data;
 271 
 272         p += sprintf(p, "\n"
 273                      "total samples = %d\n",
 274                      atomic_read(&phist_data->num_samples));
 275 
 276         p += sprintf(p,
 277                      "rx rates (in Mbps): 0=1M   1=2M 2=5.5M  3=11M   4=6M   5=9M  6=12M\n"
 278                      "7=18M  8=24M  9=36M  10=48M  11=54M 12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n");
 279 
 280         if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
 281                 p += sprintf(p,
 282                              "44-53=MCS0-9(VHT:BW20) 54-63=MCS0-9(VHT:BW40) 64-73=MCS0-9(VHT:BW80)\n\n");
 283         } else {
 284                 p += sprintf(p, "\n");
 285         }
 286 
 287         for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) {
 288                 value = atomic_read(&phist_data->rx_rate[i]);
 289                 if (value)
 290                         p += sprintf(p, "rx_rate[%02d] = %d\n", i, value);
 291         }
 292 
 293         if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
 294                 for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES;
 295                      i++) {
 296                         value = atomic_read(&phist_data->rx_rate[i]);
 297                         if (value)
 298                                 p += sprintf(p, "rx_rate[%02d] = %d\n",
 299                                            i, value);
 300                 }
 301         }
 302 
 303         for (i = 0; i < MWIFIEX_MAX_SNR; i++) {
 304                 value =  atomic_read(&phist_data->snr[i]);
 305                 if (value)
 306                         p += sprintf(p, "snr[%02ddB] = %d\n", i, value);
 307         }
 308         for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) {
 309                 value = atomic_read(&phist_data->noise_flr[i]);
 310                 if (value)
 311                         p += sprintf(p, "noise_flr[%02ddBm] = %d\n",
 312                                 (int)(i-128), value);
 313         }
 314         for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) {
 315                 value = atomic_read(&phist_data->sig_str[i]);
 316                 if (value)
 317                         p += sprintf(p, "sig_strength[-%02ddBm] = %d\n",
 318                                 i, value);
 319         }
 320 
 321         ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
 322                                       (unsigned long)p - page);
 323 
 324         return ret;
 325 }
 326 
 327 static ssize_t
 328 mwifiex_histogram_write(struct file *file, const char __user *ubuf,
 329                         size_t count, loff_t *ppos)
 330 {
 331         struct mwifiex_private *priv = (void *)file->private_data;
 332 
 333         if (priv && priv->hist_data)
 334                 mwifiex_hist_data_reset(priv);
 335         return 0;
 336 }
 337 
 338 static struct mwifiex_debug_info info;
 339 
 340 /*
 341  * Proc debug file read handler.
 342  *
 343  * This function is called when the 'debug' file is opened for reading
 344  * It prints the following log information -
 345  *      - Interrupt count
 346  *      - WMM AC VO packets count
 347  *      - WMM AC VI packets count
 348  *      - WMM AC BE packets count
 349  *      - WMM AC BK packets count
 350  *      - Maximum Tx buffer size
 351  *      - Tx buffer size
 352  *      - Current Tx buffer size
 353  *      - Power Save mode
 354  *      - Power Save state
 355  *      - Deep Sleep status
 356  *      - Device wakeup required status
 357  *      - Number of wakeup tries
 358  *      - Host Sleep configured status
 359  *      - Host Sleep activated status
 360  *      - Number of Tx timeouts
 361  *      - Number of command timeouts
 362  *      - Last timed out command ID
 363  *      - Last timed out command action
 364  *      - Last command ID
 365  *      - Last command action
 366  *      - Last command index
 367  *      - Last command response ID
 368  *      - Last command response index
 369  *      - Last event
 370  *      - Last event index
 371  *      - Number of host to card command failures
 372  *      - Number of sleep confirm command failures
 373  *      - Number of host to card data failure
 374  *      - Number of deauthentication events
 375  *      - Number of disassociation events
 376  *      - Number of link lost events
 377  *      - Number of deauthentication commands
 378  *      - Number of association success commands
 379  *      - Number of association failure commands
 380  *      - Number of commands sent
 381  *      - Number of data packets sent
 382  *      - Number of command responses received
 383  *      - Number of events received
 384  *      - Tx BA stream table (TID, RA)
 385  *      - Rx reorder table (TID, TA, Start window, Window size, Buffer)
 386  */
 387 static ssize_t
 388 mwifiex_debug_read(struct file *file, char __user *ubuf,
 389                    size_t count, loff_t *ppos)
 390 {
 391         struct mwifiex_private *priv =
 392                 (struct mwifiex_private *) file->private_data;
 393         unsigned long page = get_zeroed_page(GFP_KERNEL);
 394         char *p = (char *) page;
 395         ssize_t ret;
 396 
 397         if (!p)
 398                 return -ENOMEM;
 399 
 400         ret = mwifiex_get_debug_info(priv, &info);
 401         if (ret)
 402                 goto free_and_exit;
 403 
 404         p += mwifiex_debug_info_to_buffer(priv, p, &info);
 405 
 406         ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
 407                                       (unsigned long) p - page);
 408 
 409 free_and_exit:
 410         free_page(page);
 411         return ret;
 412 }
 413 
 414 static u32 saved_reg_type, saved_reg_offset, saved_reg_value;
 415 
 416 /*
 417  * Proc regrdwr file write handler.
 418  *
 419  * This function is called when the 'regrdwr' file is opened for writing
 420  *
 421  * This function can be used to write to a register.
 422  */
 423 static ssize_t
 424 mwifiex_regrdwr_write(struct file *file,
 425                       const char __user *ubuf, size_t count, loff_t *ppos)
 426 {
 427         char *buf;
 428         int ret;
 429         u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
 430 
 431         buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
 432         if (IS_ERR(buf))
 433                 return PTR_ERR(buf);
 434 
 435         sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
 436 
 437         if (reg_type == 0 || reg_offset == 0) {
 438                 ret = -EINVAL;
 439                 goto done;
 440         } else {
 441                 saved_reg_type = reg_type;
 442                 saved_reg_offset = reg_offset;
 443                 saved_reg_value = reg_value;
 444                 ret = count;
 445         }
 446 done:
 447         kfree(buf);
 448         return ret;
 449 }
 450 
 451 /*
 452  * Proc regrdwr file read handler.
 453  *
 454  * This function is called when the 'regrdwr' file is opened for reading
 455  *
 456  * This function can be used to read from a register.
 457  */
 458 static ssize_t
 459 mwifiex_regrdwr_read(struct file *file, char __user *ubuf,
 460                      size_t count, loff_t *ppos)
 461 {
 462         struct mwifiex_private *priv =
 463                 (struct mwifiex_private *) file->private_data;
 464         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 465         char *buf = (char *) addr;
 466         int pos = 0, ret = 0;
 467         u32 reg_value;
 468 
 469         if (!buf)
 470                 return -ENOMEM;
 471 
 472         if (!saved_reg_type) {
 473                 /* No command has been given */
 474                 pos += snprintf(buf, PAGE_SIZE, "0");
 475                 goto done;
 476         }
 477         /* Set command has been given */
 478         if (saved_reg_value != UINT_MAX) {
 479                 ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset,
 480                                         saved_reg_value);
 481 
 482                 pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n",
 483                                 saved_reg_type, saved_reg_offset,
 484                                 saved_reg_value);
 485 
 486                 ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 487 
 488                 goto done;
 489         }
 490         /* Get command has been given */
 491         ret = mwifiex_reg_read(priv, saved_reg_type,
 492                                saved_reg_offset, &reg_value);
 493         if (ret) {
 494                 ret = -EINVAL;
 495                 goto done;
 496         }
 497 
 498         pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type,
 499                         saved_reg_offset, reg_value);
 500 
 501         ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 502 
 503 done:
 504         free_page(addr);
 505         return ret;
 506 }
 507 
 508 /* Proc debug_mask file read handler.
 509  * This function is called when the 'debug_mask' file is opened for reading
 510  * This function can be used read driver debugging mask value.
 511  */
 512 static ssize_t
 513 mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
 514                         size_t count, loff_t *ppos)
 515 {
 516         struct mwifiex_private *priv =
 517                 (struct mwifiex_private *)file->private_data;
 518         unsigned long page = get_zeroed_page(GFP_KERNEL);
 519         char *buf = (char *)page;
 520         size_t ret = 0;
 521         int pos = 0;
 522 
 523         if (!buf)
 524                 return -ENOMEM;
 525 
 526         pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
 527                         priv->adapter->debug_mask);
 528         ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 529 
 530         free_page(page);
 531         return ret;
 532 }
 533 
 534 /* Proc debug_mask file read handler.
 535  * This function is called when the 'debug_mask' file is opened for reading
 536  * This function can be used read driver debugging mask value.
 537  */
 538 static ssize_t
 539 mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
 540                          size_t count, loff_t *ppos)
 541 {
 542         int ret;
 543         unsigned long debug_mask;
 544         struct mwifiex_private *priv = (void *)file->private_data;
 545         char *buf;
 546 
 547         buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
 548         if (IS_ERR(buf))
 549                 return PTR_ERR(buf);
 550 
 551         if (kstrtoul(buf, 0, &debug_mask)) {
 552                 ret = -EINVAL;
 553                 goto done;
 554         }
 555 
 556         priv->adapter->debug_mask = debug_mask;
 557         ret = count;
 558 done:
 559         kfree(buf);
 560         return ret;
 561 }
 562 
 563 /* debugfs verext file write handler.
 564  * This function is called when the 'verext' file is opened for write
 565  */
 566 static ssize_t
 567 mwifiex_verext_write(struct file *file, const char __user *ubuf,
 568                      size_t count, loff_t *ppos)
 569 {
 570         int ret;
 571         u32 versionstrsel;
 572         struct mwifiex_private *priv = (void *)file->private_data;
 573         char buf[16];
 574 
 575         memset(buf, 0, sizeof(buf));
 576 
 577         if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 578                 return -EFAULT;
 579 
 580         ret = kstrtou32(buf, 10, &versionstrsel);
 581         if (ret)
 582                 return ret;
 583 
 584         priv->versionstrsel = versionstrsel;
 585 
 586         return count;
 587 }
 588 
 589 /* Proc verext file read handler.
 590  * This function is called when the 'verext' file is opened for reading
 591  * This function can be used read driver exteneed verion string.
 592  */
 593 static ssize_t
 594 mwifiex_verext_read(struct file *file, char __user *ubuf,
 595                     size_t count, loff_t *ppos)
 596 {
 597         struct mwifiex_private *priv =
 598                 (struct mwifiex_private *)file->private_data;
 599         char buf[256];
 600         int ret;
 601 
 602         mwifiex_get_ver_ext(priv, priv->versionstrsel);
 603         ret = snprintf(buf, sizeof(buf), "version string: %s\n",
 604                        priv->version_str);
 605 
 606         return simple_read_from_buffer(ubuf, count, ppos, buf, ret);
 607 }
 608 
 609 /* Proc memrw file write handler.
 610  * This function is called when the 'memrw' file is opened for writing
 611  * This function can be used to write to a memory location.
 612  */
 613 static ssize_t
 614 mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
 615                     loff_t *ppos)
 616 {
 617         int ret;
 618         char cmd;
 619         struct mwifiex_ds_mem_rw mem_rw;
 620         u16 cmd_action;
 621         struct mwifiex_private *priv = (void *)file->private_data;
 622         char *buf;
 623 
 624         buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
 625         if (IS_ERR(buf))
 626                 return PTR_ERR(buf);
 627 
 628         ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
 629         if (ret != 3) {
 630                 ret = -EINVAL;
 631                 goto done;
 632         }
 633 
 634         if ((cmd == 'r') || (cmd == 'R')) {
 635                 cmd_action = HostCmd_ACT_GEN_GET;
 636                 mem_rw.value = 0;
 637         } else if ((cmd == 'w') || (cmd == 'W')) {
 638                 cmd_action = HostCmd_ACT_GEN_SET;
 639         } else {
 640                 ret = -EINVAL;
 641                 goto done;
 642         }
 643 
 644         memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
 645         if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
 646                              &mem_rw, true))
 647                 ret = -1;
 648         else
 649                 ret = count;
 650 
 651 done:
 652         kfree(buf);
 653         return ret;
 654 }
 655 
 656 /* Proc memrw file read handler.
 657  * This function is called when the 'memrw' file is opened for reading
 658  * This function can be used to read from a memory location.
 659  */
 660 static ssize_t
 661 mwifiex_memrw_read(struct file *file, char __user *ubuf,
 662                    size_t count, loff_t *ppos)
 663 {
 664         struct mwifiex_private *priv = (void *)file->private_data;
 665         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 666         char *buf = (char *)addr;
 667         int ret, pos = 0;
 668 
 669         if (!buf)
 670                 return -ENOMEM;
 671 
 672         pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
 673                         priv->mem_rw.value);
 674         ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 675 
 676         free_page(addr);
 677         return ret;
 678 }
 679 
 680 static u32 saved_offset = -1, saved_bytes = -1;
 681 
 682 /*
 683  * Proc rdeeprom file write handler.
 684  *
 685  * This function is called when the 'rdeeprom' file is opened for writing
 686  *
 687  * This function can be used to write to a RDEEPROM location.
 688  */
 689 static ssize_t
 690 mwifiex_rdeeprom_write(struct file *file,
 691                        const char __user *ubuf, size_t count, loff_t *ppos)
 692 {
 693         char *buf;
 694         int ret = 0;
 695         int offset = -1, bytes = -1;
 696 
 697         buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
 698         if (IS_ERR(buf))
 699                 return PTR_ERR(buf);
 700 
 701         sscanf(buf, "%d %d", &offset, &bytes);
 702 
 703         if (offset == -1 || bytes == -1) {
 704                 ret = -EINVAL;
 705                 goto done;
 706         } else {
 707                 saved_offset = offset;
 708                 saved_bytes = bytes;
 709                 ret = count;
 710         }
 711 done:
 712         kfree(buf);
 713         return ret;
 714 }
 715 
 716 /*
 717  * Proc rdeeprom read write handler.
 718  *
 719  * This function is called when the 'rdeeprom' file is opened for reading
 720  *
 721  * This function can be used to read from a RDEEPROM location.
 722  */
 723 static ssize_t
 724 mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
 725                       size_t count, loff_t *ppos)
 726 {
 727         struct mwifiex_private *priv =
 728                 (struct mwifiex_private *) file->private_data;
 729         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 730         char *buf = (char *) addr;
 731         int pos, ret, i;
 732         u8 value[MAX_EEPROM_DATA];
 733 
 734         if (!buf)
 735                 return -ENOMEM;
 736 
 737         if (saved_offset == -1) {
 738                 /* No command has been given */
 739                 pos = snprintf(buf, PAGE_SIZE, "0");
 740                 goto done;
 741         }
 742 
 743         /* Get command has been given */
 744         ret = mwifiex_eeprom_read(priv, (u16) saved_offset,
 745                                   (u16) saved_bytes, value);
 746         if (ret) {
 747                 ret = -EINVAL;
 748                 goto out_free;
 749         }
 750 
 751         pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
 752 
 753         for (i = 0; i < saved_bytes; i++)
 754                 pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
 755 
 756 done:
 757         ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 758 out_free:
 759         free_page(addr);
 760         return ret;
 761 }
 762 
 763 /* Proc hscfg file write handler
 764  * This function can be used to configure the host sleep parameters.
 765  */
 766 static ssize_t
 767 mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
 768                     size_t count, loff_t *ppos)
 769 {
 770         struct mwifiex_private *priv = (void *)file->private_data;
 771         char *buf;
 772         int ret, arg_num;
 773         struct mwifiex_ds_hs_cfg hscfg;
 774         int conditions = HS_CFG_COND_DEF;
 775         u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
 776 
 777         buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
 778         if (IS_ERR(buf))
 779                 return PTR_ERR(buf);
 780 
 781         arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
 782 
 783         memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
 784 
 785         if (arg_num > 3) {
 786                 mwifiex_dbg(priv->adapter, ERROR,
 787                             "Too many arguments\n");
 788                 ret = -EINVAL;
 789                 goto done;
 790         }
 791 
 792         if (arg_num >= 1 && arg_num < 3)
 793                 mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
 794                                       MWIFIEX_SYNC_CMD, &hscfg);
 795 
 796         if (arg_num) {
 797                 if (conditions == HS_CFG_CANCEL) {
 798                         mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
 799                         ret = count;
 800                         goto done;
 801                 }
 802                 hscfg.conditions = conditions;
 803         }
 804         if (arg_num >= 2)
 805                 hscfg.gpio = gpio;
 806         if (arg_num == 3)
 807                 hscfg.gap = gap;
 808 
 809         hscfg.is_invoke_hostcmd = false;
 810         mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
 811                               MWIFIEX_SYNC_CMD, &hscfg);
 812 
 813         mwifiex_enable_hs(priv->adapter);
 814         clear_bit(MWIFIEX_IS_HS_ENABLING, &priv->adapter->work_flags);
 815         ret = count;
 816 done:
 817         kfree(buf);
 818         return ret;
 819 }
 820 
 821 /* Proc hscfg file read handler
 822  * This function can be used to read host sleep configuration
 823  * parameters from driver.
 824  */
 825 static ssize_t
 826 mwifiex_hscfg_read(struct file *file, char __user *ubuf,
 827                    size_t count, loff_t *ppos)
 828 {
 829         struct mwifiex_private *priv = (void *)file->private_data;
 830         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 831         char *buf = (char *)addr;
 832         int pos, ret;
 833         struct mwifiex_ds_hs_cfg hscfg;
 834 
 835         if (!buf)
 836                 return -ENOMEM;
 837 
 838         mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
 839                               MWIFIEX_SYNC_CMD, &hscfg);
 840 
 841         pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
 842                        hscfg.gpio, hscfg.gap);
 843 
 844         ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
 845 
 846         free_page(addr);
 847         return ret;
 848 }
 849 
 850 static ssize_t
 851 mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
 852                             size_t count, loff_t *ppos)
 853 {
 854         struct mwifiex_private *priv = file->private_data;
 855         char buf[3];
 856         bool timeshare_coex;
 857         int ret;
 858         unsigned int len;
 859 
 860         if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
 861                 return -EOPNOTSUPP;
 862 
 863         ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
 864                                HostCmd_ACT_GEN_GET, 0, &timeshare_coex, true);
 865         if (ret)
 866                 return ret;
 867 
 868         len = sprintf(buf, "%d\n", timeshare_coex);
 869         return simple_read_from_buffer(ubuf, count, ppos, buf, len);
 870 }
 871 
 872 static ssize_t
 873 mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
 874                              size_t count, loff_t *ppos)
 875 {
 876         bool timeshare_coex;
 877         struct mwifiex_private *priv = file->private_data;
 878         char kbuf[16];
 879         int ret;
 880 
 881         if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
 882                 return -EOPNOTSUPP;
 883 
 884         memset(kbuf, 0, sizeof(kbuf));
 885 
 886         if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
 887                 return -EFAULT;
 888 
 889         if (strtobool(kbuf, &timeshare_coex))
 890                 return -EINVAL;
 891 
 892         ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
 893                                HostCmd_ACT_GEN_SET, 0, &timeshare_coex, true);
 894         if (ret)
 895                 return ret;
 896         else
 897                 return count;
 898 }
 899 
 900 static ssize_t
 901 mwifiex_reset_write(struct file *file,
 902                     const char __user *ubuf, size_t count, loff_t *ppos)
 903 {
 904         struct mwifiex_private *priv = file->private_data;
 905         struct mwifiex_adapter *adapter = priv->adapter;
 906         bool result;
 907         int rc;
 908 
 909         rc = kstrtobool_from_user(ubuf, count, &result);
 910         if (rc)
 911                 return rc;
 912 
 913         if (!result)
 914                 return -EINVAL;
 915 
 916         if (adapter->if_ops.card_reset) {
 917                 dev_info(adapter->dev, "Resetting per request\n");
 918                 adapter->if_ops.card_reset(adapter);
 919         }
 920 
 921         return count;
 922 }
 923 
 924 #define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
 925         debugfs_create_file(#name, 0644, priv->dfs_dev_dir, priv,       \
 926                             &mwifiex_dfs_##name##_fops);                \
 927 } while (0);
 928 
 929 #define MWIFIEX_DFS_FILE_OPS(name)                                      \
 930 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
 931         .read = mwifiex_##name##_read,                                  \
 932         .write = mwifiex_##name##_write,                                \
 933         .open = simple_open,                                            \
 934 };
 935 
 936 #define MWIFIEX_DFS_FILE_READ_OPS(name)                                 \
 937 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
 938         .read = mwifiex_##name##_read,                                  \
 939         .open = simple_open,                                            \
 940 };
 941 
 942 #define MWIFIEX_DFS_FILE_WRITE_OPS(name)                                \
 943 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
 944         .write = mwifiex_##name##_write,                                \
 945         .open = simple_open,                                            \
 946 };
 947 
 948 
 949 MWIFIEX_DFS_FILE_READ_OPS(info);
 950 MWIFIEX_DFS_FILE_READ_OPS(debug);
 951 MWIFIEX_DFS_FILE_READ_OPS(getlog);
 952 MWIFIEX_DFS_FILE_OPS(regrdwr);
 953 MWIFIEX_DFS_FILE_OPS(rdeeprom);
 954 MWIFIEX_DFS_FILE_OPS(memrw);
 955 MWIFIEX_DFS_FILE_OPS(hscfg);
 956 MWIFIEX_DFS_FILE_OPS(histogram);
 957 MWIFIEX_DFS_FILE_OPS(debug_mask);
 958 MWIFIEX_DFS_FILE_OPS(timeshare_coex);
 959 MWIFIEX_DFS_FILE_WRITE_OPS(reset);
 960 MWIFIEX_DFS_FILE_OPS(verext);
 961 
 962 /*
 963  * This function creates the debug FS directory structure and the files.
 964  */
 965 void
 966 mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
 967 {
 968         if (!mwifiex_dfs_dir || !priv)
 969                 return;
 970 
 971         priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
 972                                                mwifiex_dfs_dir);
 973 
 974         if (!priv->dfs_dev_dir)
 975                 return;
 976 
 977         MWIFIEX_DFS_ADD_FILE(info);
 978         MWIFIEX_DFS_ADD_FILE(debug);
 979         MWIFIEX_DFS_ADD_FILE(getlog);
 980         MWIFIEX_DFS_ADD_FILE(regrdwr);
 981         MWIFIEX_DFS_ADD_FILE(rdeeprom);
 982 
 983         MWIFIEX_DFS_ADD_FILE(memrw);
 984         MWIFIEX_DFS_ADD_FILE(hscfg);
 985         MWIFIEX_DFS_ADD_FILE(histogram);
 986         MWIFIEX_DFS_ADD_FILE(debug_mask);
 987         MWIFIEX_DFS_ADD_FILE(timeshare_coex);
 988         MWIFIEX_DFS_ADD_FILE(reset);
 989         MWIFIEX_DFS_ADD_FILE(verext);
 990 }
 991 
 992 /*
 993  * This function removes the debug FS directory structure and the files.
 994  */
 995 void
 996 mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
 997 {
 998         if (!priv)
 999                 return;
1000 
1001         debugfs_remove_recursive(priv->dfs_dev_dir);
1002 }
1003 
1004 /*
1005  * This function creates the top level proc directory.
1006  */
1007 void
1008 mwifiex_debugfs_init(void)
1009 {
1010         if (!mwifiex_dfs_dir)
1011                 mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL);
1012 }
1013 
1014 /*
1015  * This function removes the top level proc directory.
1016  */
1017 void
1018 mwifiex_debugfs_remove(void)
1019 {
1020         debugfs_remove(mwifiex_dfs_dir);
1021 }

/* [<][>][^][v][top][bottom][index][help] */