wctc4xxp: All the commands do not need to have completions embedded in them.
A small percentage of the total packets sent to the DTE ever wait for completions. This will save on the need to keep the completion around in all the packets. Also, since we can use the presence of the completion as the flag whether we intend to auto free, we can simplify the flags as well. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
parent
ea04099e77
commit
6341783cc8
@ -192,20 +192,15 @@ struct tcb {
|
|||||||
struct list_head node;
|
struct list_head node;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long retries;
|
unsigned long retries;
|
||||||
/* NOTE: these flags aren't bit fields because some of the flags are
|
|
||||||
* combinations of the other ones. */
|
|
||||||
#define DO_NOT_AUTO_FREE (1 << 0)
|
|
||||||
#define TX_COMPLETE (1 << 1)
|
#define TX_COMPLETE (1 << 1)
|
||||||
#define DO_NOT_CAPTURE (1 << 2)
|
#define DO_NOT_CAPTURE (1 << 2)
|
||||||
#define __WAIT_FOR_ACK (1 << 3)
|
#define WAIT_FOR_ACK (1 << 3)
|
||||||
#define __WAIT_FOR_RESPONSE (1 << 4)
|
#define WAIT_FOR_RESPONSE (1 << 4)
|
||||||
#define DTE_CMD_TIMEOUT (1 << 5)
|
#define DTE_CMD_TIMEOUT (1 << 5)
|
||||||
#define WAIT_FOR_ACK (__WAIT_FOR_ACK | DO_NOT_AUTO_FREE)
|
|
||||||
#define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct completion *complete;
|
||||||
struct tcb *response;
|
struct tcb *response;
|
||||||
struct channel_pvt *cpvt;
|
struct channel_pvt *cpvt;
|
||||||
struct completion complete;
|
|
||||||
/* The number of bytes available in data. */
|
/* The number of bytes available in data. */
|
||||||
int data_len;
|
int data_len;
|
||||||
};
|
};
|
||||||
@ -221,7 +216,6 @@ static inline void
|
|||||||
initialize_cmd(struct tcb *cmd, unsigned long cmd_flags)
|
initialize_cmd(struct tcb *cmd, unsigned long cmd_flags)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&cmd->node);
|
INIT_LIST_HEAD(&cmd->node);
|
||||||
init_completion(&cmd->complete);
|
|
||||||
cmd->flags = cmd_flags;
|
cmd->flags = cmd_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,9 +1519,9 @@ static void wctc4xxp_timeout_all_commands(struct wcdte *wc)
|
|||||||
|
|
||||||
list_for_each_entry_safe(cmd, temp, &local_list, node) {
|
list_for_each_entry_safe(cmd, temp, &local_list, node) {
|
||||||
list_del_init(&cmd->node);
|
list_del_init(&cmd->node);
|
||||||
if (cmd->flags & DO_NOT_AUTO_FREE) {
|
if (cmd->complete) {
|
||||||
cmd->flags |= DTE_CMD_TIMEOUT;
|
cmd->flags |= DTE_CMD_TIMEOUT;
|
||||||
complete(&cmd->complete);
|
complete(cmd->complete);
|
||||||
} else {
|
} else {
|
||||||
free_cmd(cmd);
|
free_cmd(cmd);
|
||||||
}
|
}
|
||||||
@ -1592,10 +1586,10 @@ wctc4xxp_transmit_cmd(struct wcdte *wc, struct tcb *cmd)
|
|||||||
/* If we're shutdown all commands will timeout. Just complete the
|
/* If we're shutdown all commands will timeout. Just complete the
|
||||||
* command here with the timeout flag */
|
* command here with the timeout flag */
|
||||||
if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) {
|
if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) {
|
||||||
if (cmd->flags & DO_NOT_AUTO_FREE) {
|
if (cmd->complete) {
|
||||||
cmd->flags |= DTE_CMD_TIMEOUT;
|
cmd->flags |= DTE_CMD_TIMEOUT;
|
||||||
list_del_init(&cmd->node);
|
list_del_init(&cmd->node);
|
||||||
complete(&cmd->complete);
|
complete(cmd->complete);
|
||||||
} else {
|
} else {
|
||||||
list_del(&cmd->node);
|
list_del(&cmd->node);
|
||||||
free_cmd(cmd);
|
free_cmd(cmd);
|
||||||
@ -1611,8 +1605,8 @@ wctc4xxp_transmit_cmd(struct wcdte *wc, struct tcb *cmd)
|
|||||||
WARN_ON(cmd->response);
|
WARN_ON(cmd->response);
|
||||||
WARN_ON(cmd->flags & TX_COMPLETE);
|
WARN_ON(cmd->flags & TX_COMPLETE);
|
||||||
cmd->timeout = jiffies + HZ/4;
|
cmd->timeout = jiffies + HZ/4;
|
||||||
if (cmd->flags & (__WAIT_FOR_ACK | __WAIT_FOR_RESPONSE)) {
|
if (cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE)) {
|
||||||
if (cmd->flags & __WAIT_FOR_RESPONSE) {
|
if (cmd->flags & WAIT_FOR_RESPONSE) {
|
||||||
/* We don't need both an ACK and a response. Let's
|
/* We don't need both an ACK and a response. Let's
|
||||||
* tell the DTE not to generate an ACK, and we'll just
|
* tell the DTE not to generate an ACK, and we'll just
|
||||||
* retry if we do not get the response within the
|
* retry if we do not get the response within the
|
||||||
@ -1646,9 +1640,11 @@ wctc4xxp_transmit_cmd(struct wcdte *wc, struct tcb *cmd)
|
|||||||
static int
|
static int
|
||||||
wctc4xxp_transmit_cmd_and_wait(struct wcdte *wc, struct tcb *cmd)
|
wctc4xxp_transmit_cmd_and_wait(struct wcdte *wc, struct tcb *cmd)
|
||||||
{
|
{
|
||||||
cmd->flags |= DO_NOT_AUTO_FREE;
|
DECLARE_COMPLETION_ONSTACK(done);
|
||||||
|
cmd->complete = &done;
|
||||||
wctc4xxp_transmit_cmd(wc, cmd);
|
wctc4xxp_transmit_cmd(wc, cmd);
|
||||||
wait_for_completion(&cmd->complete);
|
wait_for_completion(&done);
|
||||||
|
cmd->complete = NULL;
|
||||||
if (cmd->flags & DTE_CMD_TIMEOUT) {
|
if (cmd->flags & DTE_CMD_TIMEOUT) {
|
||||||
DTE_DEBUG(DTE_DEBUG_GENERAL, "Timeout waiting for command.\n");
|
DTE_DEBUG(DTE_DEBUG_GENERAL, "Timeout waiting for command.\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -2266,12 +2262,12 @@ static void do_rx_response_packet(struct wcdte *wc, struct tcb *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_del_init(&pos->node);
|
list_del_init(&pos->node);
|
||||||
pos->flags &= ~(__WAIT_FOR_RESPONSE);
|
pos->flags &= ~(WAIT_FOR_RESPONSE);
|
||||||
pos->response = cmd;
|
pos->response = cmd;
|
||||||
/* If this isn't TX_COMPLETE yet, then this packet will
|
/* If this isn't TX_COMPLETE yet, then this packet will
|
||||||
* be completed in service_tx_ring. */
|
* be completed in service_tx_ring. */
|
||||||
if (pos->flags & TX_COMPLETE)
|
if (pos->flags & TX_COMPLETE && pos->complete)
|
||||||
complete(&pos->complete);
|
complete(pos->complete);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2302,21 +2298,21 @@ do_rx_ack_packet(struct wcdte *wc, struct tcb *cmd)
|
|||||||
listhdr = pos->data;
|
listhdr = pos->data;
|
||||||
if (cpu_to_be16(0xefed) == listhdr->ethhdr.h_proto) {
|
if (cpu_to_be16(0xefed) == listhdr->ethhdr.h_proto) {
|
||||||
wc->seq_num = (rxhdr->seq_num + 1) & 0xff;
|
wc->seq_num = (rxhdr->seq_num + 1) & 0xff;
|
||||||
WARN_ON(!(pos->flags & DO_NOT_AUTO_FREE));
|
WARN_ON(!(pos->complete));
|
||||||
WARN_ON(!(pos->flags & TX_COMPLETE));
|
WARN_ON(!(pos->flags & TX_COMPLETE));
|
||||||
list_del_init(&pos->node);
|
list_del_init(&pos->node);
|
||||||
WARN_ON(!(pos->flags & TX_COMPLETE));
|
if (pos->complete)
|
||||||
complete(&pos->complete);
|
complete(pos->complete);
|
||||||
} else if ((listhdr->seq_num == rxhdr->seq_num) &&
|
} else if ((listhdr->seq_num == rxhdr->seq_num) &&
|
||||||
(listhdr->channel == rxhdr->channel)) {
|
(listhdr->channel == rxhdr->channel)) {
|
||||||
if (pos->flags & __WAIT_FOR_RESPONSE) {
|
if (pos->flags & WAIT_FOR_RESPONSE) {
|
||||||
pos->flags &= ~(__WAIT_FOR_ACK);
|
pos->flags &= ~(WAIT_FOR_ACK);
|
||||||
} else {
|
} else {
|
||||||
list_del_init(&pos->node);
|
list_del_init(&pos->node);
|
||||||
|
|
||||||
if (pos->flags & DO_NOT_AUTO_FREE) {
|
if (pos->complete) {
|
||||||
WARN_ON(!(pos->flags & TX_COMPLETE));
|
WARN_ON(!(pos->flags & TX_COMPLETE));
|
||||||
complete(&pos->complete);
|
complete(pos->complete);
|
||||||
} else {
|
} else {
|
||||||
free_cmd(pos);
|
free_cmd(pos);
|
||||||
}
|
}
|
||||||
@ -2368,6 +2364,11 @@ print_command(struct wcdte *wc, const struct tcb *cmd)
|
|||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void wctc4xxp_reset_processor(struct wcdte *wc)
|
||||||
|
{
|
||||||
|
wctc4xxp_setctl(wc, 0x00A0, 0x04000000);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
receive_csm_encaps_packet(struct wcdte *wc, struct tcb *cmd)
|
receive_csm_encaps_packet(struct wcdte *wc, struct tcb *cmd)
|
||||||
{
|
{
|
||||||
@ -2416,6 +2417,7 @@ receive_csm_encaps_packet(struct wcdte *wc, struct tcb *cmd)
|
|||||||
"Received alert (0x%04x) from dsp. Please reload driver.\n",
|
"Received alert (0x%04x) from dsp. Please reload driver.\n",
|
||||||
alert_type);
|
alert_type);
|
||||||
|
|
||||||
|
wctc4xxp_reset_processor(wc);
|
||||||
set_bit(DTE_SHUTDOWN, &wc->flags);
|
set_bit(DTE_SHUTDOWN, &wc->flags);
|
||||||
wctc4xxp_timeout_all_commands(wc);
|
wctc4xxp_timeout_all_commands(wc);
|
||||||
} else {
|
} else {
|
||||||
@ -2509,14 +2511,14 @@ static void service_tx_ring(struct wcdte *wc)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
while ((cmd = wctc4xxp_retrieve(wc->txd))) {
|
while ((cmd = wctc4xxp_retrieve(wc->txd))) {
|
||||||
cmd->flags |= TX_COMPLETE;
|
cmd->flags |= TX_COMPLETE;
|
||||||
if (!(cmd->flags & (__WAIT_FOR_ACK | __WAIT_FOR_RESPONSE))) {
|
if (!(cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE))) {
|
||||||
/* If we're not waiting for an ACK or Response from
|
/* If we're not waiting for an ACK or Response from
|
||||||
* the DTE, this message should not be sitting on any
|
* the DTE, this message should not be sitting on any
|
||||||
* lists. */
|
* lists. */
|
||||||
WARN_ON(!list_empty(&cmd->node));
|
WARN_ON(!list_empty(&cmd->node));
|
||||||
if (DO_NOT_AUTO_FREE & cmd->flags) {
|
if (cmd->complete) {
|
||||||
WARN_ON(!(cmd->flags & TX_COMPLETE));
|
WARN_ON(!(cmd->flags & TX_COMPLETE));
|
||||||
complete(&cmd->complete);
|
complete(cmd->complete);
|
||||||
} else {
|
} else {
|
||||||
free_cmd(cmd);
|
free_cmd(cmd);
|
||||||
}
|
}
|
||||||
@ -2882,6 +2884,7 @@ wctc4xxp_load_firmware(struct wcdte *wc, const struct firmware *firmware)
|
|||||||
unsigned int byteloc;
|
unsigned int byteloc;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
struct tcb *cmd;
|
struct tcb *cmd;
|
||||||
|
DECLARE_COMPLETION_ONSTACK(done);
|
||||||
|
|
||||||
byteloc = 17;
|
byteloc = 17;
|
||||||
|
|
||||||
@ -2902,8 +2905,9 @@ wctc4xxp_load_firmware(struct wcdte *wc, const struct firmware *firmware)
|
|||||||
memcpy(cmd->data, &firmware->data[byteloc], length);
|
memcpy(cmd->data, &firmware->data[byteloc], length);
|
||||||
byteloc += length;
|
byteloc += length;
|
||||||
cmd->flags = WAIT_FOR_ACK;
|
cmd->flags = WAIT_FOR_ACK;
|
||||||
|
cmd->complete = &done;
|
||||||
wctc4xxp_transmit_cmd(wc, cmd);
|
wctc4xxp_transmit_cmd(wc, cmd);
|
||||||
wait_for_completion(&cmd->complete);
|
wait_for_completion(&done);
|
||||||
if (cmd->flags & DTE_CMD_TIMEOUT) {
|
if (cmd->flags & DTE_CMD_TIMEOUT) {
|
||||||
free_cmd(cmd);
|
free_cmd(cmd);
|
||||||
dev_err(&wc->pdev->dev, "Failed to load firmware.\n");
|
dev_err(&wc->pdev->dev, "Failed to load firmware.\n");
|
||||||
@ -2938,8 +2942,7 @@ wctc4xxp_turn_off_booted_led(struct wcdte *wc)
|
|||||||
DTE_DEBUG(DTE_DEBUG_GENERAL, "PHY register 0 = %X\n",
|
DTE_DEBUG(DTE_DEBUG_GENERAL, "PHY register 0 = %X\n",
|
||||||
wctc4xxp_read_phy(wc, 0));
|
wctc4xxp_read_phy(wc, 0));
|
||||||
|
|
||||||
/* Set reset */
|
wctc4xxp_reset_processor(wc);
|
||||||
wctc4xxp_setctl(wc, 0x00A0, 0x04000000);
|
|
||||||
|
|
||||||
/* Wait 4 ms to ensure processor reset */
|
/* Wait 4 ms to ensure processor reset */
|
||||||
msleep(4);
|
msleep(4);
|
||||||
@ -3306,8 +3309,10 @@ wctc4xxp_watchdog(unsigned long data)
|
|||||||
|
|
||||||
cmd->flags |= DTE_CMD_TIMEOUT;
|
cmd->flags |= DTE_CMD_TIMEOUT;
|
||||||
list_del_init(&cmd->node);
|
list_del_init(&cmd->node);
|
||||||
complete(&cmd->complete);
|
if (cmd->complete)
|
||||||
|
complete(cmd->complete);
|
||||||
|
|
||||||
|
wctc4xxp_reset_processor(wc);
|
||||||
set_bit(DTE_SHUTDOWN, &wc->flags);
|
set_bit(DTE_SHUTDOWN, &wc->flags);
|
||||||
spin_unlock(&wc->cmd_list_lock);
|
spin_unlock(&wc->cmd_list_lock);
|
||||||
_wctc4xxp_stop_dma(wc);
|
_wctc4xxp_stop_dma(wc);
|
||||||
@ -3323,7 +3328,8 @@ wctc4xxp_watchdog(unsigned long data)
|
|||||||
*/
|
*/
|
||||||
cmd->flags |= DTE_CMD_TIMEOUT;
|
cmd->flags |= DTE_CMD_TIMEOUT;
|
||||||
list_del_init(&cmd->node);
|
list_del_init(&cmd->node);
|
||||||
complete(&cmd->complete);
|
if (cmd->complete)
|
||||||
|
complete(cmd->complete);
|
||||||
} else if (cmd->flags & TX_COMPLETE) {
|
} else if (cmd->flags & TX_COMPLETE) {
|
||||||
/* Move this to the local list because we're
|
/* Move this to the local list because we're
|
||||||
* going to resend it once we free the locks
|
* going to resend it once we free the locks
|
||||||
|
Loading…
Reference in New Issue
Block a user