1 /* 2 * Copyright Gavin Shan, IBM Corporation 2016. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/etherdevice.h> 14 #include <linux/netdevice.h> 15 #include <linux/skbuff.h> 16 17 #include <net/ncsi.h> 18 #include <net/net_namespace.h> 19 #include <net/sock.h> 20 21 #include "internal.h" 22 #include "ncsi-pkt.h" 23 24 u32 ncsi_calculate_checksum(unsigned char *data, int len) 25 { 26 u32 checksum = 0; 27 int i; 28 29 for (i = 0; i < len; i += 2) 30 checksum += (((u32)data[i] << 8) | data[i + 1]); 31 32 checksum = (~checksum + 1); 33 return checksum; 34 } 35 36 /* This function should be called after the data area has been 37 * populated completely. 38 */ 39 static void ncsi_cmd_build_header(struct ncsi_pkt_hdr *h, 40 struct ncsi_cmd_arg *nca) 41 { 42 u32 checksum; 43 __be32 *pchecksum; 44 45 h->mc_id = 0; 46 h->revision = NCSI_PKT_REVISION; 47 h->reserved = 0; 48 h->id = nca->id; 49 h->type = nca->type; 50 h->channel = NCSI_TO_CHANNEL(nca->package, 51 nca->channel); 52 h->length = htons(nca->payload); 53 h->reserved1[0] = 0; 54 h->reserved1[1] = 0; 55 56 /* Fill with calculated checksum */ 57 checksum = ncsi_calculate_checksum((unsigned char *)h, 58 sizeof(*h) + nca->payload); 59 pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) + 60 nca->payload); 61 *pchecksum = htonl(checksum); 62 } 63 64 static int ncsi_cmd_handler_default(struct sk_buff *skb, 65 struct ncsi_cmd_arg *nca) 66 { 67 struct ncsi_cmd_pkt *cmd; 68 69 cmd = skb_put_zero(skb, sizeof(*cmd)); 70 ncsi_cmd_build_header(&cmd->cmd.common, nca); 71 72 return 0; 73 } 74 75 static int ncsi_cmd_handler_sp(struct sk_buff *skb, 76 struct ncsi_cmd_arg *nca) 77 { 78 struct ncsi_cmd_sp_pkt *cmd; 79 80 cmd = skb_put_zero(skb, sizeof(*cmd)); 81 cmd->hw_arbitration = nca->bytes[0]; 82 ncsi_cmd_build_header(&cmd->cmd.common, nca); 83 84 return 0; 85 } 86 87 static int ncsi_cmd_handler_dc(struct sk_buff *skb, 88 struct ncsi_cmd_arg *nca) 89 { 90 struct ncsi_cmd_dc_pkt *cmd; 91 92 cmd = skb_put_zero(skb, sizeof(*cmd)); 93 cmd->ald = nca->bytes[0]; 94 ncsi_cmd_build_header(&cmd->cmd.common, nca); 95 96 return 0; 97 } 98 99 static int ncsi_cmd_handler_rc(struct sk_buff *skb, 100 struct ncsi_cmd_arg *nca) 101 { 102 struct ncsi_cmd_rc_pkt *cmd; 103 104 cmd = skb_put_zero(skb, sizeof(*cmd)); 105 ncsi_cmd_build_header(&cmd->cmd.common, nca); 106 107 return 0; 108 } 109 110 static int ncsi_cmd_handler_ae(struct sk_buff *skb, 111 struct ncsi_cmd_arg *nca) 112 { 113 struct ncsi_cmd_ae_pkt *cmd; 114 115 cmd = skb_put_zero(skb, sizeof(*cmd)); 116 cmd->mc_id = nca->bytes[0]; 117 cmd->mode = htonl(nca->dwords[1]); 118 ncsi_cmd_build_header(&cmd->cmd.common, nca); 119 120 return 0; 121 } 122 123 static int ncsi_cmd_handler_sl(struct sk_buff *skb, 124 struct ncsi_cmd_arg *nca) 125 { 126 struct ncsi_cmd_sl_pkt *cmd; 127 128 cmd = skb_put_zero(skb, sizeof(*cmd)); 129 cmd->mode = htonl(nca->dwords[0]); 130 cmd->oem_mode = htonl(nca->dwords[1]); 131 ncsi_cmd_build_header(&cmd->cmd.common, nca); 132 133 return 0; 134 } 135 136 static int ncsi_cmd_handler_svf(struct sk_buff *skb, 137 struct ncsi_cmd_arg *nca) 138 { 139 struct ncsi_cmd_svf_pkt *cmd; 140 141 cmd = skb_put_zero(skb, sizeof(*cmd)); 142 cmd->vlan = htons(nca->words[1]); 143 cmd->index = nca->bytes[6]; 144 cmd->enable = nca->bytes[7]; 145 ncsi_cmd_build_header(&cmd->cmd.common, nca); 146 147 return 0; 148 } 149 150 static int ncsi_cmd_handler_ev(struct sk_buff *skb, 151 struct ncsi_cmd_arg *nca) 152 { 153 struct ncsi_cmd_ev_pkt *cmd; 154 155 cmd = skb_put_zero(skb, sizeof(*cmd)); 156 cmd->mode = nca->bytes[3]; 157 ncsi_cmd_build_header(&cmd->cmd.common, nca); 158 159 return 0; 160 } 161 162 static int ncsi_cmd_handler_sma(struct sk_buff *skb, 163 struct ncsi_cmd_arg *nca) 164 { 165 struct ncsi_cmd_sma_pkt *cmd; 166 int i; 167 168 cmd = skb_put_zero(skb, sizeof(*cmd)); 169 for (i = 0; i < 6; i++) 170 cmd->mac[i] = nca->bytes[i]; 171 cmd->index = nca->bytes[6]; 172 cmd->at_e = nca->bytes[7]; 173 ncsi_cmd_build_header(&cmd->cmd.common, nca); 174 175 return 0; 176 } 177 178 static int ncsi_cmd_handler_ebf(struct sk_buff *skb, 179 struct ncsi_cmd_arg *nca) 180 { 181 struct ncsi_cmd_ebf_pkt *cmd; 182 183 cmd = skb_put_zero(skb, sizeof(*cmd)); 184 cmd->mode = htonl(nca->dwords[0]); 185 ncsi_cmd_build_header(&cmd->cmd.common, nca); 186 187 return 0; 188 } 189 190 static int ncsi_cmd_handler_egmf(struct sk_buff *skb, 191 struct ncsi_cmd_arg *nca) 192 { 193 struct ncsi_cmd_egmf_pkt *cmd; 194 195 cmd = skb_put_zero(skb, sizeof(*cmd)); 196 cmd->mode = htonl(nca->dwords[0]); 197 ncsi_cmd_build_header(&cmd->cmd.common, nca); 198 199 return 0; 200 } 201 202 static int ncsi_cmd_handler_snfc(struct sk_buff *skb, 203 struct ncsi_cmd_arg *nca) 204 { 205 struct ncsi_cmd_snfc_pkt *cmd; 206 207 cmd = skb_put_zero(skb, sizeof(*cmd)); 208 cmd->mode = nca->bytes[0]; 209 ncsi_cmd_build_header(&cmd->cmd.common, nca); 210 211 return 0; 212 } 213 214 static int ncsi_cmd_handler_oem(struct sk_buff *skb, 215 struct ncsi_cmd_arg *nca) 216 { 217 struct ncsi_cmd_oem_pkt *cmd; 218 unsigned int len; 219 220 len = sizeof(struct ncsi_cmd_pkt_hdr) + 4; 221 if (nca->payload < 26) 222 len += 26; 223 else 224 len += nca->payload; 225 226 cmd = skb_put_zero(skb, len); 227 memcpy(&cmd->mfr_id, nca->data, nca->payload); 228 ncsi_cmd_build_header(&cmd->cmd.common, nca); 229 230 return 0; 231 } 232 233 static struct ncsi_cmd_handler { 234 unsigned char type; 235 int payload; 236 int (*handler)(struct sk_buff *skb, 237 struct ncsi_cmd_arg *nca); 238 } ncsi_cmd_handlers[] = { 239 { NCSI_PKT_CMD_CIS, 0, ncsi_cmd_handler_default }, 240 { NCSI_PKT_CMD_SP, 4, ncsi_cmd_handler_sp }, 241 { NCSI_PKT_CMD_DP, 0, ncsi_cmd_handler_default }, 242 { NCSI_PKT_CMD_EC, 0, ncsi_cmd_handler_default }, 243 { NCSI_PKT_CMD_DC, 4, ncsi_cmd_handler_dc }, 244 { NCSI_PKT_CMD_RC, 4, ncsi_cmd_handler_rc }, 245 { NCSI_PKT_CMD_ECNT, 0, ncsi_cmd_handler_default }, 246 { NCSI_PKT_CMD_DCNT, 0, ncsi_cmd_handler_default }, 247 { NCSI_PKT_CMD_AE, 8, ncsi_cmd_handler_ae }, 248 { NCSI_PKT_CMD_SL, 8, ncsi_cmd_handler_sl }, 249 { NCSI_PKT_CMD_GLS, 0, ncsi_cmd_handler_default }, 250 { NCSI_PKT_CMD_SVF, 8, ncsi_cmd_handler_svf }, 251 { NCSI_PKT_CMD_EV, 4, ncsi_cmd_handler_ev }, 252 { NCSI_PKT_CMD_DV, 0, ncsi_cmd_handler_default }, 253 { NCSI_PKT_CMD_SMA, 8, ncsi_cmd_handler_sma }, 254 { NCSI_PKT_CMD_EBF, 4, ncsi_cmd_handler_ebf }, 255 { NCSI_PKT_CMD_DBF, 0, ncsi_cmd_handler_default }, 256 { NCSI_PKT_CMD_EGMF, 4, ncsi_cmd_handler_egmf }, 257 { NCSI_PKT_CMD_DGMF, 0, ncsi_cmd_handler_default }, 258 { NCSI_PKT_CMD_SNFC, 4, ncsi_cmd_handler_snfc }, 259 { NCSI_PKT_CMD_GVI, 0, ncsi_cmd_handler_default }, 260 { NCSI_PKT_CMD_GC, 0, ncsi_cmd_handler_default }, 261 { NCSI_PKT_CMD_GP, 0, ncsi_cmd_handler_default }, 262 { NCSI_PKT_CMD_GCPS, 0, ncsi_cmd_handler_default }, 263 { NCSI_PKT_CMD_GNS, 0, ncsi_cmd_handler_default }, 264 { NCSI_PKT_CMD_GNPTS, 0, ncsi_cmd_handler_default }, 265 { NCSI_PKT_CMD_GPS, 0, ncsi_cmd_handler_default }, 266 { NCSI_PKT_CMD_OEM, -1, ncsi_cmd_handler_oem }, 267 { NCSI_PKT_CMD_PLDM, 0, NULL }, 268 { NCSI_PKT_CMD_GPUUID, 0, ncsi_cmd_handler_default } 269 }; 270 271 static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) 272 { 273 struct ncsi_dev_priv *ndp = nca->ndp; 274 struct ncsi_dev *nd = &ndp->ndev; 275 struct net_device *dev = nd->dev; 276 int hlen = LL_RESERVED_SPACE(dev); 277 int tlen = dev->needed_tailroom; 278 int len = hlen + tlen; 279 struct sk_buff *skb; 280 struct ncsi_request *nr; 281 282 nr = ncsi_alloc_request(ndp, nca->req_flags); 283 if (!nr) 284 return NULL; 285 286 /* NCSI command packet has 16-bytes header, payload, 4 bytes checksum. 287 * The packet needs padding if its payload is less than 26 bytes to 288 * meet 64 bytes minimal ethernet frame length. 289 */ 290 len += sizeof(struct ncsi_cmd_pkt_hdr) + 4; 291 if (nca->payload < 26) 292 len += 26; 293 else 294 len += nca->payload; 295 296 /* Allocate skb */ 297 skb = alloc_skb(len, GFP_ATOMIC); 298 if (!skb) { 299 ncsi_free_request(nr); 300 return NULL; 301 } 302 303 nr->cmd = skb; 304 skb_reserve(skb, hlen); 305 skb_reset_network_header(skb); 306 307 skb->dev = dev; 308 skb->protocol = htons(ETH_P_NCSI); 309 310 return nr; 311 } 312 313 int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca) 314 { 315 struct ncsi_request *nr; 316 struct ethhdr *eh; 317 struct ncsi_cmd_handler *nch = NULL; 318 int i, ret; 319 320 /* Search for the handler */ 321 for (i = 0; i < ARRAY_SIZE(ncsi_cmd_handlers); i++) { 322 if (ncsi_cmd_handlers[i].type == nca->type) { 323 if (ncsi_cmd_handlers[i].handler) 324 nch = &ncsi_cmd_handlers[i]; 325 else 326 nch = NULL; 327 328 break; 329 } 330 } 331 332 if (!nch) { 333 netdev_err(nca->ndp->ndev.dev, 334 "Cannot send packet with type 0x%02x\n", nca->type); 335 return -ENOENT; 336 } 337 338 /* Get packet payload length and allocate the request 339 * It is expected that if length set as negative in 340 * handler structure means caller is initializing it 341 * and setting length in nca before calling xmit function 342 */ 343 if (nch->payload >= 0) 344 nca->payload = nch->payload; 345 nr = ncsi_alloc_command(nca); 346 if (!nr) 347 return -ENOMEM; 348 349 /* Prepare the packet */ 350 nca->id = nr->id; 351 ret = nch->handler(nr->cmd, nca); 352 if (ret) { 353 ncsi_free_request(nr); 354 return ret; 355 } 356 357 /* Fill the ethernet header */ 358 eh = skb_push(nr->cmd, sizeof(*eh)); 359 eh->h_proto = htons(ETH_P_NCSI); 360 eth_broadcast_addr(eh->h_dest); 361 eth_broadcast_addr(eh->h_source); 362 363 /* Start the timer for the request that might not have 364 * corresponding response. Given NCSI is an internal 365 * connection a 1 second delay should be sufficient. 366 */ 367 nr->enabled = true; 368 mod_timer(&nr->timer, jiffies + 1 * HZ); 369 370 /* Send NCSI packet */ 371 skb_get(nr->cmd); 372 ret = dev_queue_xmit(nr->cmd); 373 if (ret < 0) { 374 ncsi_free_request(nr); 375 return ret; 376 } 377 378 return 0; 379 } 380