wcte12xp, wctdm24xxp: Do not call pci_set_drvdata after device initialization.
Instead of using pci_set_drvdata embed the 'struct voicebus_operations' directly in the context so we can use container_of to find the context. This resolves a problem where the 'remove_one' callback gets an invalid pointer to 'struct t1' if the VPMADT032 is in the middle of a reload when the module is unloading. DAHDI-783. Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9554 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
5759e5a6a6
commit
8870b8e1fb
@ -68,17 +68,14 @@ struct private_context {
|
|||||||
struct voicebus *vb;
|
struct voicebus *vb;
|
||||||
void *pvt;
|
void *pvt;
|
||||||
struct completion done;
|
struct completion done;
|
||||||
|
struct voicebus_operations ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void init_private_context(struct private_context *ctx)
|
|
||||||
{
|
|
||||||
init_completion(&ctx->done);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_receive(struct voicebus *vb, struct list_head *buffers)
|
static void handle_receive(struct voicebus *vb, struct list_head *buffers)
|
||||||
{
|
{
|
||||||
struct private_context *ctx = pci_get_drvdata(vb->pdev);
|
|
||||||
struct vbb *vbb;
|
struct vbb *vbb;
|
||||||
|
struct private_context *ctx = container_of(vb->ops,
|
||||||
|
struct private_context, ops);
|
||||||
list_for_each_entry(vbb, buffers, entry) {
|
list_for_each_entry(vbb, buffers, entry) {
|
||||||
__vpmadt032_receive(ctx->pvt, vbb->data);
|
__vpmadt032_receive(ctx->pvt, vbb->data);
|
||||||
if (__vpmadt032_done(ctx->pvt))
|
if (__vpmadt032_done(ctx->pvt))
|
||||||
@ -89,22 +86,24 @@ static void handle_receive(struct voicebus *vb, struct list_head *buffers)
|
|||||||
static void handle_transmit(struct voicebus *vb, struct list_head *buffers)
|
static void handle_transmit(struct voicebus *vb, struct list_head *buffers)
|
||||||
{
|
{
|
||||||
struct vbb *vbb;
|
struct vbb *vbb;
|
||||||
struct private_context *ctx = pci_get_drvdata(vb->pdev);
|
struct private_context *ctx = container_of(vb->ops,
|
||||||
|
struct private_context, ops);
|
||||||
list_for_each_entry(vbb, buffers, entry)
|
list_for_each_entry(vbb, buffers, entry)
|
||||||
__vpmadt032_transmit(ctx->pvt, vbb->data);
|
__vpmadt032_transmit(ctx->pvt, vbb->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct voicebus_operations loader_operations = {
|
static void init_private_context(struct private_context *ctx)
|
||||||
.handle_receive = handle_receive,
|
{
|
||||||
.handle_transmit = handle_transmit,
|
init_completion(&ctx->done);
|
||||||
};
|
ctx->ops.handle_receive = handle_receive;
|
||||||
|
ctx->ops.handle_transmit = handle_transmit;
|
||||||
|
}
|
||||||
|
|
||||||
static int vpmadt032_load_firmware(struct voicebus *vb)
|
static int vpmadt032_load_firmware(struct voicebus *vb)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct private_context *ctx;
|
struct private_context *ctx;
|
||||||
const struct voicebus_operations *old;
|
const struct voicebus_operations *old;
|
||||||
void *old_drvdata;
|
|
||||||
int id;
|
int id;
|
||||||
might_sleep();
|
might_sleep();
|
||||||
ctx = kzalloc(sizeof(struct private_context), GFP_KERNEL);
|
ctx = kzalloc(sizeof(struct private_context), GFP_KERNEL);
|
||||||
@ -121,14 +120,11 @@ static int vpmadt032_load_firmware(struct voicebus *vb)
|
|||||||
ret = __vpmadt032_start_load(0, id, &ctx->pvt);
|
ret = __vpmadt032_start_load(0, id, &ctx->pvt);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
old_drvdata = pci_get_drvdata(vb->pdev);
|
|
||||||
pci_set_drvdata(vb->pdev, ctx);
|
|
||||||
old = vb->ops;
|
old = vb->ops;
|
||||||
vb->ops = &loader_operations;
|
vb->ops = &ctx->ops;
|
||||||
if (!wait_for_completion_timeout(&ctx->done, HZ*20))
|
if (!wait_for_completion_timeout(&ctx->done, HZ*20))
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
vb->ops = old;
|
vb->ops = old;
|
||||||
pci_set_drvdata(vb->pdev, old_drvdata);
|
|
||||||
__vpmadt032_cleanup(ctx->pvt);
|
__vpmadt032_cleanup(ctx->pvt);
|
||||||
error_exit:
|
error_exit:
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user