aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/ev-layer.c
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2006-04-11 01:55:16 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:50 -0400
commit69049cc87dccb1e6fb54aa25c63033efac805dbd (patch)
tree9db1953a831091335b98f8749865f4c8b410ff9b /drivers/isdn/gigaset/ev-layer.c
parent27d1ac2ef7d0b9250ca9fd2ef506e12866ce8fdf (diff)
[PATCH] isdn4linux: Siemens Gigaset drivers: make some variables non-atomic
With Hansjoerg Lipp <hjlipp@web.de> Replace some atomic_t variables in the Gigaset drivers by non-atomic ones, using spinlocks instead to assure atomicity, as proposed in discussions on the linux-kernel mailing list. Signed-off-by: Hansjoerg Lipp <hjlipp@web.de> Signed-off-by: Tilman Schmidt <tilman@imap.cc> Cc: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/isdn/gigaset/ev-layer.c')
-rw-r--r--drivers/isdn/gigaset/ev-layer.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 2e826d051c85..1ba3424a286b 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -482,14 +482,6 @@ static int isdn_gethex(char *p)
482 return v; 482 return v;
483} 483}
484 484
485static inline void new_index(atomic_t *index, int max)
486{
487 if (atomic_read(index) == max) //FIXME race?
488 atomic_set(index, 0);
489 else
490 atomic_inc(index);
491}
492
493/* retrieve CID from parsed response 485/* retrieve CID from parsed response
494 * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535 486 * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
495 */ 487 */
@@ -581,8 +573,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
581 } 573 }
582 574
583 spin_lock_irqsave(&cs->ev_lock, flags); 575 spin_lock_irqsave(&cs->ev_lock, flags);
584 head = atomic_read(&cs->ev_head); 576 head = cs->ev_head;
585 tail = atomic_read(&cs->ev_tail); 577 tail = cs->ev_tail;
586 578
587 abort = 1; 579 abort = 1;
588 curarg = 0; 580 curarg = 0;
@@ -715,7 +707,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
715 break; 707 break;
716 } 708 }
717 709
718 atomic_set(&cs->ev_tail, tail); 710 cs->ev_tail = tail;
719 spin_unlock_irqrestore(&cs->ev_lock, flags); 711 spin_unlock_irqrestore(&cs->ev_lock, flags);
720 712
721 if (curarg != params) 713 if (curarg != params)
@@ -734,14 +726,16 @@ static void disconnect(struct at_state_t **at_state_p)
734 struct bc_state *bcs = (*at_state_p)->bcs; 726 struct bc_state *bcs = (*at_state_p)->bcs;
735 struct cardstate *cs = (*at_state_p)->cs; 727 struct cardstate *cs = (*at_state_p)->cs;
736 728
737 new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX); 729 spin_lock_irqsave(&cs->lock, flags);
730 ++(*at_state_p)->seq_index;
738 731
739 /* revert to selected idle mode */ 732 /* revert to selected idle mode */
740 if (!atomic_read(&cs->cidmode)) { 733 if (!cs->cidmode) {
741 cs->at_state.pending_commands |= PC_UMMODE; 734 cs->at_state.pending_commands |= PC_UMMODE;
742 atomic_set(&cs->commands_pending, 1); //FIXME 735 atomic_set(&cs->commands_pending, 1); //FIXME
743 gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); 736 gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
744 } 737 }
738 spin_unlock_irqrestore(&cs->lock, flags);
745 739
746 if (bcs) { 740 if (bcs) {
747 /* B channel assigned: invoke hardware specific handler */ 741 /* B channel assigned: invoke hardware specific handler */
@@ -933,17 +927,21 @@ static void bchannel_up(struct bc_state *bcs)
933 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); 927 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
934} 928}
935 929
936static void start_dial(struct at_state_t *at_state, void *data, int seq_index) 930static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index)
937{ 931{
938 struct bc_state *bcs = at_state->bcs; 932 struct bc_state *bcs = at_state->bcs;
939 struct cardstate *cs = at_state->cs; 933 struct cardstate *cs = at_state->cs;
940 int retval; 934 int retval;
935 unsigned long flags;
941 936
942 bcs->chstate |= CHS_NOTIFY_LL; 937 bcs->chstate |= CHS_NOTIFY_LL;
943 //atomic_set(&bcs->status, BCS_INIT);
944 938
945 if (atomic_read(&at_state->seq_index) != seq_index) 939 spin_lock_irqsave(&cs->lock, flags);
940 if (at_state->seq_index != seq_index) {
941 spin_unlock_irqrestore(&cs->lock, flags);
946 goto error; 942 goto error;
943 }
944 spin_unlock_irqrestore(&cs->lock, flags);
947 945
948 retval = gigaset_isdn_setup_dial(at_state, data); 946 retval = gigaset_isdn_setup_dial(at_state, data);
949 if (retval != 0) 947 if (retval != 0)
@@ -988,6 +986,7 @@ static void do_start(struct cardstate *cs)
988 if (atomic_read(&cs->mstate) != MS_LOCKED) 986 if (atomic_read(&cs->mstate) != MS_LOCKED)
989 schedule_init(cs, MS_INIT); 987 schedule_init(cs, MS_INIT);
990 988
989 cs->isdn_up = 1;
991 gigaset_i4l_cmd(cs, ISDN_STAT_RUN); 990 gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
992 // FIXME: not in locked mode 991 // FIXME: not in locked mode
993 // FIXME 2: only after init sequence 992 // FIXME 2: only after init sequence
@@ -1003,6 +1002,12 @@ static void finish_shutdown(struct cardstate *cs)
1003 atomic_set(&cs->mode, M_UNKNOWN); 1002 atomic_set(&cs->mode, M_UNKNOWN);
1004 } 1003 }
1005 1004
1005 /* Tell the LL that the device is not available .. */
1006 if (cs->isdn_up) {
1007 cs->isdn_up = 0;
1008 gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
1009 }
1010
1006 /* The rest is done by cleanup_cs () in user mode. */ 1011 /* The rest is done by cleanup_cs () in user mode. */
1007 1012
1008 cs->cmd_result = -ENODEV; 1013 cs->cmd_result = -ENODEV;
@@ -1025,6 +1030,12 @@ static void do_shutdown(struct cardstate *cs)
1025 1030
1026static void do_stop(struct cardstate *cs) 1031static void do_stop(struct cardstate *cs)
1027{ 1032{
1033 unsigned long flags;
1034
1035 spin_lock_irqsave(&cs->lock, flags);
1036 cs->connected = 0;
1037 spin_unlock_irqrestore(&cs->lock, flags);
1038
1028 do_shutdown(cs); 1039 do_shutdown(cs);
1029} 1040}
1030 1041
@@ -1153,7 +1164,7 @@ static int do_unlock(struct cardstate *cs)
1153 atomic_set(&cs->mstate, MS_UNINITIALIZED); 1164 atomic_set(&cs->mstate, MS_UNINITIALIZED);
1154 atomic_set(&cs->mode, M_UNKNOWN); 1165 atomic_set(&cs->mode, M_UNKNOWN);
1155 gigaset_free_channels(cs); 1166 gigaset_free_channels(cs);
1156 if (atomic_read(&cs->connected)) 1167 if (cs->connected)
1157 schedule_init(cs, MS_INIT); 1168 schedule_init(cs, MS_INIT);
1158 1169
1159 return 0; 1170 return 0;
@@ -1185,11 +1196,14 @@ static void do_action(int action, struct cardstate *cs,
1185 cs->at_state.pending_commands &= ~PC_INIT; 1196 cs->at_state.pending_commands &= ~PC_INIT;
1186 cs->cur_at_seq = SEQ_NONE; 1197 cs->cur_at_seq = SEQ_NONE;
1187 atomic_set(&cs->mode, M_UNIMODEM); 1198 atomic_set(&cs->mode, M_UNIMODEM);
1188 if (!atomic_read(&cs->cidmode)) { 1199 spin_lock_irqsave(&cs->lock, flags);
1200 if (!cs->cidmode) {
1201 spin_unlock_irqrestore(&cs->lock, flags);
1189 gigaset_free_channels(cs); 1202 gigaset_free_channels(cs);
1190 atomic_set(&cs->mstate, MS_READY); 1203 atomic_set(&cs->mstate, MS_READY);
1191 break; 1204 break;
1192 } 1205 }
1206 spin_unlock_irqrestore(&cs->lock, flags);
1193 cs->at_state.pending_commands |= PC_CIDMODE; 1207 cs->at_state.pending_commands |= PC_CIDMODE;
1194 atomic_set(&cs->commands_pending, 1); 1208 atomic_set(&cs->commands_pending, 1);
1195 gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); 1209 gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
@@ -1536,8 +1550,9 @@ static void do_action(int action, struct cardstate *cs,
1536 1550
1537 /* events from the proc file system */ // FIXME without ACT_xxxx? 1551 /* events from the proc file system */ // FIXME without ACT_xxxx?
1538 case ACT_PROC_CIDMODE: 1552 case ACT_PROC_CIDMODE:
1539 if (ev->parameter != atomic_read(&cs->cidmode)) { 1553 spin_lock_irqsave(&cs->lock, flags);
1540 atomic_set(&cs->cidmode, ev->parameter); 1554 if (ev->parameter != cs->cidmode) {
1555 cs->cidmode = ev->parameter;
1541 if (ev->parameter) { 1556 if (ev->parameter) {
1542 cs->at_state.pending_commands |= PC_CIDMODE; 1557 cs->at_state.pending_commands |= PC_CIDMODE;
1543 gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); 1558 gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
@@ -1547,6 +1562,7 @@ static void do_action(int action, struct cardstate *cs,
1547 } 1562 }
1548 atomic_set(&cs->commands_pending, 1); 1563 atomic_set(&cs->commands_pending, 1);
1549 } 1564 }
1565 spin_unlock_irqrestore(&cs->lock, flags);
1550 cs->waiting = 0; 1566 cs->waiting = 0;
1551 wake_up(&cs->waitqueue); 1567 wake_up(&cs->waitqueue);
1552 break; 1568 break;
@@ -1615,8 +1631,9 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
1615 /* Setting the pointer to the dial array */ 1631 /* Setting the pointer to the dial array */
1616 rep = at_state->replystruct; 1632 rep = at_state->replystruct;
1617 1633
1634 spin_lock_irqsave(&cs->lock, flags);
1618 if (ev->type == EV_TIMEOUT) { 1635 if (ev->type == EV_TIMEOUT) {
1619 if (ev->parameter != atomic_read(&at_state->timer_index) 1636 if (ev->parameter != at_state->timer_index
1620 || !at_state->timer_active) { 1637 || !at_state->timer_active) {
1621 ev->type = RSP_NONE; /* old timeout */ 1638 ev->type = RSP_NONE; /* old timeout */
1622 gig_dbg(DEBUG_ANY, "old timeout"); 1639 gig_dbg(DEBUG_ANY, "old timeout");
@@ -1625,6 +1642,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
1625 else 1642 else
1626 gig_dbg(DEBUG_ANY, "stopped waiting"); 1643 gig_dbg(DEBUG_ANY, "stopped waiting");
1627 } 1644 }
1645 spin_unlock_irqrestore(&cs->lock, flags);
1628 1646
1629 /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] 1647 /* if the response belongs to a variable in at_state->int_var[VAR_XXXX]
1630 or at_state->str_var[STR_XXXX], set it */ 1648 or at_state->str_var[STR_XXXX], set it */
@@ -1686,7 +1704,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
1686 } else { 1704 } else {
1687 /* Send command to modem if not NULL... */ 1705 /* Send command to modem if not NULL... */
1688 if (p_command/*rep->command*/) { 1706 if (p_command/*rep->command*/) {
1689 if (atomic_read(&cs->connected)) 1707 if (cs->connected)
1690 send_command(cs, p_command, 1708 send_command(cs, p_command,
1691 sendcid, cs->dle, 1709 sendcid, cs->dle,
1692 GFP_ATOMIC); 1710 GFP_ATOMIC);
@@ -1703,8 +1721,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
1703 } else if (rep->timeout > 0) { /* new timeout */ 1721 } else if (rep->timeout > 0) { /* new timeout */
1704 at_state->timer_expires = rep->timeout * 10; 1722 at_state->timer_expires = rep->timeout * 10;
1705 at_state->timer_active = 1; 1723 at_state->timer_active = 1;
1706 new_index(&at_state->timer_index, 1724 ++at_state->timer_index;
1707 MAX_TIMER_INDEX);
1708 } 1725 }
1709 spin_unlock_irqrestore(&cs->lock, flags); 1726 spin_unlock_irqrestore(&cs->lock, flags);
1710 } 1727 }
@@ -1724,6 +1741,7 @@ static void process_command_flags(struct cardstate *cs)
1724 struct bc_state *bcs; 1741 struct bc_state *bcs;
1725 int i; 1742 int i;
1726 int sequence; 1743 int sequence;
1744 unsigned long flags;
1727 1745
1728 atomic_set(&cs->commands_pending, 0); 1746 atomic_set(&cs->commands_pending, 0);
1729 1747
@@ -1773,8 +1791,9 @@ static void process_command_flags(struct cardstate *cs)
1773 } 1791 }
1774 1792
1775 /* only switch back to unimodem mode, if no commands are pending and no channels are up */ 1793 /* only switch back to unimodem mode, if no commands are pending and no channels are up */
1794 spin_lock_irqsave(&cs->lock, flags);
1776 if (cs->at_state.pending_commands == PC_UMMODE 1795 if (cs->at_state.pending_commands == PC_UMMODE
1777 && !atomic_read(&cs->cidmode) 1796 && !cs->cidmode
1778 && list_empty(&cs->temp_at_states) 1797 && list_empty(&cs->temp_at_states)
1779 && atomic_read(&cs->mode) == M_CID) { 1798 && atomic_read(&cs->mode) == M_CID) {
1780 sequence = SEQ_UMMODE; 1799 sequence = SEQ_UMMODE;
@@ -1788,6 +1807,7 @@ static void process_command_flags(struct cardstate *cs)
1788 } 1807 }
1789 } 1808 }
1790 } 1809 }
1810 spin_unlock_irqrestore(&cs->lock, flags);
1791 cs->at_state.pending_commands &= ~PC_UMMODE; 1811 cs->at_state.pending_commands &= ~PC_UMMODE;
1792 if (sequence != SEQ_NONE) { 1812 if (sequence != SEQ_NONE) {
1793 schedule_sequence(cs, at_state, sequence); 1813 schedule_sequence(cs, at_state, sequence);
@@ -1900,18 +1920,21 @@ static void process_events(struct cardstate *cs)
1900 int i; 1920 int i;
1901 int check_flags = 0; 1921 int check_flags = 0;
1902 int was_busy; 1922 int was_busy;
1923 unsigned long flags;
1903 1924
1904 /* no locking needed (only one reader) */ 1925 spin_lock_irqsave(&cs->ev_lock, flags);
1905 head = atomic_read(&cs->ev_head); 1926 head = cs->ev_head;
1906 1927
1907 for (i = 0; i < 2 * MAX_EVENTS; ++i) { 1928 for (i = 0; i < 2 * MAX_EVENTS; ++i) {
1908 tail = atomic_read(&cs->ev_tail); 1929 tail = cs->ev_tail;
1909 if (tail == head) { 1930 if (tail == head) {
1910 if (!check_flags && !atomic_read(&cs->commands_pending)) 1931 if (!check_flags && !atomic_read(&cs->commands_pending))
1911 break; 1932 break;
1912 check_flags = 0; 1933 check_flags = 0;
1934 spin_unlock_irqrestore(&cs->ev_lock, flags);
1913 process_command_flags(cs); 1935 process_command_flags(cs);
1914 tail = atomic_read(&cs->ev_tail); 1936 spin_lock_irqsave(&cs->ev_lock, flags);
1937 tail = cs->ev_tail;
1915 if (tail == head) { 1938 if (tail == head) {
1916 if (!atomic_read(&cs->commands_pending)) 1939 if (!atomic_read(&cs->commands_pending))
1917 break; 1940 break;
@@ -1921,16 +1944,20 @@ static void process_events(struct cardstate *cs)
1921 1944
1922 ev = cs->events + head; 1945 ev = cs->events + head;
1923 was_busy = cs->cur_at_seq != SEQ_NONE; 1946 was_busy = cs->cur_at_seq != SEQ_NONE;
1947 spin_unlock_irqrestore(&cs->ev_lock, flags);
1924 process_event(cs, ev); 1948 process_event(cs, ev);
1949 spin_lock_irqsave(&cs->ev_lock, flags);
1925 kfree(ev->ptr); 1950 kfree(ev->ptr);
1926 ev->ptr = NULL; 1951 ev->ptr = NULL;
1927 if (was_busy && cs->cur_at_seq == SEQ_NONE) 1952 if (was_busy && cs->cur_at_seq == SEQ_NONE)
1928 check_flags = 1; 1953 check_flags = 1;
1929 1954
1930 head = (head + 1) % MAX_EVENTS; 1955 head = (head + 1) % MAX_EVENTS;
1931 atomic_set(&cs->ev_head, head); 1956 cs->ev_head = head;
1932 } 1957 }
1933 1958
1959 spin_unlock_irqrestore(&cs->ev_lock, flags);
1960
1934 if (i == 2 * MAX_EVENTS) { 1961 if (i == 2 * MAX_EVENTS) {
1935 dev_err(cs->dev, 1962 dev_err(cs->dev,
1936 "infinite loop in process_events; aborting.\n"); 1963 "infinite loop in process_events; aborting.\n");