static int __devexit hsi_char_remove(struct device *dev) { struct hsi_client *cl = to_hsi_client(dev); struct hsi_char_client_data *cl_data = hsi_client_drvdata(cl); struct hsi_char_channel *channel = cl_data->channels; int i; for (i = 0; i < HSI_CHAR_DEVS; i++) { if (!(channel->state & HSI_CHST_AVAIL)) continue; if (cl_data->attached) { hsi_release_port(channel->cl); cl_data->attached = 0; } channel->state = HSI_CHST_UNAVAIL; channel->cl = NULL; channel++; } return 0; }
static int __devinit hsi_char_probe(struct device *dev) { struct hsi_char_client_data *cl_data = &hsi_char_cl_data; struct hsi_char_channel *channel = cl_data->channels; struct hsi_client *cl = to_hsi_client(dev); int i; for (i = 0; i < HSI_CHAR_DEVS; i++) { if (channel->state == HSI_CHST_AVAIL) channel->cl = cl; channel++; } cl->hsi_start_rx = NULL; cl->hsi_stop_rx = NULL; atomic_set(&cl_data->refcnt, 0); atomic_set(&cl_data->breq, 1); cl_data->attached = 0; hsi_client_set_drvdata(cl, cl_data); return 0; }
static int nokia_modem_probe(struct device *dev) { struct device_node *np; struct nokia_modem_device *modem; struct hsi_client *cl = to_hsi_client(dev); struct hsi_port *port = hsi_get_port(cl); int irq, pflags, err; struct hsi_board_info ssip; struct hsi_board_info cmtspeech; np = dev->of_node; if (!np) { dev_err(dev, "device tree node not found\n"); return -ENXIO; } modem = devm_kzalloc(dev, sizeof(*modem), GFP_KERNEL); if (!modem) { dev_err(dev, "Could not allocate memory for nokia_modem_device\n"); return -ENOMEM; } dev_set_drvdata(dev, modem); modem->device = dev; irq = irq_of_parse_and_map(np, 0); if (!irq) { dev_err(dev, "Invalid rst_ind interrupt (%d)\n", irq); return -EINVAL; } modem->nokia_modem_rst_ind_irq = irq; pflags = irq_get_trigger_type(irq); tasklet_init(&modem->nokia_modem_rst_ind_tasklet, do_nokia_modem_rst_ind_tasklet, (unsigned long)modem); err = devm_request_irq(dev, irq, nokia_modem_rst_ind_isr, pflags, "modem_rst_ind", modem); if (err < 0) { dev_err(dev, "Request rst_ind irq(%d) failed (flags %d)\n", irq, pflags); return err; } enable_irq_wake(irq); if(pm) { err = nokia_modem_gpio_probe(dev); if (err < 0) { dev_err(dev, "Could not probe GPIOs\n"); goto error1; } } ssip.name = "ssi-protocol"; ssip.tx_cfg = cl->tx_cfg; ssip.rx_cfg = cl->rx_cfg; ssip.platform_data = NULL; ssip.archdata = NULL; modem->ssi_protocol = hsi_new_client(port, &ssip); if (!modem->ssi_protocol) { dev_err(dev, "Could not register ssi-protocol device\n"); err = -ENOMEM; goto error2; } err = device_attach(&modem->ssi_protocol->device); if (err == 0) { dev_dbg(dev, "Missing ssi-protocol driver\n"); err = -EPROBE_DEFER; goto error3; } else if (err < 0) { dev_err(dev, "Could not load ssi-protocol driver (%d)\n", err); goto error3; } cmtspeech.name = "cmt-speech"; cmtspeech.tx_cfg = cl->tx_cfg; cmtspeech.rx_cfg = cl->rx_cfg; cmtspeech.platform_data = NULL; cmtspeech.archdata = NULL; modem->cmt_speech = hsi_new_client(port, &cmtspeech); if (!modem->cmt_speech) { dev_err(dev, "Could not register cmt-speech device\n"); err = -ENOMEM; goto error3; } err = device_attach(&modem->cmt_speech->device); if (err == 0) { dev_dbg(dev, "Missing cmt-speech driver\n"); err = -EPROBE_DEFER; goto error4; } else if (err < 0) { dev_err(dev, "Could not load cmt-speech driver (%d)\n", err); goto error4; } dev_info(dev, "Registered Nokia HSI modem\n"); return 0; error4: hsi_remove_client(&modem->cmt_speech->device, NULL); error3: hsi_remove_client(&modem->ssi_protocol->device, NULL); error2: nokia_modem_gpio_unexport(dev); error1: disable_irq_wake(modem->nokia_modem_rst_ind_irq); tasklet_kill(&modem->nokia_modem_rst_ind_tasklet); return err; }
struct dlp_channel *dlp_ctrl_ctx_create(unsigned int ch_id, unsigned int hsi_channel, struct device *dev) { struct hsi_client *client = to_hsi_client(dev); struct dlp_channel *ch_ctx; struct dlp_ctrl_context *ctrl_ctx; ch_ctx = kzalloc(sizeof(struct dlp_channel), GFP_KERNEL); if (!ch_ctx) { pr_err(DRVNAME ": Out of memory (ctrl_ch_ctx)\n"); return NULL; } /* Allocate the context private data */ ctrl_ctx = kzalloc(sizeof(struct dlp_ctrl_context), GFP_KERNEL); if (!ctrl_ctx) { pr_err(DRVNAME ": Out of memory (ctrl_ctx)\n"); goto free_ch; } /* Create a workqueue to to manage: * - Modem readiness * - HSI TX timeout */ ctrl_ctx->wq = create_singlethread_workqueue(DRVNAME "-ctrl_wq"); if (!ctrl_ctx->wq) { pr_err(DRVNAME ": Unable to create CTRL workqueue\n"); goto free_ctx; } /* Save params */ ch_ctx->ch_data = ctrl_ctx; ch_ctx->ch_id = ch_id; ch_ctx->hsi_channel = hsi_channel; ch_ctx->rx.config = client->rx_cfg; ch_ctx->tx.config = client->tx_cfg; spin_lock_init(&ch_ctx->lock); INIT_WORK(&ctrl_ctx->tx_timeout_work, dlp_ctrl_handle_tx_timeout); spin_lock_init(&ctrl_ctx->open_lock); /* Register PDUs push, cleanup CBs */ ch_ctx->push_rx_pdus = dlp_ctrl_push_rx_pdus; ch_ctx->cleanup = dlp_ctrl_ctx_cleanup; dlp_xfer_ctx_init(ch_ctx, DLP_CTRL_TX_PDU_SIZE, 0, 0, 0, NULL, HSI_MSG_WRITE); dlp_xfer_ctx_init(ch_ctx, DLP_CTRL_RX_PDU_SIZE, 0, 0, 0, NULL, HSI_MSG_READ); /* Set ch_ctx, not yet done in the probe */ DLP_CHANNEL_CTX(DLP_CHANNEL_CTRL) = ch_ctx; return ch_ctx; free_ctx: kfree(ctrl_ctx); free_ch: kfree(ch_ctx); return NULL; }