|
|
1.1 root 1: /*
2: * Copyright (C) 2006 Michael Brown <[email protected]>.
3: *
4: * This program is free software; you can redistribute it and/or
5: * modify it under the terms of the GNU General Public License as
6: * published by the Free Software Foundation; either version 2 of the
7: * License, or any later version.
8: *
9: * This program is distributed in the hope that it will be useful, but
10: * WITHOUT ANY WARRANTY; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12: * General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with this program; if not, write to the Free Software
16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: FILE_LICENCE ( GPL2_OR_LATER );
20:
21: #include <stddef.h>
22: #include <string.h>
23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <errno.h>
26: #include <assert.h>
27: #include <byteswap.h>
28: #include <ipxe/list.h>
29: #include <ipxe/if_ether.h>
30: #include <ipxe/iobuf.h>
31: #include <ipxe/uaccess.h>
32: #include <ipxe/netdevice.h>
33: #include <ipxe/features.h>
34: #include <ipxe/interface.h>
35: #include <ipxe/xfer.h>
36: #include <ipxe/uri.h>
37: #include <ipxe/open.h>
38: #include <ipxe/ata.h>
39: #include <ipxe/device.h>
40: #include <ipxe/aoe.h>
41:
42: /** @file
43: *
44: * AoE protocol
45: *
46: */
47:
48: FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
49:
50: struct net_protocol aoe_protocol __net_protocol;
51:
52: /******************************************************************************
53: *
54: * AoE devices and commands
55: *
56: ******************************************************************************
57: */
58:
59: /** List of all AoE devices */
60: static LIST_HEAD ( aoe_devices );
61:
62: /** List of active AoE commands */
63: static LIST_HEAD ( aoe_commands );
64:
65: /** An AoE device */
66: struct aoe_device {
67: /** Reference counter */
68: struct refcnt refcnt;
69:
70: /** Network device */
71: struct net_device *netdev;
72: /** ATA command issuing interface */
73: struct interface ata;
74:
75: /** Major number */
76: uint16_t major;
77: /** Minor number */
78: uint8_t minor;
79: /** Target MAC address */
80: uint8_t target[MAX_LL_ADDR_LEN];
81:
82: /** Saved timeout value */
83: unsigned long timeout;
84:
85: /** Configuration command interface */
86: struct interface config;
87: /** Device is configued */
88: int configured;
89: };
90:
91: /** An AoE command */
92: struct aoe_command {
93: /** Reference count */
94: struct refcnt refcnt;
95: /** AOE device */
96: struct aoe_device *aoedev;
97: /** List of active commands */
98: struct list_head list;
99:
100: /** ATA command interface */
101: struct interface ata;
102:
103: /** ATA command */
104: struct ata_cmd command;
105: /** Command type */
106: struct aoe_command_type *type;
107: /** Command tag */
108: uint32_t tag;
109:
110: /** Retransmission timer */
111: struct retry_timer timer;
112: };
113:
114: /** An AoE command type */
115: struct aoe_command_type {
116: /**
117: * Calculate length of AoE command IU
118: *
119: * @v aoecmd AoE command
120: * @ret len Length of command IU
121: */
122: size_t ( * cmd_len ) ( struct aoe_command *aoecmd );
123: /**
124: * Build AoE command IU
125: *
126: * @v aoecmd AoE command
127: * @v data Command IU
128: * @v len Length of command IU
129: */
130: void ( * cmd ) ( struct aoe_command *aoecmd, void *data, size_t len );
131: /**
132: * Handle AoE response IU
133: *
134: * @v aoecmd AoE command
135: * @v data Response IU
136: * @v len Length of response IU
137: * @v ll_source Link-layer source address
138: * @ret rc Return status code
139: */
140: int ( * rsp ) ( struct aoe_command *aoecmd, const void *data,
141: size_t len, const void *ll_source );
142: };
143:
144: /**
145: * Get reference to AoE device
146: *
147: * @v aoedev AoE device
148: * @ret aoedev AoE device
149: */
150: static inline __attribute__ (( always_inline )) struct aoe_device *
151: aoedev_get ( struct aoe_device *aoedev ) {
152: ref_get ( &aoedev->refcnt );
153: return aoedev;
154: }
155:
156: /**
157: * Drop reference to AoE device
158: *
159: * @v aoedev AoE device
160: */
161: static inline __attribute__ (( always_inline )) void
162: aoedev_put ( struct aoe_device *aoedev ) {
163: ref_put ( &aoedev->refcnt );
164: }
165:
166: /**
167: * Get reference to AoE command
168: *
169: * @v aoecmd AoE command
170: * @ret aoecmd AoE command
171: */
172: static inline __attribute__ (( always_inline )) struct aoe_command *
173: aoecmd_get ( struct aoe_command *aoecmd ) {
174: ref_get ( &aoecmd->refcnt );
175: return aoecmd;
176: }
177:
178: /**
179: * Drop reference to AoE command
180: *
181: * @v aoecmd AoE command
182: */
183: static inline __attribute__ (( always_inline )) void
184: aoecmd_put ( struct aoe_command *aoecmd ) {
185: ref_put ( &aoecmd->refcnt );
186: }
187:
188: /**
189: * Name AoE device
190: *
191: * @v aoedev AoE device
192: * @ret name AoE device name
193: */
194: static const char * aoedev_name ( struct aoe_device *aoedev ) {
195: static char buf[16];
196:
197: snprintf ( buf, sizeof ( buf ), "%s/e%d.%d", aoedev->netdev->name,
198: aoedev->major, aoedev->minor );
199: return buf;
200: }
201:
202: /**
203: * Free AoE command
204: *
205: * @v refcnt Reference counter
206: */
207: static void aoecmd_free ( struct refcnt *refcnt ) {
208: struct aoe_command *aoecmd =
209: container_of ( refcnt, struct aoe_command, refcnt );
210:
211: assert ( ! timer_running ( &aoecmd->timer ) );
212: assert ( list_empty ( &aoecmd->list ) );
213:
214: aoedev_put ( aoecmd->aoedev );
215: free ( aoecmd );
216: }
217:
218: /**
219: * Close AoE command
220: *
221: * @v aoecmd AoE command
222: * @v rc Reason for close
223: */
224: static void aoecmd_close ( struct aoe_command *aoecmd, int rc ) {
225: struct aoe_device *aoedev = aoecmd->aoedev;
226:
227: /* Stop timer */
228: stop_timer ( &aoecmd->timer );
229:
230: /* Preserve the timeout value for subsequent commands */
231: aoedev->timeout = aoecmd->timer.timeout;
232:
233: /* Remove from list of commands */
234: if ( ! list_empty ( &aoecmd->list ) ) {
235: list_del ( &aoecmd->list );
236: INIT_LIST_HEAD ( &aoecmd->list );
237: aoecmd_put ( aoecmd );
238: }
239:
240: /* Shut down interfaces */
241: intf_shutdown ( &aoecmd->ata, rc );
242: }
243:
244: /**
245: * Transmit AoE command request
246: *
247: * @v aoecmd AoE command
248: * @ret rc Return status code
249: */
250: static int aoecmd_tx ( struct aoe_command *aoecmd ) {
251: struct aoe_device *aoedev = aoecmd->aoedev;
252: struct net_device *netdev = aoedev->netdev;
253: struct io_buffer *iobuf;
254: struct aoehdr *aoehdr;
255: size_t cmd_len;
256: int rc;
257:
258: /* Sanity check */
259: assert ( netdev != NULL );
260:
261: /* If we are transmitting anything that requires a response,
262: * start the retransmission timer. Do this before attempting
263: * to allocate the I/O buffer, in case allocation itself
264: * fails.
265: */
266: start_timer ( &aoecmd->timer );
267:
268: /* Create outgoing I/O buffer */
269: cmd_len = aoecmd->type->cmd_len ( aoecmd );
270: iobuf = alloc_iob ( MAX_LL_HEADER_LEN + cmd_len );
271: if ( ! iobuf )
272: return -ENOMEM;
273: iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
274: aoehdr = iob_put ( iobuf, cmd_len );
275:
276: /* Fill AoE header */
277: memset ( aoehdr, 0, sizeof ( *aoehdr ) );
278: aoehdr->ver_flags = AOE_VERSION;
279: aoehdr->major = htons ( aoedev->major );
280: aoehdr->minor = aoedev->minor;
281: aoehdr->tag = htonl ( aoecmd->tag );
282: aoecmd->type->cmd ( aoecmd, iobuf->data, iob_len ( iobuf ) );
283:
284: /* Send packet */
285: if ( ( rc = net_tx ( iobuf, netdev, &aoe_protocol, aoedev->target,
286: netdev->ll_addr ) ) != 0 ) {
287: DBGC ( aoedev, "AoE %s/%08x could not transmit: %s\n",
288: aoedev_name ( aoedev ), aoecmd->tag,
289: strerror ( rc ) );
290: return rc;
291: }
292:
293: return 0;
294: }
295:
296: /**
297: * Receive AoE command response
298: *
299: * @v aoecmd AoE command
300: * @v iobuf I/O buffer
301: * @v ll_source Link-layer source address
302: * @ret rc Return status code
303: */
304: static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
305: const void *ll_source ) {
306: struct aoe_device *aoedev = aoecmd->aoedev;
307: struct aoehdr *aoehdr = iobuf->data;
308: int rc;
309:
310: /* Sanity check */
311: if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
312: DBGC ( aoedev, "AoE %s/%08x received underlength response "
313: "(%zd bytes)\n", aoedev_name ( aoedev ),
314: aoecmd->tag, iob_len ( iobuf ) );
315: rc = -EINVAL;
316: goto done;
317: }
318: if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
319: ( aoehdr->minor != aoedev->minor ) ) {
320: DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
321: "device e%d.%d\n", aoedev_name ( aoedev ), aoecmd->tag,
322: ntohs ( aoehdr->major ), aoehdr->minor );
323: rc = -EINVAL;
324: goto done;
325: }
326:
327: /* Catch command failures */
328: if ( aoehdr->ver_flags & AOE_FL_ERROR ) {
329: DBGC ( aoedev, "AoE %s/%08x terminated in error\n",
330: aoedev_name ( aoedev ), aoecmd->tag );
331: aoecmd_close ( aoecmd, -EIO );
332: rc = -EIO;
333: goto done;
334: }
335:
336: /* Hand off to command completion handler */
337: if ( ( rc = aoecmd->type->rsp ( aoecmd, iobuf->data, iob_len ( iobuf ),
338: ll_source ) ) != 0 )
339: goto done;
340:
341: done:
342: /* Free I/O buffer */
343: free_iob ( iobuf );
344:
345: /* Terminate command */
346: aoecmd_close ( aoecmd, rc );
347:
348: return rc;
349: }
350:
351: /**
352: * Handle AoE retry timer expiry
353: *
354: * @v timer AoE retry timer
355: * @v fail Failure indicator
356: */
357: static void aoecmd_expired ( struct retry_timer *timer, int fail ) {
358: struct aoe_command *aoecmd =
359: container_of ( timer, struct aoe_command, timer );
360:
361: if ( fail ) {
362: aoecmd_close ( aoecmd, -ETIMEDOUT );
363: } else {
364: aoecmd_tx ( aoecmd );
365: }
366: }
367:
368: /**
369: * Calculate length of AoE ATA command IU
370: *
371: * @v aoecmd AoE command
372: * @ret len Length of command IU
373: */
374: static size_t aoecmd_ata_cmd_len ( struct aoe_command *aoecmd ) {
375: struct ata_cmd *command = &aoecmd->command;
376:
377: return ( sizeof ( struct aoehdr ) + sizeof ( struct aoeata ) +
378: command->data_out_len );
379: }
380:
381: /**
382: * Build AoE ATA command IU
383: *
384: * @v aoecmd AoE command
385: * @v data Command IU
386: * @v len Length of command IU
387: */
388: static void aoecmd_ata_cmd ( struct aoe_command *aoecmd,
389: void *data, size_t len ) {
390: struct aoe_device *aoedev = aoecmd->aoedev;
391: struct ata_cmd *command = &aoecmd->command;
392: struct aoehdr *aoehdr = data;
393: struct aoeata *aoeata = &aoehdr->payload[0].ata;
394:
395: /* Sanity check */
396: linker_assert ( AOE_FL_DEV_HEAD == ATA_DEV_SLAVE, __fix_ata_h__ );
397: assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) +
398: command->data_out_len ) );
399:
400: /* Build IU */
401: aoehdr->command = AOE_CMD_ATA;
402: memset ( aoeata, 0, sizeof ( *aoeata ) );
403: aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 ) |
404: ( command->cb.device & ATA_DEV_SLAVE ) |
405: ( command->data_out_len ? AOE_FL_WRITE : 0 ) );
406: aoeata->err_feat = command->cb.err_feat.bytes.cur;
407: aoeata->count = command->cb.count.native;
408: aoeata->cmd_stat = command->cb.cmd_stat;
409: aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
410: if ( ! command->cb.lba48 )
411: aoeata->lba.bytes[3] |=
412: ( command->cb.device & ATA_DEV_MASK );
413: copy_from_user ( aoeata->data, command->data_out, 0,
414: command->data_out_len );
415:
416: DBGC2 ( aoedev, "AoE %s/%08x ATA cmd %02x:%02x:%02x:%02x:%08llx",
417: aoedev_name ( aoedev ), aoecmd->tag, aoeata->aflags,
418: aoeata->err_feat, aoeata->count, aoeata->cmd_stat,
419: aoeata->lba.u64 );
420: if ( command->data_out_len )
421: DBGC2 ( aoedev, " out %04zx", command->data_out_len );
422: if ( command->data_in_len )
423: DBGC2 ( aoedev, " in %04zx", command->data_in_len );
424: DBGC2 ( aoedev, "\n" );
425: }
426:
427: /**
428: * Handle AoE ATA response IU
429: *
430: * @v aoecmd AoE command
431: * @v data Response IU
432: * @v len Length of response IU
433: * @v ll_source Link-layer source address
434: * @ret rc Return status code
435: */
436: static int aoecmd_ata_rsp ( struct aoe_command *aoecmd, const void *data,
437: size_t len, const void *ll_source __unused ) {
438: struct aoe_device *aoedev = aoecmd->aoedev;
439: struct ata_cmd *command = &aoecmd->command;
440: const struct aoehdr *aoehdr = data;
441: const struct aoeata *aoeata = &aoehdr->payload[0].ata;
442: size_t data_len;
443:
444: /* Sanity check */
445: if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) ) {
446: DBGC ( aoedev, "AoE %s/%08x received underlength ATA response "
447: "(%zd bytes)\n", aoedev_name ( aoedev ),
448: aoecmd->tag, len );
449: return -EINVAL;
450: }
451: data_len = ( len - ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) );
452: DBGC2 ( aoedev, "AoE %s/%08x ATA rsp %02x in %04zx\n",
453: aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat,
454: data_len );
455:
456: /* Check for command failure */
457: if ( aoeata->cmd_stat & ATA_STAT_ERR ) {
458: DBGC ( aoedev, "AoE %s/%08x status %02x\n",
459: aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat );
460: return -EIO;
461: }
462:
463: /* Check data-in length is sufficient. (There may be trailing
464: * garbage due to Ethernet minimum-frame-size padding.)
465: */
466: if ( data_len < command->data_in_len ) {
467: DBGC ( aoedev, "AoE %s/%08x data-in underrun (received %zd, "
468: "expected %zd)\n", aoedev_name ( aoedev ), aoecmd->tag,
469: data_len, command->data_in_len );
470: return -ERANGE;
471: }
472:
473: /* Copy out data payload */
474: copy_to_user ( command->data_in, 0, aoeata->data,
475: command->data_in_len );
476:
477: return 0;
478: }
479:
480: /** AoE ATA command */
481: static struct aoe_command_type aoecmd_ata = {
482: .cmd_len = aoecmd_ata_cmd_len,
483: .cmd = aoecmd_ata_cmd,
484: .rsp = aoecmd_ata_rsp,
485: };
486:
487: /**
488: * Calculate length of AoE configuration command IU
489: *
490: * @v aoecmd AoE command
491: * @ret len Length of command IU
492: */
493: static size_t aoecmd_cfg_cmd_len ( struct aoe_command *aoecmd __unused ) {
494: return ( sizeof ( struct aoehdr ) + sizeof ( struct aoecfg ) );
495: }
496:
497: /**
498: * Build AoE configuration command IU
499: *
500: * @v aoecmd AoE command
501: * @v data Command IU
502: * @v len Length of command IU
503: */
504: static void aoecmd_cfg_cmd ( struct aoe_command *aoecmd,
505: void *data, size_t len ) {
506: struct aoe_device *aoedev = aoecmd->aoedev;
507: struct aoehdr *aoehdr = data;
508: struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
509:
510: /* Sanity check */
511: assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) );
512:
513: /* Build IU */
514: aoehdr->command = AOE_CMD_CONFIG;
515: memset ( aoecfg, 0, sizeof ( *aoecfg ) );
516:
517: DBGC ( aoedev, "AoE %s/%08x CONFIG cmd\n",
518: aoedev_name ( aoedev ), aoecmd->tag );
519: }
520:
521: /**
522: * Handle AoE configuration response IU
523: *
524: * @v aoecmd AoE command
525: * @v data Response IU
526: * @v len Length of response IU
527: * @v ll_source Link-layer source address
528: * @ret rc Return status code
529: */
530: static int aoecmd_cfg_rsp ( struct aoe_command *aoecmd, const void *data,
531: size_t len, const void *ll_source ) {
532: struct aoe_device *aoedev = aoecmd->aoedev;
533: struct ll_protocol *ll_protocol = aoedev->netdev->ll_protocol;
534: const struct aoehdr *aoehdr = data;
535: const struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
536:
537: /* Sanity check */
538: if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) ) {
539: DBGC ( aoedev, "AoE %s/%08x received underlength "
540: "configuration response (%zd bytes)\n",
541: aoedev_name ( aoedev ), aoecmd->tag, len );
542: return -EINVAL;
543: }
544: DBGC ( aoedev, "AoE %s/%08x CONFIG rsp buf %04x fw %04x scnt %02x\n",
545: aoedev_name ( aoedev ), aoecmd->tag, ntohs ( aoecfg->bufcnt ),
546: aoecfg->fwver, aoecfg->scnt );
547:
548: /* Record target MAC address */
549: memcpy ( aoedev->target, ll_source, ll_protocol->ll_addr_len );
550: DBGC ( aoedev, "AoE %s has MAC address %s\n",
551: aoedev_name ( aoedev ), ll_protocol->ntoa ( aoedev->target ) );
552:
553: return 0;
554: }
555:
556: /** AoE configuration command */
557: static struct aoe_command_type aoecmd_cfg = {
558: .cmd_len = aoecmd_cfg_cmd_len,
559: .cmd = aoecmd_cfg_cmd,
560: .rsp = aoecmd_cfg_rsp,
561: };
562:
563: /** AoE command ATA interface operations */
564: static struct interface_operation aoecmd_ata_op[] = {
565: INTF_OP ( intf_close, struct aoe_command *, aoecmd_close ),
566: };
567:
568: /** AoE command ATA interface descriptor */
569: static struct interface_descriptor aoecmd_ata_desc =
570: INTF_DESC ( struct aoe_command, ata, aoecmd_ata_op );
571:
572: /**
573: * Identify AoE command by tag
574: *
575: * @v tag Command tag
576: * @ret aoecmd AoE command, or NULL
577: */
578: static struct aoe_command * aoecmd_find_tag ( uint32_t tag ) {
579: struct aoe_command *aoecmd;
580:
581: list_for_each_entry ( aoecmd, &aoe_commands, list ) {
582: if ( aoecmd->tag == tag )
583: return aoecmd;
584: }
585: return NULL;
586: }
587:
588: /**
589: * Choose an AoE command tag
590: *
591: * @ret tag New tag, or negative error
592: */
593: static int aoecmd_new_tag ( void ) {
594: static uint16_t tag_idx;
595: unsigned int i;
596:
597: for ( i = 0 ; i < 65536 ; i++ ) {
598: tag_idx++;
599: if ( aoecmd_find_tag ( tag_idx ) == NULL )
600: return ( AOE_TAG_MAGIC | tag_idx );
601: }
602: return -EADDRINUSE;
603: }
604:
605: /**
606: * Create AoE command
607: *
608: * @v aoedev AoE device
609: * @v type AoE command type
610: * @ret aoecmd AoE command
611: */
612: static struct aoe_command * aoecmd_create ( struct aoe_device *aoedev,
613: struct aoe_command_type *type ) {
614: struct aoe_command *aoecmd;
615: int tag;
616:
617: /* Allocate command tag */
618: tag = aoecmd_new_tag();
619: if ( tag < 0 )
620: return NULL;
621:
622: /* Allocate and initialise structure */
623: aoecmd = zalloc ( sizeof ( *aoecmd ) );
624: if ( ! aoecmd )
625: return NULL;
626: ref_init ( &aoecmd->refcnt, aoecmd_free );
627: list_add ( &aoecmd->list, &aoe_commands );
628: intf_init ( &aoecmd->ata, &aoecmd_ata_desc, &aoecmd->refcnt );
629: timer_init ( &aoecmd->timer, aoecmd_expired, &aoecmd->refcnt );
630: aoecmd->aoedev = aoedev_get ( aoedev );
631: aoecmd->type = type;
632: aoecmd->tag = tag;
633:
634: /* Preserve timeout from last completed command */
635: aoecmd->timer.timeout = aoedev->timeout;
636:
637: /* Return already mortalised. (Reference is held by command list.) */
638: return aoecmd;
639: }
640:
641: /**
642: * Issue AoE ATA command
643: *
644: * @v aoedev AoE device
645: * @v parent Parent interface
646: * @v command ATA command
647: * @ret tag Command tag, or negative error
648: */
649: static int aoedev_ata_command ( struct aoe_device *aoedev,
650: struct interface *parent,
651: struct ata_cmd *command ) {
652: struct net_device *netdev = aoedev->netdev;
653: struct aoe_command *aoecmd;
654:
655: /* Fail immediately if net device is closed */
656: if ( ! netdev_is_open ( netdev ) ) {
657: DBGC ( aoedev, "AoE %s cannot issue command while net device "
658: "is closed\n", aoedev_name ( aoedev ) );
659: return -EWOULDBLOCK;
660: }
661:
662: /* Create command */
663: aoecmd = aoecmd_create ( aoedev, &aoecmd_ata );
664: if ( ! aoecmd )
665: return -ENOMEM;
666: memcpy ( &aoecmd->command, command, sizeof ( aoecmd->command ) );
667:
668: /* Attempt to send command. Allow failures to be handled by
669: * the retry timer.
670: */
671: aoecmd_tx ( aoecmd );
672:
673: /* Attach to parent interface, leave reference with command
674: * list, and return.
675: */
676: intf_plug_plug ( &aoecmd->ata, parent );
677: return aoecmd->tag;
678: }
679:
680: /**
681: * Issue AoE configuration command
682: *
683: * @v aoedev AoE device
684: * @v parent Parent interface
685: * @ret tag Command tag, or negative error
686: */
687: static int aoedev_cfg_command ( struct aoe_device *aoedev,
688: struct interface *parent ) {
689: struct aoe_command *aoecmd;
690:
691: /* Create command */
692: aoecmd = aoecmd_create ( aoedev, &aoecmd_cfg );
693: if ( ! aoecmd )
694: return -ENOMEM;
695:
696: /* Attempt to send command. Allow failures to be handled by
697: * the retry timer.
698: */
699: aoecmd_tx ( aoecmd );
700:
701: /* Attach to parent interface, leave reference with command
702: * list, and return.
703: */
704: intf_plug_plug ( &aoecmd->ata, parent );
705: return aoecmd->tag;
706: }
707:
708: /**
709: * Free AoE device
710: *
711: * @v refcnt Reference count
712: */
713: static void aoedev_free ( struct refcnt *refcnt ) {
714: struct aoe_device *aoedev =
715: container_of ( refcnt, struct aoe_device, refcnt );
716:
717: netdev_put ( aoedev->netdev );
718: free ( aoedev );
719: }
720:
721: /**
722: * Close AoE device
723: *
724: * @v aoedev AoE device
725: * @v rc Reason for close
726: */
727: static void aoedev_close ( struct aoe_device *aoedev, int rc ) {
728: struct aoe_command *aoecmd;
729: struct aoe_command *tmp;
730:
731: /* Shut down interfaces */
732: intf_shutdown ( &aoedev->ata, rc );
733: intf_shutdown ( &aoedev->config, rc );
734:
735: /* Shut down any active commands */
736: list_for_each_entry_safe ( aoecmd, tmp, &aoe_commands, list ) {
737: if ( aoecmd->aoedev != aoedev )
738: continue;
739: aoecmd_get ( aoecmd );
740: aoecmd_close ( aoecmd, rc );
741: aoecmd_put ( aoecmd );
742: }
743: }
744:
745: /**
746: * Check AoE device flow-control window
747: *
748: * @v aoedev AoE device
749: * @ret len Length of window
750: */
751: static size_t aoedev_window ( struct aoe_device *aoedev ) {
752: return ( aoedev->configured ? ~( ( size_t ) 0 ) : 0 );
753: }
754:
755: /**
756: * Handle AoE device configuration completion
757: *
758: * @v aoedev AoE device
759: * @v rc Reason for completion
760: */
761: static void aoedev_config_done ( struct aoe_device *aoedev, int rc ) {
762:
763: /* Shut down interface */
764: intf_shutdown ( &aoedev->config, rc );
765:
766: /* Close device on failure */
767: if ( rc != 0 ) {
768: aoedev_close ( aoedev, rc );
769: return;
770: }
771:
772: /* Mark device as configured */
773: aoedev->configured = 1;
774: xfer_window_changed ( &aoedev->ata );
775: }
776:
777: /**
778: * Identify device underlying AoE device
779: *
780: * @v aoedev AoE device
781: * @ret device Underlying device
782: */
783: static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) {
784: return aoedev->netdev->dev;
785: }
786:
787: /**
788: * Describe AoE device in an ACPI table
789: *
790: * @v aoedev AoE device
791: * @v acpi ACPI table
792: * @v len Length of ACPI table
793: * @ret rc Return status code
794: */
795: static int aoedev_describe ( struct aoe_device *aoedev,
796: struct acpi_description_header *acpi,
797: size_t len ) {
798: struct abft_table *abft =
799: container_of ( acpi, struct abft_table, acpi );
800:
801: /* Sanity check */
802: if ( len < sizeof ( *abft ) )
803: return -ENOBUFS;
804:
805: /* Populate table */
806: abft->acpi.signature = cpu_to_le32 ( ABFT_SIG );
807: abft->acpi.length = cpu_to_le32 ( sizeof ( *abft ) );
808: abft->acpi.revision = 1;
809: abft->shelf = cpu_to_le16 ( aoedev->major );
810: abft->slot = aoedev->minor;
811: memcpy ( abft->mac, aoedev->netdev->ll_addr, sizeof ( abft->mac ) );
812:
813: return 0;
814: }
815:
816: /** AoE device ATA interface operations */
817: static struct interface_operation aoedev_ata_op[] = {
818: INTF_OP ( ata_command, struct aoe_device *, aoedev_ata_command ),
819: INTF_OP ( xfer_window, struct aoe_device *, aoedev_window ),
820: INTF_OP ( intf_close, struct aoe_device *, aoedev_close ),
821: INTF_OP ( acpi_describe, struct aoe_device *, aoedev_describe ),
822: INTF_OP ( identify_device, struct aoe_device *,
823: aoedev_identify_device ),
824: };
825:
826: /** AoE device ATA interface descriptor */
827: static struct interface_descriptor aoedev_ata_desc =
828: INTF_DESC ( struct aoe_device, ata, aoedev_ata_op );
829:
830: /** AoE device configuration interface operations */
831: static struct interface_operation aoedev_config_op[] = {
832: INTF_OP ( intf_close, struct aoe_device *, aoedev_config_done ),
833: };
834:
835: /** AoE device configuration interface descriptor */
836: static struct interface_descriptor aoedev_config_desc =
837: INTF_DESC ( struct aoe_device, config, aoedev_config_op );
838:
839: /**
840: * Open AoE device
841: *
842: * @v parent Parent interface
843: * @v netdev Network device
844: * @v major Device major number
845: * @v minor Device minor number
846: * @ret rc Return status code
847: */
848: static int aoedev_open ( struct interface *parent, struct net_device *netdev,
849: unsigned int major, unsigned int minor ) {
850: struct aoe_device *aoedev;
851: int rc;
852:
853: /* Allocate and initialise structure */
854: aoedev = zalloc ( sizeof ( *aoedev ) );
855: if ( ! aoedev ) {
856: rc = -ENOMEM;
857: goto err_zalloc;
858: }
859: ref_init ( &aoedev->refcnt, aoedev_free );
860: intf_init ( &aoedev->ata, &aoedev_ata_desc, &aoedev->refcnt );
861: intf_init ( &aoedev->config, &aoedev_config_desc, &aoedev->refcnt );
862: aoedev->netdev = netdev_get ( netdev );
863: aoedev->major = major;
864: aoedev->minor = minor;
865: memcpy ( aoedev->target, netdev->ll_broadcast,
866: netdev->ll_protocol->ll_addr_len );
867:
868: /* Initiate configuration */
869: if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
870: DBGC ( aoedev, "AoE %s could not initiate configuration: %s\n",
871: aoedev_name ( aoedev ), strerror ( rc ) );
872: goto err_config;
873: }
874:
875: /* Attach ATA device to parent interface */
876: if ( ( rc = ata_open ( parent, &aoedev->ata, ATA_DEV_MASTER,
877: AOE_MAX_COUNT ) ) != 0 ) {
878: DBGC ( aoedev, "AoE %s could not create ATA device: %s\n",
879: aoedev_name ( aoedev ), strerror ( rc ) );
880: goto err_ata_open;
881: }
882:
883: /* Mortalise self and return */
884: ref_put ( &aoedev->refcnt );
885: return 0;
886:
887: err_ata_open:
888: err_config:
889: aoedev_close ( aoedev, rc );
890: ref_put ( &aoedev->refcnt );
891: err_zalloc:
892: return rc;
893: }
894:
895: /******************************************************************************
896: *
897: * AoE network protocol
898: *
899: ******************************************************************************
900: */
901:
902: /**
903: * Process incoming AoE packets
904: *
905: * @v iobuf I/O buffer
906: * @v netdev Network device
907: * @v ll_dest Link-layer destination address
908: * @v ll_source Link-layer source address
909: * @ret rc Return status code
910: *
911: */
912: static int aoe_rx ( struct io_buffer *iobuf,
913: struct net_device *netdev __unused,
914: const void *ll_dest __unused,
915: const void *ll_source ) {
916: struct aoehdr *aoehdr = iobuf->data;
917: struct aoe_command *aoecmd;
918: int rc;
919:
920: /* Sanity check */
921: if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
922: DBG ( "AoE received underlength packet (%zd bytes)\n",
923: iob_len ( iobuf ) );
924: rc = -EINVAL;
925: goto err_sanity;
926: }
927: if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
928: DBG ( "AoE received packet for unsupported protocol version "
929: "%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
930: rc = -EPROTONOSUPPORT;
931: goto err_sanity;
932: }
933: if ( ! ( aoehdr->ver_flags & AOE_FL_RESPONSE ) ) {
934: DBG ( "AoE received request packet\n" );
935: rc = -EOPNOTSUPP;
936: goto err_sanity;
937: }
938:
939: /* Demultiplex amongst active AoE commands */
940: aoecmd = aoecmd_find_tag ( ntohl ( aoehdr->tag ) );
941: if ( ! aoecmd ) {
942: DBG ( "AoE received packet for unused tag %08x\n",
943: ntohl ( aoehdr->tag ) );
944: rc = -ENOENT;
945: goto err_demux;
946: }
947:
948: /* Pass received frame to command */
949: aoecmd_get ( aoecmd );
950: if ( ( rc = aoecmd_rx ( aoecmd, iob_disown ( iobuf ),
951: ll_source ) ) != 0 )
952: goto err_rx;
953:
954: err_rx:
955: aoecmd_put ( aoecmd );
956: err_demux:
957: err_sanity:
958: free_iob ( iobuf );
959: return rc;
960: }
961:
962: /** AoE protocol */
963: struct net_protocol aoe_protocol __net_protocol = {
964: .name = "AoE",
965: .net_proto = htons ( ETH_P_AOE ),
966: .rx = aoe_rx,
967: };
968:
969: /******************************************************************************
970: *
971: * AoE URIs
972: *
973: ******************************************************************************
974: */
975:
976: /**
977: * Parse AoE URI
978: *
979: * @v uri URI
980: * @ret major Major device number
981: * @ret minor Minor device number
982: * @ret rc Return status code
983: *
984: * An AoE URI has the form "aoe:e<major>.<minor>".
985: */
986: static int aoe_parse_uri ( struct uri *uri, unsigned int *major,
987: unsigned int *minor ) {
988: const char *ptr;
989: char *end;
990:
991: /* Check for URI with opaque portion */
992: if ( ! uri->opaque )
993: return -EINVAL;
994: ptr = uri->opaque;
995:
996: /* Check for initial 'e' */
997: if ( *ptr != 'e' )
998: return -EINVAL;
999: ptr++;
1000:
1001: /* Parse major device number */
1002: *major = strtoul ( ptr, &end, 10 );
1003: if ( *end != '.' )
1004: return -EINVAL;
1005: ptr = ( end + 1 );
1006:
1007: /* Parse minor device number */
1008: *minor = strtoul ( ptr, &end, 10 );
1009: if ( *end )
1010: return -EINVAL;
1011:
1012: return 0;
1013: }
1014:
1015: /**
1016: * Open AoE URI
1017: *
1018: * @v parent Parent interface
1019: * @v uri URI
1020: * @ret rc Return status code
1021: */
1022: static int aoe_open ( struct interface *parent, struct uri *uri ) {
1023: struct net_device *netdev;
1024: unsigned int major;
1025: unsigned int minor;
1026: int rc;
1027:
1028: /* Identify network device. This is something of a hack, but
1029: * the AoE URI scheme that has been in use for some time now
1030: * provides no way to specify a particular device.
1031: */
1032: netdev = last_opened_netdev();
1033: if ( ! netdev ) {
1034: DBG ( "AoE cannot identify network device\n" );
1035: return -ENODEV;
1036: }
1037:
1038: /* Parse URI */
1039: if ( ( rc = aoe_parse_uri ( uri, &major, &minor ) ) != 0 ) {
1040: DBG ( "AoE cannot parse URI\n" );
1041: return rc;
1042: }
1043:
1044: /* Open AoE device */
1045: if ( ( rc = aoedev_open ( parent, netdev, major, minor ) ) != 0 )
1046: return rc;
1047:
1048: return 0;
1049: }
1050:
1051: /** AoE URI opener */
1052: struct uri_opener aoe_uri_opener __uri_opener = {
1053: .scheme = "aoe",
1054: .open = aoe_open,
1055: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.