static int recv_stream(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t buf_len, int flags) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sk_buff *buf; struct tipc_msg *msg; unsigned int sz; int sz_to_copy, target, needed; int sz_copied = 0; char __user *crs = m->msg_iov->iov_base; unsigned char *buf_crs; u32 err; int res = 0; /* Catch invalid receive attempts */ if (m->msg_iovlen != 1) return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ if (unlikely(!buf_len)) return -EINVAL; lock_sock(sk); if (unlikely((sock->state == SS_UNCONNECTED) || (sock->state == SS_CONNECTING))) { res = -ENOTCONN; goto exit; } target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); restart: /* Look for a message in receive queue; wait if necessary */ while (skb_queue_empty(&sk->sk_receive_queue)) { if (sock->state == SS_DISCONNECTING) { res = -ENOTCONN; goto exit; } if (flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; goto exit; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue) || (sock->state == SS_DISCONNECTING))); lock_sock(sk); if (res) goto exit; } /* Look at first message in receive queue */ buf = skb_peek(&sk->sk_receive_queue); msg = buf_msg(buf); sz = msg_data_sz(msg); err = msg_errcode(msg); /* Discard an empty non-errored message & try again */ if ((!sz) && (!err)) { advance_rx_queue(sk); goto restart; } /* Optionally capture sender's address & ancillary data of first msg */ if (sz_copied == 0) { set_orig_addr(m, msg); res = anc_data_recv(m, msg, tport); if (res) goto exit; } /* Capture message data (if valid) & compute return value (always) */ if (!err) { buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); sz = (unsigned char *)msg + msg_size(msg) - buf_crs; needed = (buf_len - sz_copied); sz_to_copy = (sz <= needed) ? sz : needed; if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { res = -EFAULT; goto exit; } sz_copied += sz_to_copy; if (sz_to_copy < sz) { if (!(flags & MSG_PEEK)) TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; goto exit; } crs += sz_to_copy; } else { if (sz_copied != 0) goto exit; /* can't add error msg to valid data */ if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) res = 0; else res = -ECONNRESET; } /* Consume received message (optional) */ if (likely(!(flags & MSG_PEEK))) { if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) tipc_acknowledge(tport->ref, tport->conn_unacked); advance_rx_queue(sk); } /* Loop around if more data is required */ if ((sz_copied < buf_len) && /* didn't get all requested data */ (!skb_queue_empty(&sk->sk_receive_queue) || (sz_copied < target)) && /* and more is ready or required */ (!(flags & MSG_PEEK)) && /* and aren't just peeking at data */ (!err)) /* and haven't reached a FIN */ goto restart; exit: release_sock(sk); return sz_copied ? sz_copied : res; }
static int akmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *) arg; char rwbuf[16]; char databuf[RBUFF_SIZE]; int ret = -1; int status; int value[3]; short delay; short mode; struct akm8975_data *akm = file->private_data; FUNCDBG("called"); switch (cmd) { case ECS_IOCTL_READ: case ECS_IOCTL_WRITE: if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) return -EFAULT; break; case ECS_IOCTL_SET_MODE: if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; break; case ECS_IOCTL_SET_YPR: if (copy_from_user(&value, argp, sizeof(value))) return -EFAULT; break; default: break; } switch (cmd) { case ECS_IOCTL_READ: if ((rwbuf[0] > AK8975_FUSE_ASAZ) || (rwbuf[1] < 1) || (rwbuf[1] > 3)) { pr_err("AKM8975 IOCTL_READ invalid argument: %d, %d\n", (int)rwbuf[0], (int)rwbuf[1]); return -EINVAL; } ret = akm8975_i2c_rxdata(akm, rwbuf[0], rwbuf[1], &rwbuf[2]); if (ret < 0) return ret; break; case ECS_IOCTL_WRITE: if (rwbuf[0] < 2) return -EINVAL; ret = akm8975_i2c_txdata(akm, rwbuf[0], rwbuf[1]); if (ret < 0) return ret; break; case ECS_IOCTL_SET_MODE: ret = akm8975_ecs_set_mode(akm, (char) mode); if (ret < 0) return ret; if (mode == AK8975_MODE_SNG_MEASURE) { /* wait for data to become ready */ ret = wait_for_completion_interruptible_timeout(&akm->data_ready, msecs_to_jiffies(AK8975_MAX_CONVERSION_TIMEOUT)); if (ret < 0) { pr_err("AKM8975 conversion timeout happened\n"); return -EINVAL; } } break; case ECS_IOCTL_GETDATA: ret = akm8975_ecs_get_data(akm, RBUFF_SIZE, databuf); if (ret < 0) return ret; case ECS_IOCTL_SET_YPR: akm8975_ecs_report_value(akm, value); break; case ECS_IOCTL_GET_OPEN_STATUS: wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0)); status = atomic_read(&open_flag); break; case ECS_IOCTL_GET_CLOSE_STATUS: wait_event_interruptible(open_wq, (atomic_read(&open_flag) == 0)); status = atomic_read(&open_flag); break; case ECS_IOCTL_GET_DELAY: delay = akmd_delay; break; default: FUNCDBG("Unknown cmd\n"); return -ENOTTY; } switch (cmd) { case ECS_IOCTL_READ: if (copy_to_user(argp, &rwbuf[2], rwbuf[1])) return -EFAULT; break; case ECS_IOCTL_GETDATA: if (copy_to_user(argp, &databuf, RBUFF_SIZE)) return -EFAULT; break; case ECS_IOCTL_GET_OPEN_STATUS: case ECS_IOCTL_GET_CLOSE_STATUS: if (copy_to_user(argp, &status, sizeof(status))) return -EFAULT; break; case ECS_IOCTL_GET_DELAY: if (copy_to_user(argp, &delay, sizeof(delay))) return -EFAULT; break; default: break; } return 0; }
static ssize_t pn544_dev_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { struct pn544_dev *pn544_dev = filp->private_data; char tmp[MAX_BUFFER_SIZE]; int ret; if (count > MAX_BUFFER_SIZE) count = MAX_BUFFER_SIZE; pr_debug("%s : reading %zu bytes.\n", __func__, count); #ifdef FEATURE_PN544_KERNEL_LOG pr_info("==> %s #1 (ven, firm, irq)=(%d, %d, %d)\n", __func__, gpio_get_value(pn544_dev->ven_gpio), gpio_get_value(pn544_dev->firm_gpio), gpio_get_value(pn544_dev->irq_gpio)); #endif mutex_lock(&pn544_dev->read_mutex); if (!gpio_get_value(pn544_dev->irq_gpio)) { if (filp->f_flags & O_NONBLOCK) { ret = -EAGAIN; goto fail; } pn544_dev->irq_enabled = true; #ifdef READ_IRQ_MODIFY do_reading=0; #endif enable_irq(pn544_dev->client->irq); #ifdef READ_IRQ_MODIFY ret = wait_event_interruptible(pn544_dev->read_wq, do_reading); #else ret = wait_event_interruptible(pn544_dev->read_wq, gpio_get_value(pn544_dev->irq_gpio)); #endif pn544_disable_irq(pn544_dev); #ifdef READ_IRQ_MODIFY if(cancle_read == true) { cancle_read = false; ret = -1; goto fail; } #endif if (ret) goto fail; } #ifdef FEATURE_PN544_KERNEL_LOG pr_info("==> %s #2 (ven, firm, irq)=(%d, %d, %d)\n", __func__, gpio_get_value(pn544_dev->ven_gpio), gpio_get_value(pn544_dev->firm_gpio), gpio_get_value(pn544_dev->irq_gpio)); #endif /* Read data */ ret = i2c_master_recv(pn544_dev->client, tmp, count); mutex_unlock(&pn544_dev->read_mutex); if (ret < 0) { pr_err("%s: i2c_master_recv returned %d\n", __func__, ret); return ret; } if (ret > count) { pr_err("%s: received too many bytes from i2c (%d)\n", __func__, ret); return -EIO; } if (copy_to_user(buf, tmp, ret)) { pr_warning("%s : failed to copy to user space\n", __func__); return -EFAULT; } return ret; fail: mutex_unlock(&pn544_dev->read_mutex); return ret; }
int do_syslog(int type, char __user *buf, int len, bool from_file) { unsigned i, j, limit, count; int do_clear = 0; char c; int error; error = check_syslog_permissions(type, from_file); if (error) goto out; error = security_syslog(type); if (error) return error; switch (type) { case SYSLOG_ACTION_CLOSE: /* Close log */ break; case SYSLOG_ACTION_OPEN: /* Open log */ break; case SYSLOG_ACTION_READ: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; /* Read/clear last kernel messages */ case SYSLOG_ACTION_READ_CLEAR: do_clear = 1; /* FALL THRU */ /* Read last kernel messages */ case SYSLOG_ACTION_READ_ALL: error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; /* Clear ring buffer */ case SYSLOG_ACTION_CLEAR: logged_chars = 0; break; /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_OFF: if (saved_console_loglevel == -1) saved_console_loglevel = console_loglevel; console_loglevel = minimum_console_loglevel; break; /* Enable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: if (saved_console_loglevel != -1) { console_loglevel = saved_console_loglevel; saved_console_loglevel = -1; } break; /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; /* Implicitly re-enable logging to console */ saved_console_loglevel = -1; error = 0; break; /* Number of chars in the log buffer */ case SYSLOG_ACTION_SIZE_UNREAD: error = log_end - log_start; break; /* Size of the log buffer */ case SYSLOG_ACTION_SIZE_BUFFER: error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
/* * This function removes the card. * * This function follows the following major steps to remove the device - * - Stop data traffic * - Shutdown firmware * - Remove the logical interfaces * - Terminate the work queue * - Unregister the device * - Free the adapter structure */ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) { struct mwifiex_private *priv = NULL; int i; if (down_trylock(sem)) goto exit_sem_err; if (!adapter) goto exit_remove; /* We can no longer handle interrupts once we start doing the teardown * below. */ if (adapter->if_ops.disable_int) adapter->if_ops.disable_int(adapter); adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv && priv->netdev) { mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); } } mwifiex_dbg(adapter, CMD, "cmd: calling mwifiex_shutdown_drv...\n"); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); mwifiex_dbg(adapter, CMD, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || atomic_read(&adapter->tx_pending) || atomic_read(&adapter->cmd_pending)) { mwifiex_dbg(adapter, ERROR, "rx_pending=%d, tx_pending=%d,\t" "cmd_pending=%d\n", atomic_read(&adapter->rx_pending), atomic_read(&adapter->tx_pending), atomic_read(&adapter->cmd_pending)); } for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (!priv) continue; rtnl_lock(); if (priv->netdev && priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); rtnl_unlock(); } wiphy_unregister(adapter->wiphy); wiphy_free(adapter->wiphy); /* Unregister device */ mwifiex_dbg(adapter, INFO, "info: unregister device\n"); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); /* Free adapter structure */ mwifiex_dbg(adapter, INFO, "info: free adapter\n"); mwifiex_free_adapter(adapter); exit_remove: up(sem); exit_sem_err: return 0; }
/* * Alon: This function should write the buffer given by the user into the file. * The function assumes the given buffer is encrypted, and will therefor * use the iKey to decypher each character before writing it to the file. * The function returns the amount of bytes it managed to write into the * file, and -1 in case of failure. */ ssize_t my_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { if(check_buffer_size(count) != 0) { return -EINVAL; } int minor = get_minor_from_file(filp); int is_this_process_reader = is_reader(filp); int key = ((device_private_data *)((filp)->private_data))->private_key; down_interruptible(&write_lock[minor]); down_interruptible(&index_lock[minor]); int maxToWrite = get_max_to_write(minor); if (maxToWrite == 0) { int current_num_of_readers = get_current_num_of_readers(minor); if(current_num_of_readers == is_this_process_reader) { up(&index_lock[minor]); up(&write_lock[minor]); return 0; } //Going to sleep until a reader clears some room in the buffer up(&index_lock[minor]); int wake_up_reason = wait_event_interruptible(write_wq[minor], flag_is_full[minor] == 0 || get_current_num_of_readers(minor) == is_this_process_reader); if(wake_up_reason != 0) { up(&write_lock[minor]); return -EINTR; } if (get_current_num_of_readers(minor) == is_this_process_reader) { up(&write_lock[minor]); return 0; } down_interruptible(&index_lock[minor]); maxToWrite = get_max_to_write(minor); } int numToWrite = MIN(maxToWrite,count); int firstPartSize = 0; int retval = 0; char* tmpBuf =(char*)kmalloc(sizeof(char)*numToWrite,GFP_KERNEL); if (!tmpBuf){ up(&index_lock[minor]); up(&write_lock[minor]); return -ENOMEM; } retval = copy_from_user(tmpBuf, buf, numToWrite); //copy the data from user if(retval != 0){ kfree(tmpBuf); up(&index_lock[minor]); up(&write_lock[minor]); return retval; } int numOfParts = ( (writing_position[minor] + numToWrite) > BUF_SIZE) ? TWO : ONE ; if(numOfParts == ONE ) { if (minor == 1) { encryptor(tmpBuf, &buffer[minor][writing_position[minor]], numToWrite, key, minor); } else if(minor == 0){ memcpy(&buffer[minor][ writing_position[minor] ], tmpBuf, numToWrite); } writing_position[minor] = (writing_position[minor] + numToWrite) % BUF_SIZE; } else { firstPartSize = BUF_SIZE - writing_position[minor]; if (minor == 1) { encryptor(tmpBuf, &buffer[minor][writing_position[minor]], firstPartSize, key, minor); encryptor(tmpBuf + firstPartSize, &buffer[minor][0], numToWrite - firstPartSize, key, minor); } else if (minor == 0) { memcpy(&buffer[minor][writing_position[minor]], tmpBuf, firstPartSize); memcpy(&buffer[minor][0], tmpBuf + firstPartSize, numToWrite - firstPartSize); } writing_position[minor] = (numToWrite - firstPartSize); } if(( writing_position[minor] == reading_position[minor]) && numToWrite){ flag_is_full[minor] = 1; } if (numToWrite) { flag_is_empty[minor] = 0; wake_up_interruptible(&read_wq[minor]); } /* * If we wrote something into the buffer, this makes sure to wake up * any writer who may be waiting for input. */ kfree(tmpBuf); up(&index_lock[minor]); up(&write_lock[minor]); if(retval != 0){ return retval; } return numToWrite; }
/* * iowarrior_write */ static ssize_t iowarrior_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos) { struct iowarrior *dev; int retval = 0; char *buf = NULL; /* for IOW24 and IOW56 we need a buffer */ struct urb *int_out_urb = NULL; dev = file->private_data; mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ if (!dev->present) { retval = -ENODEV; goto exit; } dbg("%s - minor %d, count = %zd", __func__, dev->minor, count); /* if count is 0 we're already done */ if (count == 0) { retval = 0; goto exit; } /* We only accept full reports */ if (count != dev->report_size) { retval = -EINVAL; goto exit; } switch (dev->product_id) { case USB_DEVICE_ID_CODEMERCS_IOW24: case USB_DEVICE_ID_CODEMERCS_IOWPV1: case USB_DEVICE_ID_CODEMERCS_IOWPV2: case USB_DEVICE_ID_CODEMERCS_IOW40: /* IOW24 and IOW40 use a synchronous call */ buf = kmalloc(8, GFP_KERNEL); /* 8 bytes are enough for both products */ if (!buf) { retval = -ENOMEM; goto exit; } if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; kfree(buf); goto exit; } retval = usb_set_report(dev->interface, 2, 0, buf, count); kfree(buf); goto exit; break; case USB_DEVICE_ID_CODEMERCS_IOW56: /* The IOW56 uses asynchronous IO and more urbs */ if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) { /* Wait until we are below the limit for submitted urbs */ if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; goto exit; } else { retval = wait_event_interruptible(dev->write_wait, (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT))); if (retval) { /* we were interrupted by a signal */ retval = -ERESTART; goto exit; } if (!dev->present) { /* The device was unplugged */ retval = -ENODEV; goto exit; } if (!dev->opened) { /* We were closed while waiting for an URB */ retval = -ENODEV; goto exit; } } } atomic_inc(&dev->write_busy); int_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!int_out_urb) { retval = -ENOMEM; dbg("%s Unable to allocate urb ", __func__); goto error_no_urb; } buf = usb_alloc_coherent(dev->udev, dev->report_size, GFP_KERNEL, &int_out_urb->transfer_dma); if (!buf) { retval = -ENOMEM; dbg("%s Unable to allocate buffer ", __func__); goto error_no_buffer; } usb_fill_int_urb(int_out_urb, dev->udev, usb_sndintpipe(dev->udev, dev->int_out_endpoint->bEndpointAddress), buf, dev->report_size, iowarrior_write_callback, dev, dev->int_out_endpoint->bInterval); int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error; } retval = usb_submit_urb(int_out_urb, GFP_KERNEL); if (retval) { dbg("%s submit error %d for urb nr.%d", __func__, retval, atomic_read(&dev->write_busy)); goto error; } /* submit was ok */ retval = count; usb_free_urb(int_out_urb); goto exit; break; default: /* what do we have here ? An unsupported Product-ID ? */ dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n", __func__, dev->product_id); retval = -EFAULT; goto exit; break; } error: usb_free_coherent(dev->udev, dev->report_size, buf, int_out_urb->transfer_dma); error_no_buffer: usb_free_urb(int_out_urb); error_no_urb: atomic_dec(&dev->write_busy); wake_up_interruptible(&dev->write_wait); exit: mutex_unlock(&dev->mutex); return retval; }
/* * This function gets firmware and initializes it. * * The main initialization steps followed are - * - Download the correct firmware to card * - Issue the init commands to firmware */ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) { int ret; char fmt[64]; struct mwifiex_private *priv; struct mwifiex_adapter *adapter = context; struct mwifiex_fw_image fw; if (!firmware) { dev_err(adapter->dev, "Failed to get firmware %s\n", adapter->fw_name); goto done; } memset(&fw, 0, sizeof(struct mwifiex_fw_image)); adapter->firmware = firmware; fw.fw_buf = (u8 *) adapter->firmware->data; fw.fw_len = adapter->firmware->size; if (adapter->if_ops.dnld_fw) ret = adapter->if_ops.dnld_fw(adapter, &fw); else ret = mwifiex_dnld_fw(adapter, &fw); if (ret == -1) goto done; dev_notice(adapter->dev, "WLAN FW is active\n"); adapter->init_wait_q_woken = false; ret = mwifiex_init_fw(adapter); if (ret == -1) { goto done; } else if (!ret) { adapter->hw_status = MWIFIEX_HW_STATUS_READY; goto done; } /* Wait for mwifiex_init to complete */ wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) goto done; priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; if (mwifiex_register_cfg80211(adapter)) { dev_err(adapter->dev, "cannot register with cfg80211\n"); goto err_init_fw; } rtnl_lock(); /* Create station interface by default */ if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NL80211_IFTYPE_STATION, NULL, NULL)) { dev_err(adapter->dev, "cannot create default STA interface\n"); goto err_add_intf; } rtnl_unlock(); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); dev_notice(adapter->dev, "driver_version = %s\n", fmt); goto done; err_add_intf: mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); rtnl_unlock(); err_init_fw: pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); done: release_firmware(adapter->firmware); complete(&adapter->fw_load); return; }
/* * This function adds the card. * * This function follows the following major steps to set up the device - * - Initialize software. This includes probing the card, registering * the interface operations table, and allocating/initializing the * adapter structure * - Set up the netlink socket * - Create and start the main work queue * - Register the device * - Initialize firmware and hardware * - Add logical interfaces */ int mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops, u8 iface_type) { struct mwifiex_adapter *adapter; if (down_interruptible(sem)) goto exit_sem_err; if (mwifiex_register(card, if_ops, (void **)&adapter)) { pr_err("%s: software init failed\n", __func__); goto err_init_sw; } adapter->iface_type = iface_type; adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; adapter->surprise_removed = false; init_waitqueue_head(&adapter->init_wait_q); adapter->is_suspended = false; adapter->hs_activated = false; init_waitqueue_head(&adapter->hs_activate_wait_q); adapter->cmd_wait_q_required = false; init_waitqueue_head(&adapter->cmd_wait_q.wait); adapter->cmd_wait_q.status = 0; adapter->scan_wait_q_woken = false; adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); if (!adapter->workqueue) goto err_kmalloc; INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); /* Register the device. Fill up the private data structure with relevant information from the card and request for the required IRQ. */ if (adapter->if_ops.register_dev(adapter)) { pr_err("%s: failed to register mwifiex device\n", __func__); goto err_registerdev; } if (mwifiex_init_hw_fw(adapter)) { pr_err("%s: firmware init failed\n", __func__); goto err_init_fw; } up(sem); return 0; err_init_fw: pr_debug("info: %s: unregister device\n", __func__); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); err_registerdev: adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); err_kmalloc: if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) || (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) { pr_debug("info: %s: shutdown mwifiex\n", __func__); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); } mwifiex_free_adapter(adapter); err_init_sw: up(sem); exit_sem_err: return -1; }
static ssize_t rmnet_ctl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int retval = 0; int bytes_to_read; unsigned int hdr_len = 0; struct rmnet_ctrl_dev *dev; struct ctrl_pkt_list_elem *list_elem = NULL; unsigned long flags; dev = file->private_data; if (!dev) return -ENODEV; DBG("%s: Read from %s\n", __func__, dev->name); ctrl_read: if (!test_bit(RMNET_CTRL_DEV_READY, &dev->status)) { dev_dbg(dev->devicep, "%s: Device not connected\n", __func__); return -ENETRESET; } spin_lock_irqsave(&dev->rx_lock, flags); if (list_empty(&dev->rx_list)) { spin_unlock_irqrestore(&dev->rx_lock, flags); retval = wait_event_interruptible(dev->read_wait_queue, !list_empty(&dev->rx_list) || !test_bit(RMNET_CTRL_DEV_READY, &dev->status)); if (retval < 0) return retval; goto ctrl_read; } list_elem = list_first_entry(&dev->rx_list, struct ctrl_pkt_list_elem, list); bytes_to_read = (uint32_t)(list_elem->cpkt.data_size); if (bytes_to_read > count) { spin_unlock_irqrestore(&dev->rx_lock, flags); dev_err(dev->devicep, "%s: Packet size %d > buf size %d\n", __func__, bytes_to_read, count); return -ENOMEM; } spin_unlock_irqrestore(&dev->rx_lock, flags); if (test_bit(RMNET_CTRL_DEV_MUX_EN, &dev->status)) hdr_len = sizeof(struct mux_hdr); if (copy_to_user(buf, list_elem->cpkt.data + hdr_len, bytes_to_read)) { dev_err(dev->devicep, "%s: copy_to_user failed for %s\n", __func__, dev->name); return -EFAULT; } spin_lock_irqsave(&dev->rx_lock, flags); list_del(&list_elem->list); spin_unlock_irqrestore(&dev->rx_lock, flags); kfree(list_elem->cpkt.data); kfree(list_elem); DBG("%s: Returning %d bytes to %s\n", __func__, bytes_to_read, dev->name); DUMP_BUFFER("Read: ", bytes_to_read, buf); return bytes_to_read; }
/* transmit out IR pulses; what you get here is a batch of alternating * pulse/space/pulse/space lengths that we should write out completely through * the FIFO, blocking on a full FIFO */ static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n) { unsigned long flags; struct ite_dev *dev = rcdev->priv; bool is_pulse = false; int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; int max_rle_us, next_rle_us; int ret = n; u8 last_sent[ITE_TX_FIFO_LEN]; u8 val; ite_dbg("%s called", __func__); /* clear the array just in case */ memset(last_sent, 0, ARRAY_SIZE(last_sent)); /* n comes in bytes; convert to ints */ n /= sizeof(int); spin_lock_irqsave(&dev->lock, flags); /* let everybody know we're now transmitting */ dev->transmitting = true; /* and set the carrier values for transmission */ ite_set_carrier_params(dev); /* calculate how much time we can send in one byte */ max_rle_us = (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * ITE_TX_MAX_RLE) / 1000; /* disable the receiver */ dev->params.disable_rx(dev); /* this is where we'll begin filling in the FIFO, until it's full. * then we'll just activate the interrupt, wait for it to wake us up * again, disable it, continue filling the FIFO... until everything * has been pushed out */ fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); while (n > 0 && dev->in_use) { /* transmit the next sample */ is_pulse = !is_pulse; remaining_us = *(txbuf++); n--; ite_dbg("%s: %ld", ((is_pulse) ? "pulse" : "space"), (long int) remaining_us); /* repeat while the pulse is non-zero length */ while (remaining_us > 0 && dev->in_use) { if (remaining_us > max_rle_us) next_rle_us = max_rle_us; else next_rle_us = remaining_us; remaining_us -= next_rle_us; /* check what's the length we have to pump out */ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; /* put it into the sent buffer */ last_sent[last_idx++] = val; last_idx &= (ITE_TX_FIFO_LEN); /* encode it for 7 bits */ val = (val - 1) & ITE_TX_RLE_MASK; /* take into account pulse/space prefix */ if (is_pulse) val |= ITE_TX_PULSE; else val |= ITE_TX_SPACE; /* * if we get to 0 available, read again, just in case * some other slot got freed */ if (fifo_avail <= 0) fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); /* if it's still full */ if (fifo_avail <= 0) { /* enable the tx interrupt */ dev->params. enable_tx_interrupt(dev); /* drop the spinlock */ spin_unlock_irqrestore(&dev->lock, flags); /* wait for the FIFO to empty enough */ wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8); /* get the spinlock again */ spin_lock_irqsave(&dev->lock, flags); /* disable the tx interrupt again. */ dev->params. disable_tx_interrupt(dev); } /* now send the byte through the FIFO */ dev->params.put_tx_byte(dev, val); fifo_avail--; } } /* wait and don't return until the whole FIFO has been sent out; * otherwise we could configure the RX carrier params instead of the * TX ones while the transmission is still being performed! */ fifo_remaining = dev->params.get_tx_used_slots(dev); remaining_us = 0; while (fifo_remaining > 0) { fifo_remaining--; last_idx--; last_idx &= (ITE_TX_FIFO_LEN - 1); remaining_us += last_sent[last_idx]; } remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); /* drop the spinlock while we sleep */ spin_unlock_irqrestore(&dev->lock, flags); /* sleep remaining_us microseconds */ mdelay(DIV_ROUND_UP(remaining_us, 1000)); /* reacquire the spinlock */ spin_lock_irqsave(&dev->lock, flags); /* now we're not transmitting anymore */ dev->transmitting = false; /* and set the carrier values for reception */ ite_set_carrier_params(dev); /* reenable the receiver */ if (dev->in_use) dev->params.enable_rx(dev); /* notify transmission end */ wake_up_interruptible(&dev->tx_ended); spin_unlock_irqrestore(&dev->lock, flags); return ret; }
static int recv_msg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t buf_len, int flags) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sk_buff *buf; struct tipc_msg *msg; unsigned int sz; u32 err; int res; /* Catch invalid receive requests */ if (m->msg_iovlen != 1) return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */ if (unlikely(!buf_len)) return -EINVAL; lock_sock(sk); if (unlikely(sock->state == SS_UNCONNECTED)) { res = -ENOTCONN; goto exit; } restart: /* Look for a message in receive queue; wait if necessary */ while (skb_queue_empty(&sk->sk_receive_queue)) { if (sock->state == SS_DISCONNECTING) { res = -ENOTCONN; goto exit; } if (flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; goto exit; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue) || (sock->state == SS_DISCONNECTING))); lock_sock(sk); if (res) goto exit; } /* Look at first message in receive queue */ buf = skb_peek(&sk->sk_receive_queue); msg = buf_msg(buf); sz = msg_data_sz(msg); err = msg_errcode(msg); /* Complete connection setup for an implied connect */ if (unlikely(sock->state == SS_CONNECTING)) { res = auto_connect(sock, msg); if (res) goto exit; } /* Discard an empty non-errored message & try again */ if ((!sz) && (!err)) { advance_rx_queue(sk); goto restart; } /* Capture sender's address (optional) */ set_orig_addr(m, msg); /* Capture ancillary data (optional) */ res = anc_data_recv(m, msg, tport); if (res) goto exit; /* Capture message data (if valid) & compute return value (always) */ if (!err) { if (unlikely(buf_len < sz)) { sz = buf_len; m->msg_flags |= MSG_TRUNC; } if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), sz))) { res = -EFAULT; goto exit; } res = sz; } else { if ((sock->state == SS_READY) || ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) res = 0; else res = -ECONNRESET; } /* Consume received message (optional) */ if (likely(!(flags & MSG_PEEK))) { if ((sock->state != SS_READY) && (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) tipc_acknowledge(tport->ref, tport->conn_unacked); advance_rx_queue(sk); } exit: release_sock(sk); return res; }
static int send_msg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; int needs_conn; int res = -EINVAL; if (unlikely(!dest)) return -EDESTADDRREQ; if (unlikely((m->msg_namelen < sizeof(*dest)) || (dest->family != AF_TIPC))) return -EINVAL; if (iocb) lock_sock(sk); needs_conn = (sock->state != SS_READY); if (unlikely(needs_conn)) { if (sock->state == SS_LISTENING) { res = -EPIPE; goto exit; } if (sock->state != SS_UNCONNECTED) { res = -EISCONN; goto exit; } if ((tport->published) || ((sock->type == SOCK_STREAM) && (total_len != 0))) { res = -EOPNOTSUPP; goto exit; } if (dest->addrtype == TIPC_ADDR_NAME) { tport->conn_type = dest->addr.name.name.type; tport->conn_instance = dest->addr.name.name.instance; } /* Abort any pending connection attempts (very unlikely) */ reject_rx_queue(sk); } do { if (dest->addrtype == TIPC_ADDR_NAME) { res = dest_name_check(dest, m); if (res) break; res = tipc_send2name(tport->ref, &dest->addr.name.name, dest->addr.name.domain, m->msg_iovlen, m->msg_iov); } else if (dest->addrtype == TIPC_ADDR_ID) { res = tipc_send2port(tport->ref, &dest->addr.id, m->msg_iovlen, m->msg_iov); } else if (dest->addrtype == TIPC_ADDR_MCAST) { if (needs_conn) { res = -EOPNOTSUPP; break; } res = dest_name_check(dest, m); if (res) break; res = tipc_multicast(tport->ref, &dest->addr.nameseq, m->msg_iovlen, m->msg_iov); } if (likely(res != -ELINKCONG)) { if (needs_conn && (res >= 0)) sock->state = SS_CONNECTING; break; } if (m->msg_flags & MSG_DONTWAIT) { res = -EWOULDBLOCK; break; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), !tport->congested); lock_sock(sk); if (res) break; } while (1); exit: if (iocb) release_sock(sk); return res; }
static int accept(struct socket *sock, struct socket *new_sock, int flags) { struct sock *sk = sock->sk; struct sk_buff *buf; int res; lock_sock(sk); if (sock->state == SS_READY) { res = -EOPNOTSUPP; goto exit; } if (sock->state != SS_LISTENING) { res = -EINVAL; goto exit; } while (skb_queue_empty(&sk->sk_receive_queue)) { if (flags & O_NONBLOCK) { res = -EWOULDBLOCK; goto exit; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue))); lock_sock(sk); if (res) goto exit; } buf = skb_peek(&sk->sk_receive_queue); res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); if (!res) { struct sock *new_sk = new_sock->sk; struct tipc_sock *new_tsock = tipc_sk(new_sk); struct tipc_port *new_tport = new_tsock->p; u32 new_ref = new_tport->ref; struct tipc_msg *msg = buf_msg(buf); lock_sock(new_sk); /* * Reject any stray messages received by new socket * before the socket lock was taken (very, very unlikely) */ reject_rx_queue(new_sk); /* Connect new socket to it's peer */ new_tsock->peer_name.ref = msg_origport(msg); new_tsock->peer_name.node = msg_orignode(msg); tipc_connect2port(new_ref, &new_tsock->peer_name); new_sock->state = SS_CONNECTED; tipc_set_portimportance(new_ref, msg_importance(msg)); if (msg_named(msg)) { new_tport->conn_type = msg_nametype(msg); new_tport->conn_instance = msg_nameinst(msg); } /* * Respond to 'SYN-' by discarding it & returning 'ACK'-. * Respond to 'SYN+' by queuing it on new socket. */ if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; advance_rx_queue(sk); send_packet(NULL, new_sock, &m, 0); } else { __skb_dequeue(&sk->sk_receive_queue); __skb_queue_head(&new_sk->sk_receive_queue, buf); } release_sock(new_sk); } exit: release_sock(sk); return res; }
static ssize_t ksb_fs_read(struct file *fp, char __user *buf, size_t count, loff_t *pos) { int ret; unsigned long flags; struct ks_bridge *ksb = fp->private_data; struct data_pkt *pkt; size_t space, copied; read_start: if (!test_bit(USB_DEV_CONNECTED, &ksb->flags)) return -ENODEV; spin_lock_irqsave(&ksb->lock, flags); if (list_empty(&ksb->to_ks_list)) { spin_unlock_irqrestore(&ksb->lock, flags); ret = wait_event_interruptible(ksb->ks_wait_q, !list_empty(&ksb->to_ks_list) || !test_bit(USB_DEV_CONNECTED, &ksb->flags)); if (ret < 0) return ret; goto read_start; } space = count; copied = 0; while (!list_empty(&ksb->to_ks_list) && space) { size_t len; pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list); len = min_t(size_t, space, pkt->len); pkt->n_read += len; spin_unlock_irqrestore(&ksb->lock, flags); ret = copy_to_user(buf + copied, pkt->buf, len); if (ret) { pr_err("copy_to_user failed err:%d\n", ret); ksb_free_data_pkt(pkt); return ret; } space -= len; copied += len; spin_lock_irqsave(&ksb->lock, flags); if (pkt->n_read == pkt->len) { /* * re-init the packet and queue it * for more data. */ list_del_init(&pkt->list); pkt->n_read = 0; pkt->len = MAX_DATA_PKT_SIZE; spin_unlock_irqrestore(&ksb->lock, flags); submit_one_urb(ksb, GFP_KERNEL, pkt); spin_lock_irqsave(&ksb->lock, flags); } } spin_unlock_irqrestore(&ksb->lock, flags); dbg_log_event(ksb, "KS_READ", copied, 0); pr_debug("count:%d space:%d copied:%d", count, space, copied); return copied; }
/* * This function removes the card. * * This function follows the following major steps to remove the device - * - Stop data traffic * - Shutdown firmware * - Remove the logical interfaces * - Terminate the work queue * - Unregister the device * - Free the adapter structure */ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) { struct mwifiex_private *priv = NULL; int i; if (down_interruptible(sem)) goto exit_sem_err; if (!adapter) goto exit_remove; adapter->surprise_removed = true; /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv && priv->netdev) { mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); } } dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || atomic_read(&adapter->tx_pending) || atomic_read(&adapter->cmd_pending)) { dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " "cmd_pending=%d\n", atomic_read(&adapter->rx_pending), atomic_read(&adapter->tx_pending), atomic_read(&adapter->cmd_pending)); } for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (!priv) continue; rtnl_lock(); if (priv->wdev && priv->netdev) mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); rtnl_unlock(); } priv = adapter->priv[0]; if (!priv || !priv->wdev) goto exit_remove; wiphy_unregister(priv->wdev->wiphy); wiphy_free(priv->wdev->wiphy); for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv) kfree(priv->wdev); } mwifiex_terminate_workqueue(adapter); /* Unregister device */ dev_dbg(adapter->dev, "info: unregister device\n"); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); /* Free adapter structure */ dev_dbg(adapter->dev, "info: free adapter\n"); mwifiex_free_adapter(adapter); exit_remove: up(sem); exit_sem_err: return 0; }
/* * Alon: this function should simply read the data on the given file, * copy it, and return it to the user as it is (encrypted or not). * The function's return value is the total amount of bytes read from the * file, or -1 if the function failed. */ ssize_t my_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { if (check_buffer_size(count) != 0) { return -EINVAL; } int minor = get_minor_from_file(filp); int is_this_process_writer = is_writer(filp); int key = ((device_private_data *)((filp)->private_data))->private_key; down_interruptible(&read_lock[minor]); down_interruptible(&index_lock[minor]); int maxToRead = get_max_to_read(minor); if (maxToRead == 0) { int current_num_of_writers = get_current_num_of_writers(minor); if(current_num_of_writers == is_this_process_writer) { up(&index_lock[minor]); up(&read_lock[minor]); return 0; } //Going to sleep until something is written into the buffer up(&index_lock[minor]); int wake_up_reason = wait_event_interruptible(read_wq[minor], flag_is_empty[minor] == 0 || get_current_num_of_writers(minor) == is_this_process_writer); if(wake_up_reason != 0) { up(&read_lock[minor]); return -EINTR; } if (get_current_num_of_writers(minor) == is_this_process_writer) { up(&read_lock[minor]); return 0; } down_interruptible(&index_lock[minor]); maxToRead = get_max_to_read(minor); } int numToRead = MIN(maxToRead,count); int firstPartSize = 0; int retval = 0; char* tmpBuf =(char*)kmalloc(sizeof(char)*numToRead,GFP_KERNEL); if (!tmpBuf){ up(&index_lock[minor]); up(&read_lock[minor]); return -ENOMEM; } int numOfParts = ( (reading_position[minor] + numToRead) > BUF_SIZE) ? TWO : ONE ; char* source = tmpBuf; if(numOfParts == ONE ) { if (minor == 0) { encryptor(&buffer[minor][reading_position[minor]], tmpBuf, numToRead, key, minor); } else if(minor == 1){ // encryptor source = &buffer[minor][ reading_position[minor] ]; } retval = copy_to_user(buf, source, numToRead) ? -EFAULT : 0; reading_position[minor] = (reading_position[minor] + numToRead) % BUF_SIZE; } else { firstPartSize = BUF_SIZE - reading_position[minor]; if (minor == 0) { encryptor(&buffer[minor][ reading_position[minor] ], tmpBuf, firstPartSize, key, minor); encryptor(&buffer[minor][0],tmpBuf+firstPartSize , numToRead - firstPartSize, key, minor); } else if (minor == 1) { memcpy(tmpBuf, &buffer[minor][ reading_position[minor] ], firstPartSize); memcpy(tmpBuf+firstPartSize, &buffer[minor][0], numToRead - firstPartSize); } retval = copy_to_user(buf, tmpBuf, numToRead); reading_position[minor] = numToRead - firstPartSize; } kfree(tmpBuf); if(retval != 0){ up(&index_lock[minor]); up(&read_lock[minor]); return retval; } if((writing_position[minor] == reading_position[minor]) && numToRead){ flag_is_empty[minor] = 1; } if(numToRead != 0){ // if we have read SOMETHING, the buffer is not full anymore flag_is_full[minor] = 0; wake_up_interruptible(&write_wq[minor]); //Notifies any waiting writers that there is now room within the buffer } up(&index_lock[minor]); up(&read_lock[minor]); return numToRead; }
/* * osprd_ioctl(inode, filp, cmd, arg) * Called to perform an ioctl on the named file. */ int osprd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { osprd_info_t *d = file2osprd(filp); // device info pid_t pid; node_t check; int wait, i; unsigned ticket; // is file open for writing? int filp_writable = (filp->f_mode & FMODE_WRITE) != 0; if (cmd == OSPRDIOCACQUIRE) { // The process id trying to get this lock is the unique identifier // in our list pid = current->pid; // Check if this pid has already tried to get a lock on this device check = check_in_list(d->lock_list, pid); if (check) { return -EDEADLK; } /* This whole section is to prevent deadlock. The global lock is necessary to avoid raceconditions, like processes getting inserted into the list after we've already checked it. This is a huge unfortunate bottleneck. I does prevent deadlock, however. */ osp_spin_lock(&g_mutex); for (i = 0; i < NOSPRD; i++) { if(d == &osprds[i]) { //Checks if this our own device continue; } else { node_t traversal = d->lock_list; //Traversal set to beginning of our lock linked list node_t start; // The starting position of our pid in the other list check = NULL; start = check_in_list(osprds[i].lock_list, pid); // We only care if our is also has another lock in this node if(start == NULL) continue; while(traversal != NULL) { // Only care about stuff after our pid check = check_in_list(start, traversal->pid); // We must make sure that our pid does not hold // a lock that would block anything in another queue if(check != NULL) { osp_spin_unlock(&g_mutex); return -EDEADLK; } traversal = traversal->next; } } } // It doesn't cause deadlock, so me must insert it into the list so // that others can check if this process will cause deadlock insert_node (&d->lock_list, pid, d->read_locks, d->write_locks); osp_spin_unlock(&g_mutex); // EXERCISE: Lock the ramdisk. // // If *filp is open for writing (filp_writable), then attempt // to write-lock the ramdisk; otherwise attempt to read-lock // the ramdisk. // // This lock request must block using 'd->blockq' until: // 1) no other process holds a write lock; // 2) either the request is for a read lock, or no other process // holds a read lock; and // 3) lock requests should be serviced in order, so no process // that blocked earlier is still blocked waiting for the // lock. // // If a process acquires a lock, mark this fact by setting // 'filp->f_flags |= F_OSPRD_LOCKED'. You also need to // keep track of how many read and write locks are held: // change the 'osprd_info_t' structure to do this. // // Also wake up processes waiting on 'd->blockq' as needed. // // If the lock request would cause a deadlock, return -EDEADLK. // If the lock request blocks and is awoken by a signal, then // return -ERESTARTSYS. // Otherwise, if we can grant the lock request, return 0. // 'd->ticket_head' and 'd->ticket_tail' should help you // service lock requests in order. These implement a ticket // order: 'ticket_tail' is the next ticket, and 'ticket_head' // is the ticket currently being served. You should set a local // variable to 'd->ticket_head' and increment 'd->ticket_head'. // Then, block at least until 'd->ticket_tail == local_ticket'. // (Some of these operations are in a critical section and must // be protected by a spinlock; which ones?) if (filp_writable) { // Get the next ticket osp_spin_lock(&d->mutex); ticket = d->ticket_tail; d->ticket_tail++; osp_spin_unlock(&d->mutex); // Wait for the ticket to become the current job wait = wait_event_interruptible( d->blockq, (ticket == d->ticket_head && d->read_locks == 0 && d->write_locks == 0) ); // Interupt handling if (wait != 0) { // Wait until we have the ticket // If we increment too early, another process could wait // forever while(ticket != d->ticket_head) { yield(); continue; } osp_spin_lock(&d->mutex); d->ticket_head++; osp_spin_unlock(&d->mutex); return wait; } // Give the lock for this job osp_spin_lock(&d->mutex); d->write_locks++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } else { // Read only // Get the next ticket osp_spin_lock(&d->mutex); ticket = d->ticket_tail; d->ticket_tail++; osp_spin_unlock(&d->mutex); // Wait for the ticket to become the current job wait = wait_event_interruptible( d->blockq, // We don't need to check for other read tasks, take note (ticket == d->ticket_head && d->write_locks == 0) ); // Interrupt handling if (wait != 0) { // Wait until we have the ticket // If we increment too early, another process could wait // forever while(ticket != d->ticket_head) { yield(); continue; } osp_spin_lock(&d->mutex); d->ticket_head++; osp_spin_unlock(&d->mutex); wake_up_all(&d->blockq); return wait; } // Give the lock to the current job osp_spin_lock(&d->mutex); d->read_locks++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); // Since the next task might be a read task, we wake everyone wake_up_all(&d->blockq); } return 0; /* */ } else if (cmd == OSPRDIOCTRYACQUIRE) { // EXERCISE: ATTEMPT to lock the ramdisk. // // This is just like OSPRDIOCACQUIRE, except it should never // block. If OSPRDIOCACQUIRE would block or return deadlock, // OSPRDIOCTRYACQUIRE should return -EBUSY. // Otherwise, if we can grant the lock request, return 0. if (filp_writable) { // Get the next ticket osp_spin_lock(&d->mutex); ticket = d->ticket_tail; d->ticket_tail++; osp_spin_unlock(&d->mutex); // Check if we can get the ticket if (ticket == d->ticket_head && d->read_locks == 0 && d->write_locks == 0) { osp_spin_lock(&d->mutex); d->write_locks++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } else { // Clean up the tickets, make sure they are back to // where they should be osp_spin_lock(&d->mutex); d->ticket_head++; osp_spin_unlock(&d->mutex); return -EBUSY; } } else { // Read only // Get the next ticket osp_spin_lock(&d->mutex); ticket = d->ticket_tail; d->ticket_tail++; osp_spin_unlock(&d->mutex); // Check if we can get the ticket if (ticket == d->ticket_head && d->write_locks == 0) { osp_spin_lock(&d->mutex); d->read_locks++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); // Wake up everyone for the same reasons wake_up_all(&d->blockq); } else { // Clean up the tickets, make sure they are back to // where they should be osp_spin_lock(&d->mutex); d->ticket_head++; osp_spin_unlock(&d->mutex); return -EBUSY; } } // Success return 0; } else if (cmd == OSPRDIOCRELEASE) { // EXERCISE: Unlock the ramdisk. // // If the file hasn't locked the ramdisk, return -EINVAL. // Otherwise, clear the lock from filp->f_flags, wake up // the wait queue, perform any additional accounting steps // you need, and return 0. // Your code here (instead of the next line). // Check to make sure has lock if (!(filp->f_flags & F_OSPRD_LOCKED)) { return -EINVAL; } // Clear the locked flag filp->f_flags &= ~(F_OSPRD_LOCKED); // Increment the current job and increment the number of finished // writing/reading tasks if(filp_writable) { osp_spin_lock(&d->mutex); d->ticket_head++; d->write_locks--; osp_spin_unlock(&d->mutex); } else { osp_spin_lock(&d->mutex); d->ticket_head++; d->read_locks--; osp_spin_unlock(&d->mutex); } // We're finished, notify everyone wake_up_all(&d->blockq); return 0; } else return -ENOTTY; /* unknown command */ }
ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, char __user *buffer, size_t length) { int writePtr; raw_htc_buffer *free; if (arRawStream2EndpointID(ar,StreamID) == 0) { AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID); return -EFAULT; } if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) { return -ERESTARTSYS; } /* Search for a free buffer */ free = get_free_buffer(ar,StreamID); /* Check if there is space to write else wait */ while (!ar->write_buffer_available[StreamID]) { up(&ar->raw_htc_write_sem[StreamID]); /* Wait for buffer to become free */ AR_DEBUG2_PRINTF("Sleeping StreamID(%d) write process\n", StreamID); if (wait_event_interruptible(ar->raw_htc_write_queue[StreamID], ar->write_buffer_available[StreamID])) { return -EINTR; } if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) { return -ERESTARTSYS; } free = get_free_buffer(ar,StreamID); } /* Send the data */ writePtr = HTC_HEADER_LEN; if (length > (AR6000_BUFFER_SIZE - HTC_HEADER_LEN)) { length = AR6000_BUFFER_SIZE - HTC_HEADER_LEN; } if (copy_from_user(&free->data[writePtr], buffer, length)) { up(&ar->raw_htc_read_sem[StreamID]); return -EFAULT; } free->length = length; SET_HTC_PACKET_INFO_TX(&free->HTCPacket, free, &free->data[writePtr], length, arRawStream2EndpointID(ar,StreamID), AR6K_DATA_PKT_TAG); HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); ar->write_buffer_available[StreamID] = FALSE; up(&ar->raw_htc_write_sem[StreamID]); return length; }
static ssize_t wdm_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { u8 *buf; int rv = -EMSGSIZE, r, we; struct wdm_device *desc = file->private_data; struct usb_ctrlrequest *req; if (count > desc->wMaxCommand) count = desc->wMaxCommand; spin_lock_irq(&desc->iuspin); we = desc->werr; desc->werr = 0; spin_unlock_irq(&desc->iuspin); if (we < 0) return -EIO; buf = kmalloc(count, GFP_KERNEL); if (!buf) { rv = -ENOMEM; goto outnl; } r = copy_from_user(buf, buffer, count); if (r > 0) { kfree(buf); rv = -EFAULT; goto outnl; } /* concurrent writes and disconnect */ r = mutex_lock_interruptible(&desc->wlock); rv = -ERESTARTSYS; if (r) { kfree(buf); goto outnl; } if (test_bit(WDM_DISCONNECTING, &desc->flags)) { kfree(buf); rv = -ENODEV; goto outnp; } r = usb_autopm_get_interface(desc->intf); if (r < 0) { kfree(buf); goto outnp; } if (!(file->f_flags & O_NONBLOCK)) r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); else if (test_bit(WDM_IN_USE, &desc->flags)) r = -EAGAIN; if (r < 0) { kfree(buf); goto out; } req = desc->orq; usb_fill_control_urb( desc->command, interface_to_usbdev(desc->intf), /* using common endpoint 0 */ usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0), (unsigned char *)req, buf, count, wdm_out_callback, desc ); req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; req->wValue = 0; req->wIndex = desc->inum; req->wLength = cpu_to_le16(count); set_bit(WDM_IN_USE, &desc->flags); desc->outbuf = buf; rv = usb_submit_urb(desc->command, GFP_KERNEL); if (rv < 0) { kfree(buf); desc->outbuf = NULL; clear_bit(WDM_IN_USE, &desc->flags); dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); } else { dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", req->wIndex); } out: usb_autopm_put_interface(desc->intf); outnp: mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; }
static int touch_event_handler(void *unused) { struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; static int x1, y1, raw_x1, raw_y1; int temp_x1, temp_y1, temp_raw_x1, temp_raw_y1, temp_touch_dir, temp_contact_id; int report_id, touch_valid, contact_id, touch_dir, touch_need_sync; char buffer[10]; int ret = -1; sched_setscheduler(current, SCHED_RR, ¶m); do { set_current_state(TASK_INTERRUPTIBLE); while (tpd_halt) {tpd_flag = 0; msleep(20);} wait_event_interruptible(waiter, tpd_flag != 0); tpd_flag = 0; TPD_DEBUG_SET_TIME; set_current_state(TASK_RUNNING); TPD_DEBUG("[mtk-tpd] touch interrupt\n"); touch_need_sync = 0; temp_x1 = 0xFFFFFFFF; temp_y1 = 0xFFFFFFFF; temp_raw_x1 = 0xFFFFFFFF; temp_raw_y1 = 0xFFFFFFFF; temp_touch_dir = 0xFFFFFFFF; temp_contact_id = 0xFFFFFFFF; do { i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG | I2C_ENEXT_FLAG; ret = tpd_i2c_read(i2c_client, buffer, 10); if (ret != sizeof(buffer)) { TPD_DEBUG("[mtk-tpd] i2c read communcate error: 0x%x\n", ret); continue; } i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG; report_id = buffer[0]; if (0x4 == report_id) { touch_valid = buffer[1]>>7; if (touch_valid) { contact_id = (buffer[1]&0x7C)>>2; touch_dir = buffer[1]&0x1; raw_x1 = x1 = ((buffer[3] << 8) | buffer[2]); raw_y1 = y1 = ((buffer[5] << 8) | buffer[4]); TPD_DEBUG("[mtk-tpd]:id:%d, raw_x1:%d, raw_y1:%d\n", contact_id, raw_x1, raw_y1); tpd_calibrate(&x1, &y1); if (((temp_x1 != x1) || (temp_y1 != y1) || (temp_contact_id != contact_id)) && (0xFFFFFFFF != temp_x1) && (0xFFFFFFFF != temp_y1)) { touch_need_sync = 1; if (temp_touch_dir) { tpd_down(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 1); } else { tpd_up(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 0); } } temp_x1 = x1; temp_y1 = y1; temp_raw_x1 = raw_x1; temp_raw_y1 = raw_y1; temp_touch_dir = touch_dir; temp_contact_id = contact_id; } else { TPD_DEBUG("[mtk-tpd]:Touch Invalid\n"); } } else { TPD_DEBUG("[mtk-tpd]:Invalid report ID:%d\n", buffer); } }while(!mt_get_gpio_in(GPIO_CTP_EINT_PIN));
static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ if (rv < 0) return -ERESTARTSYS; cntr = ACCESS_ONCE(desc->length); if (cntr == 0) { desc->read = 0; retry: if (test_bit(WDM_DISCONNECTING, &desc->flags)) { rv = -ENODEV; goto err; } if (test_bit(WDM_OVERFLOW, &desc->flags)) { clear_bit(WDM_OVERFLOW, &desc->flags); rv = -ENOBUFS; goto err; } i++; if (file->f_flags & O_NONBLOCK) { if (!test_bit(WDM_READ, &desc->flags)) { rv = cntr ? cntr : -EAGAIN; goto err; } rv = 0; } else { rv = wait_event_interruptible(desc->wait, test_bit(WDM_READ, &desc->flags)); } /* may have happened while we slept */ if (test_bit(WDM_DISCONNECTING, &desc->flags)) { rv = -ENODEV; goto err; } usb_mark_last_busy(interface_to_usbdev(desc->intf)); if (rv < 0) { rv = -ERESTARTSYS; goto err; } spin_lock_irq(&desc->iuspin); if (desc->rerr) { /* read completed, error happened */ desc->rerr = 0; spin_unlock_irq(&desc->iuspin); rv = -EIO; goto err; } /* * recheck whether we've lost the race * against the completion handler */ if (!test_bit(WDM_READ, &desc->flags)) { /* lost race */ spin_unlock_irq(&desc->iuspin); goto retry; } if (!desc->reslength) { /* zero length read */ dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); clear_bit(WDM_READ, &desc->flags); spin_unlock_irq(&desc->iuspin); goto retry; } cntr = desc->length; spin_unlock_irq(&desc->iuspin); } if (cntr > count) cntr = count; rv = copy_to_user(buffer, desc->ubuf, cntr); if (rv > 0) { rv = -EFAULT; goto err; } spin_lock_irq(&desc->iuspin); for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; desc->length -= cntr; /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); spin_unlock_irq(&desc->iuspin); rv = cntr; err: mutex_unlock(&desc->rlock); return rv; }
/* * This function adds the card. * * This function follows the following major steps to set up the device - * - Initialize software. This includes probing the card, registering * the interface operations table, and allocating/initializing the * adapter structure * - Set up the netlink socket * - Create and start the main work queue * - Register the device * - Initialize firmware and hardware * - Add logical interfaces */ int mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops, u8 iface_type) { struct mwifiex_adapter *adapter; if (down_interruptible(sem)) goto exit_sem_err; if (mwifiex_register(card, if_ops, (void **)&adapter)) { pr_err("%s: software init failed\n", __func__); goto err_init_sw; } adapter->iface_type = iface_type; adapter->card_sem = sem; adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; adapter->surprise_removed = false; init_waitqueue_head(&adapter->init_wait_q); adapter->is_suspended = false; adapter->hs_activated = false; init_waitqueue_head(&adapter->hs_activate_wait_q); init_waitqueue_head(&adapter->cmd_wait_q.wait); adapter->cmd_wait_q.status = 0; adapter->scan_wait_q_woken = false; if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) { adapter->rx_work_enabled = true; pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); } adapter->workqueue = alloc_workqueue("MWIFIEX_WORK_QUEUE", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); if (!adapter->workqueue) goto err_kmalloc; INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); if (adapter->rx_work_enabled) { adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); if (!adapter->rx_workqueue) goto err_kmalloc; INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); } /* Register the device. Fill up the private data structure with relevant information from the card. */ if (adapter->if_ops.register_dev(adapter)) { pr_err("%s: failed to register mwifiex device\n", __func__); goto err_registerdev; } if (mwifiex_init_hw_fw(adapter)) { pr_err("%s: firmware init failed\n", __func__); goto err_init_fw; } return 0; err_init_fw: pr_debug("info: %s: unregister device\n", __func__); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { pr_debug("info: %s: shutdown mwifiex\n", __func__); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); } err_registerdev: adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); err_kmalloc: mwifiex_free_adapter(adapter); err_init_sw: up(sem); exit_sem_err: return -1; }
int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, enum autofs_notify notify) { struct autofs_info *ino; struct autofs_wait_queue *wq; char *name; unsigned int len = 0; unsigned int hash = 0; int status, type; /* In catatonic mode, we don't wait for nobody */ if (sbi->catatonic) return -ENOENT; name = kmalloc(NAME_MAX + 1, GFP_KERNEL); if (!name) return -ENOMEM; /* If this is a direct mount request create a dummy name */ if (IS_ROOT(tx_cache_get_dentry(dentry)) && (sbi->type & AUTOFS_TYPE_DIRECT)) len = sprintf(name, "%p", dentry); else { len = autofs4_getpath(sbi, dentry, &name); if (!len) { kfree(name); return -ENOENT; } } hash = full_name_hash(name, len); if (mutex_lock_interruptible(&sbi->wq_mutex)) { kfree(name); return -EINTR; } wq = autofs4_find_wait(sbi, name, hash, len); ino = autofs4_dentry_ino(dentry); if (!wq && ino && notify == NFY_NONE) { /* * Either we've betean the pending expire to post it's * wait or it finished while we waited on the mutex. * So we need to wait till either, the wait appears * or the expire finishes. */ while (ino->flags & AUTOFS_INF_EXPIRING) { mutex_unlock(&sbi->wq_mutex); schedule_timeout_interruptible(HZ/10); if (mutex_lock_interruptible(&sbi->wq_mutex)) { kfree(name); return -EINTR; } wq = autofs4_find_wait(sbi, name, hash, len); if (wq) break; } /* * Not ideal but the status has already gone. Of the two * cases where we wait on NFY_NONE neither depend on the * return status of the wait. */ if (!wq) { kfree(name); mutex_unlock(&sbi->wq_mutex); return 0; } } if (!wq) { /* Create a new wait queue */ wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); if (!wq) { kfree(name); mutex_unlock(&sbi->wq_mutex); return -ENOMEM; } wq->wait_queue_token = autofs4_next_wait_queue; if (++autofs4_next_wait_queue == 0) autofs4_next_wait_queue = 1; wq->next = sbi->queues; sbi->queues = wq; init_waitqueue_head(&wq->queue); wq->hash = hash; wq->name = name; wq->len = len; wq->dev = autofs4_get_dev(sbi); wq->ino = autofs4_get_ino(sbi); wq->uid = current->uid; wq->gid = current->gid; wq->pid = current->pid; wq->tgid = current->tgid; wq->status = -EINTR; /* Status return if interrupted */ atomic_set(&wq->wait_ctr, 2); mutex_unlock(&sbi->wq_mutex); if (sbi->version < 5) { if (notify == NFY_MOUNT) type = autofs_ptype_missing; else type = autofs_ptype_expire_multi; } else { if (notify == NFY_MOUNT) type = (sbi->type & AUTOFS_TYPE_DIRECT) ? autofs_ptype_missing_direct : autofs_ptype_missing_indirect; else type = (sbi->type & AUTOFS_TYPE_DIRECT) ? autofs_ptype_expire_direct : autofs_ptype_expire_indirect; } DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); /* autofs4_notify_daemon() may block */ autofs4_notify_daemon(sbi, wq, type); } else { atomic_inc(&wq->wait_ctr); mutex_unlock(&sbi->wq_mutex); kfree(name); DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d", (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); } /* wq->name is NULL if and only if the lock is already released */ if (sbi->catatonic) { /* We might have slept, so check again for catatonic mode */ wq->status = -ENOENT; kfree(wq->name); wq->name = NULL; } if (wq->name) { /* Block all but "shutdown" signals while waiting */ sigset_t oldset; unsigned long irqflags; spin_lock_irqsave(¤t->sighand->siglock, irqflags); oldset = current->blocked; siginitsetinv(¤t->blocked, SHUTDOWN_SIGS & ~oldset.sig[0]); recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); wait_event_interruptible(wq->queue, wq->name == NULL); spin_lock_irqsave(¤t->sighand->siglock, irqflags); current->blocked = oldset; recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); } else { DPRINTK("skipped sleeping"); } status = wq->status; /* Are we the last process to need status? */ if (atomic_dec_and_test(&wq->wait_ctr)) kfree(wq); return status; }
/* * This function gets firmware and initializes it. * * The main initialization steps followed are - * - Download the correct firmware to card * - Issue the init commands to firmware */ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) { int ret; char fmt[64]; struct mwifiex_private *priv; struct mwifiex_adapter *adapter = context; struct mwifiex_fw_image fw; struct semaphore *sem = adapter->card_sem; bool init_failed = false; struct wireless_dev *wdev; if (!firmware) { mwifiex_dbg(adapter, ERROR, "Failed to get firmware %s\n", adapter->fw_name); goto err_dnld_fw; } memset(&fw, 0, sizeof(struct mwifiex_fw_image)); adapter->firmware = firmware; fw.fw_buf = (u8 *) adapter->firmware->data; fw.fw_len = adapter->firmware->size; if (adapter->if_ops.dnld_fw) { ret = adapter->if_ops.dnld_fw(adapter, &fw); } else { ret = mwifiex_dnld_fw(adapter, &fw); } if (ret == -1) goto err_dnld_fw; mwifiex_dbg(adapter, MSG, "WLAN FW is active\n"); if (cal_data_cfg) { if ((request_firmware(&adapter->cal_data, cal_data_cfg, adapter->dev)) < 0) mwifiex_dbg(adapter, ERROR, "Cal data request_firmware() failed\n"); } /* enable host interrupt after fw dnld is successful */ if (adapter->if_ops.enable_int) { if (adapter->if_ops.enable_int(adapter)) goto err_dnld_fw; } adapter->init_wait_q_woken = false; ret = mwifiex_init_fw(adapter); if (ret == -1) { goto err_init_fw; } else if (!ret) { adapter->hw_status = MWIFIEX_HW_STATUS_READY; goto done; } /* Wait for mwifiex_init to complete */ wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) goto err_init_fw; priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; if (mwifiex_register_cfg80211(adapter)) { mwifiex_dbg(adapter, ERROR, "cannot register with cfg80211\n"); goto err_init_fw; } if (mwifiex_init_channel_scan_gap(adapter)) { mwifiex_dbg(adapter, ERROR, "could not init channel stats table\n"); goto err_init_fw; } if (driver_mode) { driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK; driver_mode |= MWIFIEX_DRIVER_MODE_STA; } rtnl_lock(); /* Create station interface by default */ wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, NL80211_IFTYPE_STATION, NULL, NULL); if (IS_ERR(wdev)) { mwifiex_dbg(adapter, ERROR, "cannot create default STA interface\n"); rtnl_unlock(); goto err_add_intf; } if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM, NL80211_IFTYPE_AP, NULL, NULL); if (IS_ERR(wdev)) { mwifiex_dbg(adapter, ERROR, "cannot create AP interface\n"); rtnl_unlock(); goto err_add_intf; } } if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM, NL80211_IFTYPE_P2P_CLIENT, NULL, NULL); if (IS_ERR(wdev)) { mwifiex_dbg(adapter, ERROR, "cannot create p2p client interface\n"); rtnl_unlock(); goto err_add_intf; } } rtnl_unlock(); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt); goto done; err_add_intf: wiphy_unregister(adapter->wiphy); wiphy_free(adapter->wiphy); err_init_fw: if (adapter->if_ops.disable_int) adapter->if_ops.disable_int(adapter); err_dnld_fw: mwifiex_dbg(adapter, ERROR, "info: %s: unregister device\n", __func__); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { pr_debug("info: %s: shutdown mwifiex\n", __func__); adapter->init_wait_q_woken = false; if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) wait_event_interruptible(adapter->init_wait_q, adapter->init_wait_q_woken); } adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); init_failed = true; done: if (adapter->cal_data) { release_firmware(adapter->cal_data); adapter->cal_data = NULL; } if (adapter->firmware) { release_firmware(adapter->firmware); adapter->firmware = NULL; } if (init_failed) mwifiex_free_adapter(adapter); up(sem); return; }
/* * Commands to do_syslog: * * 0 -- Close the log. Currently a NOP. * 1 -- Open the log. Currently a NOP. * 2 -- Read from the log. * 3 -- Read all messages remaining in the ring buffer. * 4 -- Read and clear all messages remaining in the ring buffer * 5 -- Clear ring buffer. * 6 -- Disable printk's to console * 7 -- Enable printk's to console * 8 -- Set level of messages printed to console * 9 -- Return number of unread characters in the log buffer * 10 -- Return size of the log buffer */ int do_syslog(int type, char __user *buf, int len) { unsigned i, j, limit, count; int do_clear = 0; char c; int error = 0; error = security_syslog(type); if (error) return error; switch (type) { case 0: /* Close log */ break; case 1: /* Open log */ break; case 2: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; case 4: /* Read/clear last kernel messages */ do_clear = 1; /* FALL THRU */ case 3: /* Read last kernel messages */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; case 5: /* Clear ring buffer */ logged_chars = 0; break; case 6: /* Disable logging to console */ console_loglevel = minimum_console_loglevel; break; case 7: /* Enable logging to console */ console_loglevel = default_console_loglevel; break; case 8: /* Set level of messages printed to console */ error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; error = 0; break; case 9: /* Number of chars in the log buffer */ error = log_end - log_start; break; case 10: /* Size of the log buffer */ error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
// read // // wait until the teensy returns data // ssize_t vote_read (struct file *file, char __user *buf, size_t count, loff_t *pos) { struct usb_vote *vote_dev = file->private_data; int rc = 0; struct urb *vote_urb; // usb request int wqrc = 0; // return from wait queue int bytes_notcopied = 0; int copycount = 0; int actual_count; char *usbbuf; char vote_from_teensy; // single character vote from teensy printk(KERN_NOTICE "In %s\n", __FUNCTION__); if (!access_ok(VERIFY_WRITE, buf, count)) return -EINVAL; vote_urb = usb_alloc_urb(0, GFP_KERNEL); if (!vote_urb) return -ENOMEM; usbbuf = usb_buffer_alloc( vote_dev->udev, 64, GFP_KERNEL, &vote_urb->transfer_dma ); if (!usbbuf) { printk (KERN_NOTICE "%s: usb_buffer_alloc failed\n", __FUNCTION__); usb_buffer_free( vote_dev->udev, vote_urb->transfer_buffer_length, vote_urb->transfer_buffer, vote_urb->transfer_dma ); return -ENOMEM; } usb_fill_int_urb( vote_urb, vote_dev->udev, usb_rcvintpipe(vote_dev->udev, vote_dev->intr_in_endpointAddr), usbbuf, 64, (usb_complete_t) vote_read_intr_callback, vote_dev, 250 ); vote_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // vote_dev->data_from_teensy = false; data_from_teensy = false; if ((rc = usb_submit_urb(vote_urb, GFP_KERNEL))) { err("%s - failed submitting write urb, error %d", __FUNCTION__, rc); } // // Wait until teensy returns data // We will be awoken by our callback function, // vote_read_intr_callback(). // printk(KERN_DEBUG "%s: process %i (%s) going to sleep\n", __FUNCTION__, current->pid, current->comm); wqrc = wait_event_interruptible( // vote_dev->wait4voter, // vote_dev->data_from_teensy == true wait4voter, data_from_teensy == true ); if (wqrc == -ERESTARTSYS) { // Got a signal usb_buffer_free( vote_urb->dev, vote_urb->transfer_buffer_length, vote_urb->transfer_buffer, vote_urb->transfer_dma ); printk(KERN_DEBUG "%s got signal while waiting: %i (%s):\n", __FUNCTION__, current->pid, current->comm); // What needs to be deallocated here??? kgb return -EINTR; } printk(KERN_DEBUG "%s awoken %i (%s):\n", __FUNCTION__, current->pid, current->comm); // the actual amount of data from the URB actual_count = vote_urb->actual_length; printk(KERN_NOTICE "%s: Actual Count in the URB = %d\n", __FUNCTION__, actual_count); // We are expecting exactly 1 byte from the teensy. if (actual_count == 1) { vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0]; // Set the vote in vote_dev->votecast // to reflect the voter's choice. // This is for viewing in sysfs. vote_dev->votecast = vote_from_teensy; } // actual_count is 64 bytes -- not the amount of data sent from teensy // kgb: Since we know its just one byte vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0]; vote_dev->votecast = vote_from_teensy; printk(KERN_NOTICE "%s: Vote from teensy. [%c]\n", __FUNCTION__, vote_dev->votecast); if(count <= actual_count) copycount = count; else copycount = actual_count; bytes_notcopied = copy_to_user( buf, (char *) vote_urb->transfer_buffer, copycount ); if (bytes_notcopied != 0) { printk(KERN_NOTICE "%s: copy_to_user failed. \n", __FUNCTION__); } printk(KERN_NOTICE "%s: after copy_to_user. bytes_not_copied=%d \n", __FUNCTION__, bytes_notcopied); printk(KERN_NOTICE "%s: after copy_to_user. %c\n", __FUNCTION__, ((char *) vote_urb->transfer_buffer)[0]); // dealloc the URB usb_buffer_free( vote_urb->dev, vote_urb->transfer_buffer_length, vote_urb->transfer_buffer, vote_urb->transfer_dma ); // return the number of bytes read return copycount; } // vote_read()
static int touch_event_handler(void *unused) { struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; int x1=0, y1=0, x2=0, y2=0, x3=0, y3=0, x4=0, y4=0, p1=0, p2=0, p3=0, p4=0, id1=0xf, id2=0xf, id3=0xf, id4 = 0xf, pre_id1 = 0xf, pre_id2 = 0xf, pre_id3 = 0xf, pre_id4 = 0xf, pre_tt_mode = 0, finger_num = 0, pre_num = 0; int raw_x1=0, raw_y1=0, raw_x2=0, raw_y2=0, raw_x3=0, raw_y3=0, raw_x4=0, raw_y4=0; static char toggle; static char buffer[32];//[16]; // int pending = 0; u32 temp; sched_setscheduler(current, SCHED_RR, ¶m); g_temptimerdiff=get_jiffies_64();//jiffies; do { if(tpd_debuglog==1) { TPD_DMESG("[mtk-tpd] %s\n", __FUNCTION__); } set_current_state(TASK_INTERRUPTIBLE); if(tpd_debuglog==1) TPD_DMESG("[mtk-tpd], %s, tpd_halt=%d\n", __FUNCTION__, tpd_halt); while (tpd_halt) { tpd_flag = 0; msleep(20); } #ifndef POLL_MODE wait_event_interruptible(waiter, tpd_flag != 0); tpd_flag = 0; #endif TPD_DEBUG_SET_TIME; set_current_state(TASK_RUNNING); // #ifndef CY8CTMA300_CHARGE #if 0 temp = *(volatile u32 *)CHR_CON0; temp &= (1<<13); if(temp!=0) { if(tpd_debuglog==1) TPD_DMESG("[mtk-tpd], write 0x01 to 0x1D register!!\n"); buffer[0] = 0x01; buffer[0] = 0x01; i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0])); } else { if(tpd_debuglog==1) TPD_DMESG("[mtk-tpd], write 0x00 to 0x1D register!!\n"); buffer[0] = 0x00; i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0])); } #endif #ifndef TPD_NO_GPIO // for mt6575T fpga early porting if (tpd_show_version) { tpd_show_version = 0; mt_set_gpio_mode(GPIO1, 0x00); mt_set_gpio_dir(GPIO1, GPIO_DIR_OUT); mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE); mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP); mt_set_gpio_out(GPIO1, GPIO_OUT_ZERO); msleep(100); buffer[0] = 0x01; // reset touch panel mode i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0])); msleep(200); buffer[0] = 0x10; // swith to system information mode i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0])); msleep(200); i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0x0])); i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[0x8])); i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[0x10])); i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[0x18])); printk("[mtk-tpd] Cypress Touch Panel ID %x.%x\n", buffer[0x07], buffer[0x08]); printk("[mtk-tpd] Cypress Touch Panel Firmware Version %x.%x\n", buffer[0x15], buffer[0x16]); buffer[0] = 0x04; // switch to operation mode i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0])); msleep(200); mt_set_gpio_out(GPIO1, GPIO_OUT_ONE); mt_set_gpio_mode(GPIO1, 0x01); mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE); mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP); continue; } #endif i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0])); i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[8])); i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[16])); i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[24])); if(tpd_debuglog==1) { TPD_DMESG("[mtk-tpd]HST_MODE : %x\n", buffer[0]); TPD_DMESG("[mtk-tpd]TT_MODE : %x\n", buffer[1]); TPD_DMESG("[mtk-tpd]TT_STAT : %x\n", buffer[2]); // TPD_DEBUG("[mtk-tpd]TOUCH_ID : %x\n", buffer[8]); TPD_DMESG("[mtk-tpd]TOUCH_12ID : %x\n", buffer[8]); TPD_DMESG("[mtk-tpd]TOUCH_34ID : %x\n", buffer[21]); } finger_num = buffer[2] & 0x0f; if (finger_num == 0 && pre_num ==0) { msleep(10); tpd_flag = 0; pre_tt_mode = buffer[1]; continue; } if (pre_tt_mode == buffer[1]) { msleep(5); tpd_flag = 0; pre_tt_mode = buffer[1]; continue; } if (buffer[1] & 0x20) { TPD_DEBUG("buffer not ready\n"); tpd_flag = 0; pre_tt_mode = buffer[1]; continue; // buffer is not ready for use } id1 = (buffer[8] & 0xf0) >> 4; id2 = (buffer[8] & 0x0f); id3 = (buffer[21] & 0xf0) >> 4; id4 = (buffer[21] & 0x0f); // if (id1 != 0xf) { if(finger_num>=1) { x1 = (((int)buffer[3]) << 8) + buffer[4]; y1 = (((int)buffer[5]) << 8) + buffer[6]; if(x1>2048 || y1>2048) { tpd_flag = 0; pre_tt_mode = buffer[1]; continue; } p1 = buffer[7]; raw_x1 = x1; raw_y1 = y1; tpd_calibrate(&x1, &y1); tpd_down(raw_x1, raw_y1, x1, y1, p1); if(counter_pointer==0) g_temptimerdiff=get_jiffies_64();//jiffies; if(x_min==0&&y_min==0&&x_max==0&&y_max==0) { x_min = x1; y_min = y1; x_max = x1; y_max = y1; } if(x1<x_min) x_min = x1; if(x1>x_max) x_max = x1; if(y1<y_min) y_min = y1; if(y1>y_max) y_max = y1; counter_pointer++; if (time_after(jiffies, g_temptimerdiff + 100)) { //1s TPD_DMESG("[mtk-tpd], x_min=%d, y_min=%d, x_max=%d, y_max=%d, counter_pointer=%d!!\n", x_min, y_min, x_max, y_max, counter_pointer); x_min=0; y_min=0; x_max=0; y_max=0; counter_pointer=0; } } // if (id2 != 0xf || finger_num==2) { if(finger_num>=2) { x2 = (((int)buffer[9]) << 8) + buffer[10]; y2 = (((int)buffer[11]) << 8) + buffer[12]; p2 = buffer[13]; raw_x2 = x2; raw_y2 = y2; tpd_calibrate(&x2, &y2); tpd_down(raw_x2, raw_y2, x2, y2, p2); } // if(id3 != 0xf || finger_num==3) { if(finger_num>=3) { x3 = (((int)buffer[16]) << 8) + buffer[17]; y3= (((int)buffer[18]) << 8) + buffer[19]; p3= buffer[20]; raw_x3 = x3; raw_y3 = y3; tpd_calibrate(&x3, &y3); tpd_down(raw_x3, raw_y3, x3, y3, p3); } // if(id4 != 0xf || finger_num==4) { if(finger_num>=4) { x4 = (((int)buffer[22]) << 8) + buffer[23]; y4= (((int)buffer[24]) << 8) + buffer[25]; p4= buffer[26]; raw_x4 = x4; raw_y4 = y4; tpd_calibrate(&x4, &y4); tpd_down(raw_x4, raw_y4, x4, y4, p4); } if(pre_num>=1 && pre_id1==0xf) { if(finger_num>=1 && id1==0xf) { if(tpd_debuglog==1) TPD_DMESG("finger1 is still down!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger1 is up!!\n"); tpd_up(raw_x1, raw_y1, x1, y1, p1); } } else if(pre_num>=1 && pre_id1 !=0xf) { if(id1==pre_id1) { if(tpd_debuglog==1) TPD_DMESG("finger1 is still down!!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger1 is up!\n"); tpd_up(raw_x1, raw_y1, x1, y1, p1); } } if(pre_num>=2 && pre_id2==0xf) { if((finger_num>=2 && id2==0xf) || (finger_num==1 && id1==0xf)) { if(tpd_debuglog==1) TPD_DMESG("finger2 is still down!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger2 is up!!\n"); tpd_up(raw_x2, raw_y2, x2, y2, p2); } } else if(pre_num>=2 && pre_id2 !=0xf) { if(id2==pre_id2 || id1==pre_id2) { if(tpd_debuglog==1) TPD_DMESG("finger2 is still down!!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger2 is up!\n"); tpd_up(raw_x2, raw_y2, x2, y2, p2); } } if(pre_num>=3 && pre_id3==0xf) { if((finger_num>=3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) { if(tpd_debuglog==1) TPD_DMESG("finger3 is still down!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger3 is up!!\n"); tpd_up(raw_x3, raw_y3, x3, y3, p3); } } else if(pre_num>=3 && pre_id3 !=0xf) { if(id3==pre_id3 || id2==pre_id3 || id1==pre_id3) { if(tpd_debuglog==1) TPD_DMESG("finger3 is still down!!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger3 is up!\n"); tpd_up(raw_x3, raw_y3, x3, y3, p3); } } if(pre_num==4 && pre_id4==0xf) { if((finger_num>=4 && id4==0xf) || (finger_num==3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) { if(tpd_debuglog==1) TPD_DMESG("finger4 is still down!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger4 is up!!\n"); tpd_up(raw_x4, raw_y4, x4, y4, p4); } } else if(pre_num==4 && pre_id4 !=0xf) { if(id4==pre_id4 || id3==pre_id4 || id2==pre_id4 || id1==pre_id4) { if(tpd_debuglog==1) TPD_DMESG("finger4 is still down!!\n"); } else { if(tpd_debuglog==1) TPD_DMESG("finger4 is up!\n"); tpd_up(raw_x4, raw_y4, x4, y4, p4); } } if(tpd_debuglog==1) TPD_DMESG("pre_id1=%d, pre_id2=%d, pre_id3=%d, pre_id4=%d, id1=%d, id2=%d, id3=%d, id4=%d\n", pre_id1, pre_id2, pre_id3, pre_id4, id1, id2, id3, id4); pre_id1 = id1; pre_id2 = id2; pre_id3 = id3; pre_id4 = id4; pre_tt_mode = buffer[1]; pre_num = finger_num; if(tpd && tpd->dev && tpd_register_flag==1) { input_sync(tpd->dev); } i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &toggle); if((toggle & 0x80) == 0) toggle = toggle | 0x80; else toggle = toggle & (~0x80); i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &toggle); // switch the read toggle bit to do next sampling tpd_flag = 0; #ifndef POLL_MODE } while (!kthread_should_stop()); #else }
static ssize_t evtchn_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int rc; unsigned int c, p, bytes1 = 0, bytes2 = 0; struct per_user_data *u = file->private_data; /* Whole number of ports. */ count &= ~(sizeof(evtchn_port_t)-1); if (count == 0) return 0; if (count > PAGE_SIZE) count = PAGE_SIZE; for (;;) { mutex_lock(&u->ring_cons_mutex); rc = -EFBIG; if (u->ring_overflow) goto unlock_out; c = u->ring_cons; p = u->ring_prod; if (c != p) break; mutex_unlock(&u->ring_cons_mutex); if (file->f_flags & O_NONBLOCK) return -EAGAIN; rc = wait_event_interruptible(u->evtchn_wait, u->ring_cons != u->ring_prod); if (rc) return rc; } /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ if (((c ^ p) & EVTCHN_RING_SIZE) != 0) { bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(evtchn_port_t); bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t); } else { bytes1 = (p - c) * sizeof(evtchn_port_t); bytes2 = 0; } /* Truncate chunks according to caller's maximum byte count. */ if (bytes1 > count) { bytes1 = count; bytes2 = 0; } else if ((bytes1 + bytes2) > count) { bytes2 = count - bytes1; } rc = -EFAULT; rmb(); /* Ensure that we see the port before we copy it. */ if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) goto unlock_out; u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); rc = bytes1 + bytes2; unlock_out: mutex_unlock(&u->ring_cons_mutex); return rc; }
static ssize_t plx_drv_read(struct file *file, char __user *data, size_t len, loff_t *ppos) { int err; ssize_t retval = 0; driver_t *dev = file->private_data; PDEBUG(("function: %s, file: %s line: %d invoked, dev %lx\n", __FUNCTION__, __FILE__, __LINE__, (unsigned long)dev)); if(down_interruptible(&dev->read_semph)) return -ERESTARTSYS; dev->cntr_read++; /* Wait for interrupt handler to signal that it's OK to read */ while (dev->rp == dev->wp) { /* nothing to read */ PDEBUG(("function: %s, line: %d, wp and rp eq:%d\n", __FUNCTION__, __LINE__, dev->wp)); up(&dev->read_semph); /* release the lock */ if (file->f_flags & O_NONBLOCK) return -EAGAIN; PDEBUG(("\"%s\" reading: going to sleep\n", current->comm)); if (wait_event_interruptible(dev->read_queue, (dev->rp != dev->wp))) return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ /* otherwise loop, but first reacquire the lock */ if (down_interruptible(&dev->read_semph)) return -ERESTARTSYS; } /* Copy to user space */ PDEBUG(("function: %s, line: %d, data: %x, frame addr: %lx , len: %lx, rp%d\n", __FUNCTION__, __LINE__, (unsigned int)data, (unsigned long)dev->frames[dev->rp],(unsigned long)len, dev->rp)); err = copy_to_user(data, (void *) dev->frames[dev->rp],len); if (err) { ERROR(("function: %s, line: %d, couldn't copy to user\n", __FUNCTION__, __LINE__)); retval = -EFAULT; goto out; } dev->cntr_2_user_space++; /* This should never occur! */ if (dev->rp == dev->ip) { ERROR(("function: %s, line: %d, ERROR rp reached ip :%d\n", __FUNCTION__, __LINE__, dev->rp)); dev->cntr_circ_empty_rp++; return -EFAULT; } /* Increment read pointer and check for wrap */ dev->rp++; if (dev->rp == NO_OF_BUFFERS) dev->rp = 0; PDEBUG(("function: %s, after copy_to_user read time:%d\n", __FUNCTION__, plx_diff_since_read(dev))); /* Nonnegative value represents successfully read bytes */ retval = len; out: /* Unlock .. */ up(&dev->read_semph); return retval; }