[PATCH 2/2] staging: dgnc: Replace fixed-size board array with list
Konrad Zapalowicz
bergo.torino+kernel at gmail.com
Sun Aug 31 21:23:58 UTC 2014
Each registered board is asigned a data structure to keep it's state.
So far this was implemented using the static array of fixed-size. This
commit changes the implementation by replacing the array with dynamic
solution based on the kernel list.
Signed-off-by: Konrad Zapalowicz <bergo.torino+kernel at gmail.com>
---
drivers/staging/dgnc/dgnc_driver.c | 57 ++++++++++++++++++--------------------
drivers/staging/dgnc/dgnc_driver.h | 3 +-
drivers/staging/dgnc/dgnc_mgmt.c | 49 +++++++++++++++++++-------------
drivers/staging/dgnc/dgnc_sysfs.c | 8 +++++-
drivers/staging/dgnc/dgnc_utils.c | 18 ++++++++++++
drivers/staging/dgnc/dgnc_utils.h | 1 +
6 files changed, 84 insertions(+), 52 deletions(-)
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
index 11bed56..405ae35 100644
--- a/drivers/staging/dgnc/dgnc_driver.c
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -87,12 +87,10 @@ static const struct file_operations dgnc_BoardFops = {
/*
* Globals
*/
-uint dgnc_NumBoards;
-struct dgnc_board *dgnc_Board[MAXBOARDS];
DEFINE_SPINLOCK(dgnc_global_lock);
uint dgnc_Major;
int dgnc_poll_tick = 20; /* Poll interval - 20 ms */
-
+LIST_HEAD(board_list);
/*
* Static vars.
*/
@@ -183,8 +181,9 @@ char *dgnc_state_text[] = {
*/
static void dgnc_cleanup_module(void)
{
- int i;
ulong lock_flags;
+ struct list_head *ptr, *next;
+ struct dgnc_board *brd;
DGNC_LOCK(dgnc_poll_lock, lock_flags);
dgnc_poll_stop = 1;
@@ -199,15 +198,17 @@ static void dgnc_cleanup_module(void)
class_destroy(dgnc_class);
unregister_chrdev(dgnc_Major, "dgnc");
- for (i = 0; i < dgnc_NumBoards; ++i) {
- dgnc_remove_ports_sysfiles(dgnc_Board[i]);
- dgnc_tty_uninit(dgnc_Board[i]);
- dgnc_cleanup_board(dgnc_Board[i]);
+ list_for_each_safe(ptr, next, &board_list) {
+ list_del(ptr);
+ brd = list_entry(ptr, struct dgnc_board, list);
+ dgnc_remove_ports_sysfiles(brd);
+ dgnc_tty_uninit(brd);
+ dgnc_cleanup_board(brd);
}
dgnc_tty_post_uninit();
- if (dgnc_NumBoards)
+ if (!list_empty(&board_list))
pci_unregister_driver(&dgnc_driver);
}
@@ -240,7 +241,7 @@ static int __init dgnc_init_module(void)
*/
if (rc < 0) {
/* Only unregister the pci driver if it was actually registered. */
- if (dgnc_NumBoards)
+ if (!list_empty(&board_list))
pci_unregister_driver(&dgnc_driver);
else
pr_warn("WARNING: dgnc driver load failed. No Digi Neo or Classic boards found.\n");
@@ -320,13 +321,11 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* wake up and enable device */
rc = pci_enable_device(pdev);
- if (rc < 0) {
+ if (rc < 0)
rc = -EIO;
- } else {
+ else
rc = dgnc_found_board(pdev, ent->driver_data);
- if (rc == 0)
- dgnc_NumBoards++;
- }
+
return rc;
}
@@ -389,9 +388,6 @@ static void dgnc_cleanup_board(struct dgnc_board *brd)
}
kfree(brd->flipbuf);
-
- dgnc_Board[brd->boardnum] = NULL;
-
kfree(brd);
}
@@ -408,10 +404,11 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
int i = 0;
int rc = 0;
unsigned long flags;
+ unsigned int brd_num = 0;
+ struct list_head *ptr = NULL;
/* get the board structure and prep it */
- brd = dgnc_Board[dgnc_NumBoards] =
- kzalloc(sizeof(*brd), GFP_KERNEL);
+ brd = kzalloc(sizeof(*brd), GFP_KERNEL);
if (!brd)
return -ENOMEM;
@@ -423,9 +420,12 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
return -ENOMEM;
}
+ list_for_each(ptr, &board_list)
+ brd_num++;
+
/* store the info for the board we've found */
brd->magic = DGNC_BOARD_MAGIC;
- brd->boardnum = dgnc_NumBoards;
+ brd->boardnum = brd_num;
brd->vendor = dgnc_pci_tbl[id].vendor;
brd->device = dgnc_pci_tbl[id].device;
brd->pdev = pdev;
@@ -571,6 +571,9 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
}
+ /* Now is the time to add the board to the list */
+ list_add(&brd->list, &board_list);
+
/*
* Do tty device initialization.
*/
@@ -700,14 +703,14 @@ static void dgnc_do_remap(struct dgnc_board *brd)
static void dgnc_poll_handler(ulong dummy)
{
+ struct list_head *ptr;
struct dgnc_board *brd;
unsigned long lock_flags;
- int i;
unsigned long new_time;
/* Go thru each board, kicking off a tasklet for each if needed */
- for (i = 0; i < dgnc_NumBoards; i++) {
- brd = dgnc_Board[i];
+ list_for_each(ptr, &board_list) {
+ brd = list_entry(ptr, struct dgnc_board, list);
DGNC_LOCK(brd->bd_lock, lock_flags);
@@ -753,15 +756,9 @@ static void dgnc_poll_handler(ulong dummy)
*/
static void dgnc_init_globals(void)
{
- int i = 0;
-
dgnc_rawreadok = rawreadok;
dgnc_trcbuf_size = trcbuf_size;
dgnc_debug = debug;
- dgnc_NumBoards = 0;
-
- for (i = 0; i < MAXBOARDS; i++)
- dgnc_Board[i] = NULL;
init_timer(&dgnc_poll_timer);
}
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
index 251b082..bd0d3ff 100644
--- a/drivers/staging/dgnc/dgnc_driver.h
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -470,8 +470,7 @@ extern int dgnc_rawreadok; /* Set if user wants rawreads */
extern int dgnc_poll_tick; /* Poll interval - 20 ms */
extern int dgnc_trcbuf_size; /* Size of the ringbuffer */
extern spinlock_t dgnc_global_lock; /* Driver global spinlock */
-extern uint dgnc_NumBoards; /* Total number of boards */
-extern struct dgnc_board *dgnc_Board[MAXBOARDS]; /* Array of board structs */
+extern struct list_head board_list; /* list of boards */
extern char *dgnc_state_text[]; /* Array of state text */
#endif
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
index 31e9f45..1089010 100644
--- a/drivers/staging/dgnc/dgnc_mgmt.c
+++ b/drivers/staging/dgnc/dgnc_mgmt.c
@@ -48,6 +48,7 @@
#include "dgnc_pci.h"
#include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */
#include "dgnc_mgmt.h"
+#include "dgnc_utils.h"
#include "dpacompat.h"
@@ -118,6 +119,8 @@ int dgnc_mgmt_close(struct inode *inode, struct file *file)
long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long lock_flags;
+ unsigned long brd_count = 0;
+ struct list_head *ptr = NULL;
void __user *uarg = (void __user *) arg;
switch (cmd) {
@@ -133,7 +136,10 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DGNC_LOCK(dgnc_global_lock, lock_flags);
- ddi.dinfo_nboards = dgnc_NumBoards;
+ list_for_each(ptr, &board_list)
+ brd_count++;
+
+ ddi.dinfo_nboards = brd_count;
sprintf(ddi.dinfo_version, "%s", DG_PART);
DGNC_UNLOCK(dgnc_global_lock, lock_flags);
@@ -146,34 +152,36 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case DIGI_GETBD:
{
- int brd;
-
+ int brd_num;
+ struct dgnc_board *brd = NULL;
struct digi_info di;
- if (copy_from_user(&brd, uarg, sizeof(int)))
+ if (copy_from_user(&brd_num, uarg, sizeof(int)))
return -EFAULT;
- if ((brd < 0) || (brd > dgnc_NumBoards) ||
- (dgnc_NumBoards == 0))
+ DGNC_LOCK(dgnc_global_lock, lock_flags);
+ brd = dgnc_get_board(&board_list, brd_num);
+ DGNC_UNLOCK(dgnc_global_lock, lock_flags);
+ if (!brd)
return -ENODEV;
memset(&di, 0, sizeof(di));
- di.info_bdnum = brd;
+ di.info_bdnum = brd_num;
- DGNC_LOCK(dgnc_Board[brd]->bd_lock, lock_flags);
+ DGNC_LOCK(brd->bd_lock, lock_flags);
- di.info_bdtype = dgnc_Board[brd]->dpatype;
- di.info_bdstate = dgnc_Board[brd]->dpastatus;
+ di.info_bdtype = brd->dpatype;
+ di.info_bdstate = brd->dpastatus;
di.info_ioport = 0;
- di.info_physaddr = (ulong) dgnc_Board[brd]->membase;
- di.info_physsize = (ulong) dgnc_Board[brd]->membase - dgnc_Board[brd]->membase_end;
- if (dgnc_Board[brd]->state != BOARD_FAILED)
- di.info_nports = dgnc_Board[brd]->nasync;
+ di.info_physaddr = (ulong) brd->membase;
+ di.info_physsize = (ulong) brd->membase - brd->membase_end;
+ if (brd->state != BOARD_FAILED)
+ di.info_nports = brd->nasync;
else
di.info_nports = 0;
- DGNC_UNLOCK(dgnc_Board[brd]->bd_lock, lock_flags);
+ DGNC_UNLOCK(brd->bd_lock, lock_flags);
if (copy_to_user(uarg, &di, sizeof(di)))
return -EFAULT;
@@ -183,6 +191,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case DIGI_GET_NI_INFO:
{
+ struct dgnc_board *brd = NULL;
struct channel_t *ch;
struct ni_info ni;
uchar mstat = 0;
@@ -195,15 +204,17 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
board = ni.board;
channel = ni.channel;
- /* Verify boundaries on board */
- if ((board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
+ DGNC_LOCK(dgnc_global_lock, lock_flags);
+ brd = dgnc_get_board(&board_list, board);
+ DGNC_UNLOCK(dgnc_global_lock, lock_flags);
+ if (!brd)
return -ENODEV;
/* Verify boundaries on channel */
- if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
+ if ((channel < 0) || (channel > brd->nasync))
return -ENODEV;
- ch = dgnc_Board[board]->channels[channel];
+ ch = brd->channels[channel];
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return -ENODEV;
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
index 60d247b..6ff1bc1 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.c
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -52,7 +52,13 @@ static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL);
static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards);
+ unsigned int brd_count = 0;
+ struct list_head *ptr = NULL;
+
+ list_for_each(ptr, &board_list)
+ brd_count++;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", brd_count);
}
static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL);
diff --git a/drivers/staging/dgnc/dgnc_utils.c b/drivers/staging/dgnc/dgnc_utils.c
index 61efc13..5b1364f 100644
--- a/drivers/staging/dgnc/dgnc_utils.c
+++ b/drivers/staging/dgnc/dgnc_utils.c
@@ -1,6 +1,8 @@
#include <linux/tty.h>
#include <linux/sched.h>
+#include <linux/list.h>
#include "dgnc_utils.h"
+#include "dgnc_driver.h"
#include "digi.h"
/*
@@ -68,3 +70,19 @@ char *dgnc_ioctl_name(int cmd)
default: return "unknown";
}
}
+
+struct dgnc_board *dgnc_get_board(struct list_head *board_list, int board_id)
+{
+ struct dgnc_board *retval = NULL;
+ struct list_head *ptr = NULL;
+
+ list_for_each(ptr, board_list) {
+ retval = list_entry(ptr, struct dgnc_board, list);
+ if (retval->boardnum == board_id)
+ break;
+ else
+ retval = NULL;
+ }
+
+ return retval;
+}
diff --git a/drivers/staging/dgnc/dgnc_utils.h b/drivers/staging/dgnc/dgnc_utils.h
index cebf601..eca185e 100644
--- a/drivers/staging/dgnc/dgnc_utils.h
+++ b/drivers/staging/dgnc/dgnc_utils.h
@@ -3,5 +3,6 @@
int dgnc_ms_sleep(ulong ms);
char *dgnc_ioctl_name(int cmd);
+struct dgnc_board *dgnc_get_board(struct list_head *board_list, int board_id);
#endif
--
1.8.1.2
More information about the devel
mailing list