📄 qeth_sys.c
字号:
if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) return sprintf(buf, "n/a\n"); return sprintf(buf, "%s\n", (card->options.broadcast_mode == QETH_TR_BROADCAST_ALLRINGS)? "all rings":"local");}static ssize_tqeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; char *tmp; if (!card) return -EINVAL; if ((card->state != CARD_STATE_DOWN) && (card->state != CARD_STATE_RECOVER)) return -EPERM; if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){ PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "local")){ card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL; return count; } else if (!strcmp(tmp, "all_rings")) { card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; return count; } else { PRINT_WARN("broadcast_mode: invalid mode %s!\n", tmp); return -EINVAL; } return count;}static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show, qeth_dev_broadcast_mode_store);static ssize_tqeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) return sprintf(buf, "n/a\n"); return sprintf(buf, "%i\n", (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)? 1:0);}static ssize_tqeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; char *tmp; int i; if (!card) return -EINVAL; if ((card->state != CARD_STATE_DOWN) && (card->state != CARD_STATE_RECOVER)) return -EPERM; if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){ PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } i = simple_strtoul(buf, &tmp, 16); if ((i == 0) || (i == 1)) card->options.macaddr_mode = i? QETH_TR_MACADDR_CANONICAL : QETH_TR_MACADDR_NONCANONICAL; else { PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n"); return -EINVAL; } return count;}static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show, qeth_dev_canonical_macaddr_store);static ssize_tqeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);}static ssize_tqeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; char *tmp; int i; if (!card) return -EINVAL; if (card->info.type == QETH_CARD_TYPE_IQD) { PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); return -EPERM; } if (((card->state != CARD_STATE_DOWN) && (card->state != CARD_STATE_RECOVER))) return -EPERM; i = simple_strtoul(buf, &tmp, 16); if ((i == 0) || (i == 1)) card->options.layer2 = i; else { PRINT_WARN("layer2: write 0 or 1 to this file!\n"); return -EINVAL; } return count;}static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, qeth_dev_layer2_store);static ssize_tqeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; switch (card->options.large_send) { case QETH_LARGE_SEND_NO: return sprintf(buf, "%s\n", "no"); case QETH_LARGE_SEND_EDDP: return sprintf(buf, "%s\n", "EDDP"); case QETH_LARGE_SEND_TSO: return sprintf(buf, "%s\n", "TSO"); default: return sprintf(buf, "%s\n", "N/A"); }}static ssize_tqeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; enum qeth_large_send_types type; int rc = 0; char *tmp; if (!card) return -EINVAL; tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "no")){ type = QETH_LARGE_SEND_NO; } else if (!strcmp(tmp, "EDDP")) { type = QETH_LARGE_SEND_EDDP; } else if (!strcmp(tmp, "TSO")) { type = QETH_LARGE_SEND_TSO; } else { PRINT_WARN("large_send: invalid mode %s!\n", tmp); return -EINVAL; } if (card->options.large_send == type) return count; if ((rc = qeth_set_large_send(card, type))) return rc; return count;}static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show, qeth_dev_large_send_store);static ssize_tqeth_dev_blkt_show(char *buf, struct qeth_card *card, int value ){ if (!card) return -EINVAL; return sprintf(buf, "%i\n", value);}static ssize_tqeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count, int *value, int max_value){ char *tmp; int i; if (!card) return -EINVAL; if ((card->state != CARD_STATE_DOWN) && (card->state != CARD_STATE_RECOVER)) return -EPERM; i = simple_strtoul(buf, &tmp, 10); if (i <= max_value) { *value = i; } else { PRINT_WARN("blkt total time: write values between" " 0 and %d to this file!\n", max_value); return -EINVAL; } return count;}static ssize_tqeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);}static ssize_tqeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_store(card, buf, count, &card->info.blkt.time_total,1000);}static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show, qeth_dev_blkt_total_store);static ssize_tqeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);}static ssize_tqeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_store(card, buf, count, &card->info.blkt.inter_packet,100);}static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show, qeth_dev_blkt_inter_store);static ssize_tqeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet_jumbo);}static ssize_tqeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; return qeth_dev_blkt_store(card, buf, count, &card->info.blkt.inter_packet_jumbo,100);}static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show, qeth_dev_blkt_inter_jumbo_store);static struct device_attribute * qeth_blkt_device_attrs[] = { &dev_attr_total, &dev_attr_inter, &dev_attr_inter_jumbo, NULL,};static struct attribute_group qeth_device_blkt_group = { .name = "blkt", .attrs = (struct attribute **)qeth_blkt_device_attrs,};static struct device_attribute * qeth_device_attrs[] = { &dev_attr_state, &dev_attr_chpid, &dev_attr_if_name, &dev_attr_card_type, &dev_attr_portno, &dev_attr_portname, &dev_attr_checksumming, &dev_attr_priority_queueing, &dev_attr_buffer_count, &dev_attr_route4,#ifdef CONFIG_QETH_IPV6 &dev_attr_route6,#endif &dev_attr_add_hhlen, &dev_attr_fake_ll, &dev_attr_fake_broadcast, &dev_attr_recover, &dev_attr_broadcast_mode, &dev_attr_canonical_macaddr, &dev_attr_layer2, &dev_attr_large_send, NULL,};static struct attribute_group qeth_device_attr_group = { .attrs = (struct attribute **)qeth_device_attrs,};static struct device_attribute * qeth_osn_device_attrs[] = { &dev_attr_state, &dev_attr_chpid, &dev_attr_if_name, &dev_attr_card_type, &dev_attr_buffer_count, &dev_attr_recover, NULL,};static struct attribute_group qeth_osn_device_attr_group = { .attrs = (struct attribute **)qeth_osn_device_attrs,};#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \struct device_attribute dev_attr_##_id = { \ .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\ .show = _show, \ .store = _store, \};intqeth_check_layer2(struct qeth_card *card){ if (card->options.layer2) return -EPERM; return 0;}static ssize_tqeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; if (qeth_check_layer2(card)) return -EPERM; return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);}static ssize_tqeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; char *tmp; if (!card) return -EINVAL; if ((card->state != CARD_STATE_DOWN) && (card->state != CARD_STATE_RECOVER)) return -EPERM; if (qeth_check_layer2(card)) return -EPERM; tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.enabled = (card->ipato.enabled)? 0 : 1; } else if (!strcmp(tmp, "1")){ card->ipato.enabled = 1; } else if (!strcmp(tmp, "0")){ card->ipato.enabled = 0; } else { PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to " "this file\n"); return -EINVAL; } return count;}static QETH_DEVICE_ATTR(ipato_enable, enable, 0644, qeth_dev_ipato_enable_show, qeth_dev_ipato_enable_store);static ssize_tqeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; if (qeth_check_layer2(card)) return -EPERM; return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);}static ssize_tqeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; char *tmp; if (!card) return -EINVAL; if (qeth_check_layer2(card)) return -EPERM; tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; } else if (!strcmp(tmp, "1")){ card->ipato.invert4 = 1; } else if (!strcmp(tmp, "0")){ card->ipato.invert4 = 0; } else { PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to " "this file\n"); return -EINVAL; } return count;}static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644, qeth_dev_ipato_invert4_show, qeth_dev_ipato_invert4_store);static inline ssize_tqeth_dev_ipato_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto){ struct qeth_ipato_entry *ipatoe; unsigned long flags; char addr_str[40]; int entry_len; /* length of 1 entry string, differs between v4 and v6 */ int i = 0; if (qeth_check_layer2(card)) return -EPERM; entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; /* add strlen for "/<mask>\n" */ entry_len += (proto == QETH_PROT_IPV4)? 5 : 6; spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipatoe, &card->ipato.entries, entry){ if (ipatoe->proto != proto) continue; /* String must not be longer than PAGE_SIZE. So we check if * string length gets near PAGE_SIZE. Then we can savely display * the next IPv6 address (worst case, compared to IPv4) */ if ((PAGE_SIZE - i) <= entry_len) break; qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str); i += snprintf(buf + i, PAGE_SIZE - i, "%s/%i\n", addr_str, ipatoe->mask_bits); } spin_unlock_irqrestore(&card->ip_lock, flags); i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i;}static ssize_tqeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);}static inline intqeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, u8 *addr, int *mask_bits){ const char *start, *end; char *tmp; char buffer[49] = {0, }; start = buf; /* get address string */ end = strchr(start, '/'); if (!end || (end-start >= 49)){ PRINT_WARN("Invalid format for ipato_addx/delx. " "Use <ip addr>/<mask bits>\n"); return -EINVAL; } strncpy(buffer, start, end - start); if (qeth_string_to_ipaddr(buffer, proto, addr)){ PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } start = end + 1; *mask_bits = simple_strtoul(start, &tmp, 10); return 0;}static inline ssize_tqeth_dev_ipato_add_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto){ struct qeth_ipato_entry *ipatoe; u8 addr[16]; int mask_bits; int rc; if (qeth_check_layer2(card)) return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; if (!(ipatoe = kmalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ PRINT_WARN("No memory to allocate ipato entry\n"); return -ENOMEM; } memset(ipatoe, 0, sizeof(struct qeth_ipato_entry)); ipatoe->proto = proto; memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16); ipatoe->mask_bits = mask_bits; if ((rc = qeth_add_ipato_entry(card, ipatoe))){ kfree(ipatoe); return rc; } return count;}static ssize_tqeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);}static QETH_DEVICE_ATTR(ipato_add4, add4, 0644, qeth_dev_ipato_add4_show, qeth_dev_ipato_add4_store);static inline ssize_tqeth_dev_ipato_del_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto){ u8 addr[16]; int mask_bits; int rc; if (qeth_check_layer2(card)) return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; qeth_del_ipato_entry(card, proto, addr, mask_bits); return count;}static ssize_tqeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct qeth_card *card = dev->driver_data; if (!card) return -EINVAL; return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -