// TODO are we sure we can give it all out? static size_t r_threads( struct uufile *f, void *dest, size_t bytes) { phantom_thread_t out; tid_t t = get_next_tid( f->pos, &out); f->pos = t; if( t < 0 ) return 0; int nc = umin( bytes, sizeof(out) ); memcpy( dest, &out, nc ); return nc; }
static struct sk_buff *lsp_to_skb(struct sqn_lsp_packet *lsp_packet) /* RX */ { struct sqn_eth_header eth_header = { .len = htons(sizeof(struct sqn_lsp_packet)) }; struct sk_buff *skb = __dev_alloc_skb(sizeof(eth_header) + sizeof(struct sqn_lsp_packet) , GFP_ATOMIC | GFP_DMA); sqn_pr_enter(); if (0 == skb) goto out; skb_reserve(skb, 2); memcpy(eth_header.dst_addr, g_lsp_device_mac, sizeof(g_lsp_device_mac)); memcpy(eth_header.src_addr, g_lsp_host_mac, sizeof(g_lsp_host_mac)); memcpy(skb->data, ð_header, sizeof(eth_header)); skb_put(skb, sizeof(eth_header)); memcpy(skb->data + skb->len, lsp_packet, sizeof(struct sqn_lsp_packet)); skb_put(skb, sizeof(struct sqn_lsp_packet)); sqn_pr_leave(); out: return skb; } static struct sk_buff* construct_lsp_packet(u32 id, u32 param1, u32 param2) { struct sqn_lsp_packet lsp_packet = { .thp_header = { .transport_version = 1 , .flags = 1 , .seq_number = 0 , .ack_number = 0 } , .lsp_header = { .id = htonl(id) } }; struct sk_buff *skb = 0; sqn_pr_enter(); switch (id) { case THSP_GET_MEDIA_CONNECTION_STATE: /* no parameters are needed */ if (mmc_wimax_get_sdio_lsp_log()) sqn_pr_info("TX LSP: THSP_GET_MEDIA_CONNECTION_STATE\n"); lsp_packet.thp_header.length = htons(sizeof(struct sqn_lsp_header) - 4); lsp_packet.thp_header.total_length = htonl(sizeof(struct sqn_lsp_header) - 4); break; case THSP_SET_POWER_MODE: /* deprecated */ if (mmc_wimax_get_sdio_lsp_log()) sqn_pr_info("TX LSP: THSP_SET_POWER_MODE (deprecated)\n"); break; case THSP_SET_HOST_POWER_MODE: lsp_packet.thp_header.length = htons(sizeof(struct sqn_lsp_header)); lsp_packet.thp_header.total_length = htonl(sizeof(struct sqn_lsp_header)); lsp_packet.lsp_header.u.host_power.tid = htonl(get_next_tid()); lsp_packet.lsp_header.u.host_power.mode = htonl(param1); if (mmc_wimax_get_sdio_lsp_log()) { sqn_pr_info("TX LSP: THSP_SET_HOST_POWER_MODE, tid: 0x%x, mode: %d\n" , ntohl(lsp_packet.lsp_header.u.host_power.tid) , param1); } break; case THSP_SET_FW_POWER_MODE: lsp_packet.thp_header.length = htons(sizeof(struct sqn_lsp_header)); lsp_packet.thp_header.total_length = htonl(sizeof(struct sqn_lsp_header)); lsp_packet.lsp_header.u.fw_power.tid = htonl(get_next_tid()); lsp_packet.lsp_header.u.fw_power.mode = htonl(param1); if (mmc_wimax_get_sdio_lsp_log()) { sqn_pr_info("TX LSP: THSP_SET_FW_POWER_MODE, tid: 0x%x, mode: %d\n" , htonl(lsp_packet.lsp_header.u.fw_power.tid) , param1); } break; case THSP_SQN_STATE_CHANGE_REPLY: lsp_packet.thp_header.length = htons(sizeof(struct sqn_lsp_header) - 4); lsp_packet.thp_header.total_length = htonl(sizeof(struct sqn_lsp_header) - 4); lsp_packet.lsp_header.u.fw_state.tid = htonl(param1); if (mmc_wimax_get_sdio_lsp_log()) { sqn_pr_info("TX LSP: THSP_SQN_STATE_CHANGE_REPLY, tid: %xh\n" , param1); } break; case THSP_THP_AVAILABLE_REPLY: lsp_packet.thp_header.length = htons(sizeof(struct sqn_lsp_header)); lsp_packet.thp_header.total_length = htonl(sizeof(struct sqn_lsp_header)); lsp_packet.lsp_header.u.thp_avl.tid = htonl(param1); lsp_packet.lsp_header.u.thp_avl.reply = htonl(param2); if (mmc_wimax_get_sdio_lsp_log()) { sqn_pr_info("TX LSP: THSP_THP_AVAILABLE_REPLY, tid: 0x%x, reply: %d\n" , param1, param2); } break; default: if (mmc_wimax_get_sdio_lsp_log()) sqn_pr_info("TX LSP: UNKNOWN\n"); } skb = lsp_to_skb(&lsp_packet); sqn_pr_leave(); return skb; }