From 307fc61247e696b18d84d7fd59f6576b1aca9cec Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Tue, 19 May 2009 16:01:27 +0000 Subject: xpp: fix the Astribank state machine This generally is a case that would not happen in the wild, though. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@6641 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/xpp/card_global.c | 5 ++-- drivers/dahdi/xpp/xbus-core.c | 51 ++++++++++++++++++++++++++--------------- drivers/dahdi/xpp/xbus-core.h | 8 +++++-- drivers/dahdi/xpp/xbus-pcm.c | 4 ++-- drivers/dahdi/xpp/xbus-sysfs.c | 10 +++++--- drivers/dahdi/xpp/xproto.c | 2 +- drivers/dahdi/xpp/xproto.h | 4 ++-- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/drivers/dahdi/xpp/card_global.c b/drivers/dahdi/xpp/card_global.c index cd43d4c..c364dae 100644 --- a/drivers/dahdi/xpp/card_global.c +++ b/drivers/dahdi/xpp/card_global.c @@ -307,9 +307,8 @@ int parse_chip_command(xpd_t *xpd, char *cmdline) BUG_ON(!xpd); xbus = xpd->xbus; - if(XBUS_IS(xbus, DISCONNECTED)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. In state %s.\n", - xbus_statename(XBUS_STATE(xbus))); + if(!XBUS_FLAGS(xbus, CONNECTED)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n"); return -EBUSY; } strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */ diff --git a/drivers/dahdi/xpp/xbus-core.c b/drivers/dahdi/xpp/xbus-core.c index f65d0b1..3399f44 100644 --- a/drivers/dahdi/xpp/xbus-core.c +++ b/drivers/dahdi/xpp/xbus-core.c @@ -90,7 +90,6 @@ const char *xbus_statename(enum xbus_state st) case XBUS_STATE_READY: return "READY"; case XBUS_STATE_DEACTIVATING: return "DEACTIVATING"; case XBUS_STATE_DEACTIVATED: return "DEACTIVATED"; - case XBUS_STATE_DISCONNECTED: return "DISCONNECTED"; case XBUS_STATE_FAIL: return "FAIL"; } return NULL; @@ -481,7 +480,7 @@ static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe) BUG_ON(!xbus); BUG_ON(!xframe); BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - if(XBUS_IS(xbus, DISCONNECTED)) { + if(!XBUS_FLAGS(xbus, CONNECTED)) { XBUS_ERR(xbus, "Dropped command before sending -- hardware deactivated.\n"); dump_xframe("Dropped", xbus, xframe, DBG_ANY); FREE_SEND_XFRAME(xbus, xframe); @@ -562,7 +561,7 @@ int send_cmd_frame(xbus_t *xbus, xframe_t *xframe) BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - if(XBUS_IS(xbus, DISCONNECTED)) { + if(!XBUS_FLAGS(xbus, CONNECTED)) { XBUS_ERR(xbus, "Dropped command before queueing -- hardware deactivated.\n"); ret = -ENODEV; goto err; @@ -627,7 +626,7 @@ void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe) if(rx_tasklet) { xframe_enqueue_recv(xbus, xframe); } else { - if(likely(!XBUS_IS(xbus, DISCONNECTED))) + if(likely(XBUS_FLAGS(xbus, CONNECTED))) xframe_receive(xbus, xframe); else FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ @@ -1103,6 +1102,22 @@ err: return NULL; } +bool xbus_setflags(xbus_t *xbus, int flagbit, bool on) +{ + unsigned long flags; + + spin_lock_irqsave(&xbus->transport.state_lock, flags); + XBUS_DBG(DEVICES, xbus, "%s flag %d\n", + (on) ? "Set" : "Clear", + flagbit); + if(on) + set_bit(flagbit, &(xbus->transport.transport_flags)); + else + clear_bit(flagbit, &(xbus->transport.transport_flags)); + spin_unlock_irqrestore(&xbus->transport.state_lock, flags); + return 1; +} + bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate) { unsigned long flags; @@ -1139,19 +1154,19 @@ bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate) state_flip = 1; /* We are good */ break; case XBUS_STATE_DEACTIVATING: -#if 0 - if(XBUS_IS(xbus, DEACTIVATED) || XBUS_IS(xbus, DISCONNECTED)) + if(XBUS_IS(xbus, DEACTIVATING)) + goto bad_state; + if(XBUS_IS(xbus, DEACTIVATED)) goto bad_state; -#endif break; case XBUS_STATE_DEACTIVATED: if(!XBUS_IS(xbus, DEACTIVATING)) goto bad_state; break; - case XBUS_STATE_DISCONNECTED: - break; case XBUS_STATE_FAIL: - if(XBUS_IS(xbus, DEACTIVATING) || XBUS_IS(xbus, DEACTIVATED) || XBUS_IS(xbus, DISCONNECTED)) + if(XBUS_IS(xbus, DEACTIVATING)) + goto bad_state; + if(XBUS_IS(xbus, DEACTIVATED)) goto bad_state; break; default: @@ -1212,11 +1227,12 @@ int xbus_connect(xbus_t *xbus) BUG_ON(!ops->xframe_send_cmd); BUG_ON(!ops->alloc_xframe); BUG_ON(!ops->free_xframe); + xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 1); xbus_activate(xbus); return 0; } -void xbus_deactivate(xbus_t *xbus, bool is_disconnected) +void xbus_deactivate(xbus_t *xbus) { BUG_ON(!xbus); XBUS_INFO(xbus, "[%s] Deactivating\n", xbus->label); @@ -1230,16 +1246,15 @@ void xbus_deactivate(xbus_t *xbus, bool is_disconnected) xbus_setstate(xbus, XBUS_STATE_DEACTIVATED); worker_reset(xbus->worker); xbus_release_xpds(xbus); - if(!is_disconnected) - xbus_setstate(xbus, XBUS_STATE_IDLE); elect_syncer("deactivate"); } void xbus_disconnect(xbus_t *xbus) { - XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); BUG_ON(!xbus); - xbus_deactivate(xbus, 1); + XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); + xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 0); + xbus_deactivate(xbus); xbus_command_queue_clean(xbus); xbus_command_queue_waitempty(xbus); tasklet_kill(&xbus->receive_tasklet); @@ -1247,7 +1262,6 @@ void xbus_disconnect(xbus_t *xbus) xframe_queue_clear(&xbus->send_pool); xframe_queue_clear(&xbus->receive_pool); xframe_queue_clear(&xbus->pcm_tospan); - xbus_setstate(xbus, XBUS_STATE_DISCONNECTED); del_timer_sync(&xbus->command_timer); transportops_put(xbus); transport_destroy(xbus); @@ -1481,7 +1495,7 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e xbus->busname, xbus->connector, xbus->label, - (!XBUS_IS(xbus, DISCONNECTED)) ? "connected" : "missing" + (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing" ); len += xbus_fill_proc_queue(page + len, &xbus->send_pool); len += xbus_fill_proc_queue(page + len, &xbus->receive_pool); @@ -1726,7 +1740,7 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count, int xbus->busname, xbus->connector, xbus->label, - (!XBUS_IS(xbus, DISCONNECTED)) ? "connected" : "missing" + (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing" ); } } @@ -1763,6 +1777,7 @@ static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_s spin_lock_init(&xbus->transport.state_lock); spin_lock_init(&xbus->transport.lock); atomic_set(&xbus->transport.transport_refcount, 0); + xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 0); init_waitqueue_head(&xbus->transport.transport_unused); } diff --git a/drivers/dahdi/xpp/xbus-core.h b/drivers/dahdi/xpp/xbus-core.h index a24d76b..773d703 100644 --- a/drivers/dahdi/xpp/xbus-core.h +++ b/drivers/dahdi/xpp/xbus-core.h @@ -94,7 +94,6 @@ enum xbus_state { XBUS_STATE_READY, XBUS_STATE_DEACTIVATING, XBUS_STATE_DEACTIVATED, - XBUS_STATE_DISCONNECTED, XBUS_STATE_FAIL, }; @@ -106,6 +105,7 @@ struct xbus_transport { struct device *transport_device; ushort max_send_size; enum xbus_state xbus_state; + unsigned long transport_flags; spinlock_t state_lock; atomic_t transport_refcount; wait_queue_head_t transport_unused; @@ -117,6 +117,9 @@ struct xbus_transport { #define XBUS_IS(xbus, st) (XBUS_STATE(xbus) == XBUS_STATE_ ## st) #define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL) +#define XBUS_FLAG_CONNECTED 0 +#define XBUS_FLAGS(xbus, flg) test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags)) + struct xbus_ops *transportops_get(xbus_t *xbus); void transportops_put(xbus_t *xbus); @@ -300,11 +303,12 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len); xpd_t *xpd_of(const xbus_t *xbus, int xpd_num); xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit); bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate); +bool xbus_setflags(xbus_t *xbus, int flagbit, bool on); xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv); void xbus_free(xbus_t *xbus); int xbus_connect(xbus_t *xbus); int xbus_activate(xbus_t *xbus); -void xbus_deactivate(xbus_t *xbus, bool is_disconnected); +void xbus_deactivate(xbus_t *xbus); void xbus_disconnect(xbus_t *xbus); void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe); int xbus_process_worker(xbus_t *xbus); diff --git a/drivers/dahdi/xpp/xbus-pcm.c b/drivers/dahdi/xpp/xbus-pcm.c index 6522a91..99f9c03 100644 --- a/drivers/dahdi/xpp/xbus-pcm.c +++ b/drivers/dahdi/xpp/xbus-pcm.c @@ -414,7 +414,7 @@ static void reset_sync_counters(void) (e.g: wrong firmware version, etc). */ if(xbus->self_ticking) { - if(XBUS_IS(xbus, DISCONNECTED)) { + if(!XBUS_FLAGS(xbus, CONNECTED)) { XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); } else { @@ -554,7 +554,7 @@ static void update_sync_master(xbus_t *new_syncer, bool force_dahdi) xbus_t *xbus = xbus_num(i); if(!xbus) continue; - if(!XBUS_IS(xbus, DISCONNECTED) && xbus != new_syncer) { + if(XBUS_FLAGS(xbus, CONNECTED) && xbus != new_syncer) { if(xbus->self_ticking) xbus_request_sync(xbus, SYNC_MODE_PLL); else diff --git a/drivers/dahdi/xpp/xbus-sysfs.c b/drivers/dahdi/xpp/xbus-sysfs.c index 63bce35..7f570ea 100644 --- a/drivers/dahdi/xpp/xbus-sysfs.c +++ b/drivers/dahdi/xpp/xbus-sysfs.c @@ -86,7 +86,7 @@ static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count) xbus = dev_to_xbus(dev); XBUS_DBG(GENERAL, xbus, "%s\n", buf); if(strncmp(buf, "stop", 4) == 0) - xbus_deactivate(xbus, 0); + xbus_deactivate(xbus); else if(XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0) xbus_activate(xbus); else { @@ -104,7 +104,7 @@ static DEVICE_ATTR_READER(status_show, dev, buf) int ret; xbus = dev_to_xbus(dev); - ret = snprintf(buf, PAGE_SIZE, "%s\n", (!XBUS_IS(xbus, DISCONNECTED))?"connected":"missing"); + ret = snprintf(buf, PAGE_SIZE, "%s\n", (XBUS_FLAGS(xbus, CONNECTED))?"connected":"missing"); return ret; } @@ -392,7 +392,11 @@ static void astribank_release(struct device *dev) BUG_ON(!dev); xbus = dev_to_xbus(dev); - if(!XBUS_IS(xbus, DISCONNECTED)) { + if(XBUS_FLAGS(xbus, CONNECTED)) { + XBUS_ERR(xbus, "Try to release CONNECTED device.\n"); + BUG(); + } + if(!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, FAIL) && !XBUS_IS(xbus, DEACTIVATED)) { XBUS_ERR(xbus, "Try to release in state %s\n", xbus_statename(XBUS_STATE(xbus))); BUG(); diff --git a/drivers/dahdi/xpp/xproto.c b/drivers/dahdi/xpp/xproto.c index bf51f23..70f82d5 100644 --- a/drivers/dahdi/xpp/xproto.c +++ b/drivers/dahdi/xpp/xproto.c @@ -266,7 +266,7 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe) FREE_RECV_XFRAME(xbus, xframe); return -EPROTO; } - if(XBUS_IS(xbus, DISCONNECTED)) { + if(!XBUS_FLAGS(xbus, CONNECTED)) { XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n"); return -ENODEV; } diff --git a/drivers/dahdi/xpp/xproto.h b/drivers/dahdi/xpp/xproto.h index 0034ab6..efa5e88 100644 --- a/drivers/dahdi/xpp/xproto.h +++ b/drivers/dahdi/xpp/xproto.h @@ -147,9 +147,9 @@ bool valid_xpd_addr(const struct xpd_addr *addr); do { \ int pack_len = RPACKET_SIZE(card,op); \ \ - if(XBUS_IS(xbus, DISCONNECTED)) \ + if(!XBUS_FLAGS(xbus, CONNECTED)) \ return -ENODEV; \ - (frm) = ALLOC_SEND_XFRAME(xbus); \ + (frm) = ALLOC_SEND_XFRAME(xbus); \ if(!(frm)) \ return -ENOMEM; \ (p) = xframe_next_packet(frm, pack_len); \ -- cgit v1.2.3